diff --git a/404.html b/404.html index eacb5725..bb2dc430 100644 --- a/404.html +++ b/404.html @@ -229,6 +229,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/api/examples.html b/api/examples.html index 68cee6e5..dfecbef9 100644 --- a/api/examples.html +++ b/api/examples.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/api/guide.html b/api/guide.html index 99cd948b..bd7c72ab 100644 --- a/api/guide.html +++ b/api/guide.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/api/reference.html b/api/reference.html index 6660f5b2..60a564be 100644 --- a/api/reference.html +++ b/api/reference.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1191,74 +1219,7 @@ address[0] is the LSB of the address, address[5] is the MSB.

    Source code in bumble/hci.py -
    1607
    -1608
    -1609
    -1610
    -1611
    -1612
    -1613
    -1614
    -1615
    -1616
    -1617
    -1618
    -1619
    -1620
    -1621
    -1622
    -1623
    -1624
    -1625
    -1626
    -1627
    -1628
    -1629
    -1630
    -1631
    -1632
    -1633
    -1634
    -1635
    -1636
    -1637
    -1638
    -1639
    -1640
    -1641
    -1642
    -1643
    -1644
    -1645
    -1646
    -1647
    -1648
    -1649
    -1650
    -1651
    -1652
    -1653
    -1654
    -1655
    -1656
    -1657
    -1658
    -1659
    -1660
    -1661
    -1662
    -1663
    -1664
    -1665
    -1666
    -1667
    -1668
    -1669
    -1670
    -1671
    -1672
    -1673
    -1674
    +          
    1674
     1675
     1676
     1677
    @@ -1292,251 +1253,11 @@ address[0] is the LSB of the address, address[5] is the MSB.

    1705 1706 1707 -1708
    class Address:
    -    '''
    -    Bluetooth Address (see Bluetooth spec Vol 6, Part B - 1.3 DEVICE ADDRESS)
    -    NOTE: the address bytes are stored in little-endian byte order here, so
    -    address[0] is the LSB of the address, address[5] is the MSB.
    -    '''
    -
    -    PUBLIC_DEVICE_ADDRESS   = 0x00
    -    RANDOM_DEVICE_ADDRESS   = 0x01
    -    PUBLIC_IDENTITY_ADDRESS = 0x02
    -    RANDOM_IDENTITY_ADDRESS = 0x03
    -
    -    ADDRESS_TYPE_NAMES = {
    -        PUBLIC_DEVICE_ADDRESS:   'PUBLIC_DEVICE_ADDRESS',
    -        RANDOM_DEVICE_ADDRESS:   'RANDOM_DEVICE_ADDRESS',
    -        PUBLIC_IDENTITY_ADDRESS: 'PUBLIC_IDENTITY_ADDRESS',
    -        RANDOM_IDENTITY_ADDRESS: 'RANDOM_IDENTITY_ADDRESS'
    -    }
    -
    -    ADDRESS_TYPE_SPEC = {'size': 1, 'mapper': lambda x: Address.address_type_name(x)}
    -
    -    @staticmethod
    -    def address_type_name(address_type):
    -        return name_or_number(Address.ADDRESS_TYPE_NAMES, address_type)
    -
    -    @staticmethod
    -    def parse_address(data, offset):
    -        # Fix the type to a default value. This is used for parsing type-less Classic addresses
    -        return Address.parse_address_with_type(data, offset, Address.PUBLIC_DEVICE_ADDRESS)
    -
    -    @staticmethod
    -    def parse_address_with_type(data, offset, address_type):
    -        return offset + 6, Address(data[offset:offset + 6], address_type)
    -
    -    @staticmethod
    -    def parse_address_preceded_by_type(data, offset):
    -        address_type = data[offset - 1]
    -        return Address.parse_address_with_type(data, offset, address_type)
    -
    -    def __init__(self, address, address_type = RANDOM_DEVICE_ADDRESS):
    -        '''
    -        Initialize an instance. `address` may be a byte array in little-endian
    -        format, or a hex string in big-endian format (with optional ':'
    -        separators between the bytes).
    -        If the address is a string suffixed with '/P', `address_type` is ignored and the type
    -        is set to PUBLIC_DEVICE_ADDRESS.
    -        '''
    -        if type(address) is bytes:
    -            self.address_bytes = address
    -        else:
    -            # Check if there's a '/P' type specifier
    -            if address.endswith('P'):
    -                address_type = Address.PUBLIC_DEVICE_ADDRESS
    -                address = address[:-2]
    -
    -            if len(address) == 12 + 5:
    -                # Form with ':' separators
    -                address = address.replace(':', '')
    -            self.address_bytes = bytes(reversed(bytes.fromhex(address)))
    -
    -        if len(self.address_bytes) != 6:
    -            raise ValueError('invalid address length')
    -
    -        self.address_type = address_type
    -
    -    @property
    -    def is_public(self):
    -        return self.address_type == self.PUBLIC_DEVICE_ADDRESS or self.address_type == self.PUBLIC_IDENTITY_ADDRESS
    -
    -    @property
    -    def is_random(self):
    -        return not self.is_public
    -
    -    @property
    -    def is_resolved(self):
    -        return self.address_type == self.PUBLIC_IDENTITY_ADDRESS or self.address_type == self.RANDOM_IDENTITY_ADDRESS
    -
    -    @property
    -    def is_resolvable(self):
    -        return self.address_type == self.RANDOM_DEVICE_ADDRESS and (self.address_bytes[5] >> 6 == 1)
    -
    -    @property
    -    def is_static(self):
    -        return self.is_random and (self.address_bytes[5] >> 6 == 3)
    -
    -    def to_bytes(self):
    -        return self.address_bytes
    -
    -    def __bytes__(self):
    -        return self.to_bytes()
    -
    -    def __hash__(self):
    -        return hash(self.address_bytes)
    -
    -    def __eq__(self, other):
    -        return self.address_bytes == other.address_bytes and self.is_public == other.is_public
    -
    -    def __str__(self):
    -        '''
    -        String representation of the address, MSB first
    -        '''
    -        return ':'.join([f'{x:02X}' for x in reversed(self.address_bytes)])
    -
    - - - - -
    - - - - - - - - - -
    - - - -

    -__init__(address, address_type=RANDOM_DEVICE_ADDRESS) - -

    - - -
    - -

    Initialize an instance. address may be a byte array in little-endian -format, or a hex string in big-endian format (with optional ':' -separators between the bytes). -If the address is a string suffixed with '/P', address_type is ignored and the type -is set to PUBLIC_DEVICE_ADDRESS.

    - -
    - Source code in bumble/hci.py -
    1646
    -1647
    -1648
    -1649
    -1650
    -1651
    -1652
    -1653
    -1654
    -1655
    -1656
    -1657
    -1658
    -1659
    -1660
    -1661
    -1662
    -1663
    -1664
    -1665
    -1666
    -1667
    -1668
    -1669
    -1670
    def __init__(self, address, address_type = RANDOM_DEVICE_ADDRESS):
    -    '''
    -    Initialize an instance. `address` may be a byte array in little-endian
    -    format, or a hex string in big-endian format (with optional ':'
    -    separators between the bytes).
    -    If the address is a string suffixed with '/P', `address_type` is ignored and the type
    -    is set to PUBLIC_DEVICE_ADDRESS.
    -    '''
    -    if type(address) is bytes:
    -        self.address_bytes = address
    -    else:
    -        # Check if there's a '/P' type specifier
    -        if address.endswith('P'):
    -            address_type = Address.PUBLIC_DEVICE_ADDRESS
    -            address = address[:-2]
    -
    -        if len(address) == 12 + 5:
    -            # Form with ':' separators
    -            address = address.replace(':', '')
    -        self.address_bytes = bytes(reversed(bytes.fromhex(address)))
    -
    -    if len(self.address_bytes) != 6:
    -        raise ValueError('invalid address length')
    -
    -    self.address_type = address_type
    -
    -
    -
    - -
    - -
    - - - -

    -__str__() - -

    - - -
    - -

    String representation of the address, MSB first

    - -
    - Source code in bumble/hci.py -
    1704
    -1705
    -1706
    -1707
    -1708
    def __str__(self):
    -    '''
    -    String representation of the address, MSB first
    -    '''
    -    return ':'.join([f'{x:02X}' for x in reversed(self.address_bytes)])
    -
    -
    -
    - -
    - - - -
    - -
    - -

    HCI_Packet

    - - -
    - - - -
    - - -

    Abstract Base class for HCI packets

    - - -
    - Source code in bumble/hci.py -
    1712
    +1708
    +1709
    +1710
    +1711
    +1712
     1713
     1714
     1715
    @@ -1557,68 +1278,19 @@ is set to PUBLIC_DEVICE_ADDRESS.

    1730 1731 1732 -1733
    class HCI_Packet:
    -    '''
    -    Abstract Base class for HCI packets
    -    '''
    -
    -    @staticmethod
    -    def from_bytes(packet):
    -        packet_type = packet[0]
    -        if packet_type == HCI_COMMAND_PACKET:
    -            return HCI_Command.from_bytes(packet)
    -        elif packet_type == HCI_ACL_DATA_PACKET:
    -            return HCI_AclDataPacket.from_bytes(packet)
    -        elif packet_type == HCI_EVENT_PACKET:
    -            return HCI_Event.from_bytes(packet)
    -        else:
    -            return HCI_CustomPacket(packet)
    -
    -    def __init__(self, name):
    -        self.name = name
    -
    -    def __repr__(self) -> str:
    -        return self.name
    -
    -
    - - - -
    - - - - - - - - - - - -
    - -
    - -

    HCI Commands

    -

    HCI_Command

    - - -
    - - - -
    -

    - Bases: HCI_Packet

    - - -

    See Bluetooth spec @ Vol 2, Part E - 5.4.1 HCI Command Packet

    - - -
    - Source code in bumble/hci.py -
    1745
    +1733
    +1734
    +1735
    +1736
    +1737
    +1738
    +1739
    +1740
    +1741
    +1742
    +1743
    +1744
    +1745
     1746
     1747
     1748
    @@ -1677,46 +1349,479 @@ is set to PUBLIC_DEVICE_ADDRESS.

    1801 1802 1803 -1804 -1805 -1806 -1807 -1808 -1809 -1810 -1811 -1812 -1813 -1814 -1815 -1816 -1817 -1818 -1819 -1820 -1821 -1822 -1823 -1824 -1825 -1826 -1827 -1828 -1829 -1830 -1831 -1832 -1833 -1834 -1835
    class HCI_Command(HCI_Packet):
    +1804
    class Address:
    +    '''
    +    Bluetooth Address (see Bluetooth spec Vol 6, Part B - 1.3 DEVICE ADDRESS)
    +    NOTE: the address bytes are stored in little-endian byte order here, so
    +    address[0] is the LSB of the address, address[5] is the MSB.
    +    '''
    +
    +    PUBLIC_DEVICE_ADDRESS = 0x00
    +    RANDOM_DEVICE_ADDRESS = 0x01
    +    PUBLIC_IDENTITY_ADDRESS = 0x02
    +    RANDOM_IDENTITY_ADDRESS = 0x03
    +
    +    ADDRESS_TYPE_NAMES = {
    +        PUBLIC_DEVICE_ADDRESS: 'PUBLIC_DEVICE_ADDRESS',
    +        RANDOM_DEVICE_ADDRESS: 'RANDOM_DEVICE_ADDRESS',
    +        PUBLIC_IDENTITY_ADDRESS: 'PUBLIC_IDENTITY_ADDRESS',
    +        RANDOM_IDENTITY_ADDRESS: 'RANDOM_IDENTITY_ADDRESS',
    +    }
    +
    +    # pylint: disable-next=unnecessary-lambda
    +    ADDRESS_TYPE_SPEC = {'size': 1, 'mapper': lambda x: Address.address_type_name(x)}
    +
    +    @staticmethod
    +    def address_type_name(address_type):
    +        return name_or_number(Address.ADDRESS_TYPE_NAMES, address_type)
    +
    +    @staticmethod
    +    def from_string_for_transport(string, transport):
    +        if transport == BT_BR_EDR_TRANSPORT:
    +            address_type = Address.PUBLIC_DEVICE_ADDRESS
    +        else:
    +            address_type = Address.RANDOM_DEVICE_ADDRESS
    +        return Address(string, address_type)
    +
    +    @staticmethod
    +    def parse_address(data, offset):
    +        # Fix the type to a default value. This is used for parsing type-less Classic
    +        # addresses
    +        return Address.parse_address_with_type(
    +            data, offset, Address.PUBLIC_DEVICE_ADDRESS
    +        )
    +
    +    @staticmethod
    +    def parse_address_with_type(data, offset, address_type):
    +        return offset + 6, Address(data[offset : offset + 6], address_type)
    +
    +    @staticmethod
    +    def parse_address_preceded_by_type(data, offset):
    +        address_type = data[offset - 1]
    +        return Address.parse_address_with_type(data, offset, address_type)
    +
    +    def __init__(self, address, address_type=RANDOM_DEVICE_ADDRESS):
    +        '''
    +        Initialize an instance. `address` may be a byte array in little-endian
    +        format, or a hex string in big-endian format (with optional ':'
    +        separators between the bytes).
    +        If the address is a string suffixed with '/P', `address_type` is ignored and
    +        the type is set to PUBLIC_DEVICE_ADDRESS.
    +        '''
    +        if isinstance(address, bytes):
    +            self.address_bytes = address
    +        else:
    +            # Check if there's a '/P' type specifier
    +            if address.endswith('P'):
    +                address_type = Address.PUBLIC_DEVICE_ADDRESS
    +                address = address[:-2]
    +
    +            if len(address) == 12 + 5:
    +                # Form with ':' separators
    +                address = address.replace(':', '')
    +            self.address_bytes = bytes(reversed(bytes.fromhex(address)))
    +
    +        if len(self.address_bytes) != 6:
    +            raise ValueError('invalid address length')
    +
    +        self.address_type = address_type
    +
    +    def clone(self):
    +        return Address(self.address_bytes, self.address_type)
    +
    +    @property
    +    def is_public(self):
    +        return self.address_type in (
    +            self.PUBLIC_DEVICE_ADDRESS,
    +            self.PUBLIC_IDENTITY_ADDRESS,
    +        )
    +
    +    @property
    +    def is_random(self):
    +        return not self.is_public
    +
    +    @property
    +    def is_resolved(self):
    +        return self.address_type in (
    +            self.PUBLIC_IDENTITY_ADDRESS,
    +            self.RANDOM_IDENTITY_ADDRESS,
    +        )
    +
    +    @property
    +    def is_resolvable(self):
    +        return self.address_type == self.RANDOM_DEVICE_ADDRESS and (
    +            self.address_bytes[5] >> 6 == 1
    +        )
    +
    +    @property
    +    def is_static(self):
    +        return self.is_random and (self.address_bytes[5] >> 6 == 3)
    +
    +    def to_bytes(self):
    +        return self.address_bytes
    +
    +    def __bytes__(self):
    +        return self.to_bytes()
    +
    +    def __hash__(self):
    +        return hash(self.address_bytes)
    +
    +    def __eq__(self, other):
    +        return (
    +            self.address_bytes == other.address_bytes
    +            and self.is_public == other.is_public
    +        )
    +
    +    def __str__(self):
    +        '''
    +        String representation of the address, MSB first
    +        '''
    +        result = ':'.join([f'{x:02X}' for x in reversed(self.address_bytes)])
    +        if not self.is_public:
    +            return result
    +        return result + '/P'
    +
    +
    + + + +
    + + + + + + + + + +
    + + + +

    +__init__(address, address_type=RANDOM_DEVICE_ADDRESS) + +

    + + +
    + +

    Initialize an instance. address may be a byte array in little-endian +format, or a hex string in big-endian format (with optional ':' +separators between the bytes). +If the address is a string suffixed with '/P', address_type is ignored and +the type is set to PUBLIC_DEVICE_ADDRESS.

    + +
    + Source code in bumble/hci.py +
    1725
    +1726
    +1727
    +1728
    +1729
    +1730
    +1731
    +1732
    +1733
    +1734
    +1735
    +1736
    +1737
    +1738
    +1739
    +1740
    +1741
    +1742
    +1743
    +1744
    +1745
    +1746
    +1747
    +1748
    +1749
    def __init__(self, address, address_type=RANDOM_DEVICE_ADDRESS):
    +    '''
    +    Initialize an instance. `address` may be a byte array in little-endian
    +    format, or a hex string in big-endian format (with optional ':'
    +    separators between the bytes).
    +    If the address is a string suffixed with '/P', `address_type` is ignored and
    +    the type is set to PUBLIC_DEVICE_ADDRESS.
    +    '''
    +    if isinstance(address, bytes):
    +        self.address_bytes = address
    +    else:
    +        # Check if there's a '/P' type specifier
    +        if address.endswith('P'):
    +            address_type = Address.PUBLIC_DEVICE_ADDRESS
    +            address = address[:-2]
    +
    +        if len(address) == 12 + 5:
    +            # Form with ':' separators
    +            address = address.replace(':', '')
    +        self.address_bytes = bytes(reversed(bytes.fromhex(address)))
    +
    +    if len(self.address_bytes) != 6:
    +        raise ValueError('invalid address length')
    +
    +    self.address_type = address_type
    +
    +
    +
    + +
    + +
    + + + +

    +__str__() + +

    + + +
    + +

    String representation of the address, MSB first

    + +
    + Source code in bumble/hci.py +
    1797
    +1798
    +1799
    +1800
    +1801
    +1802
    +1803
    +1804
    def __str__(self):
    +    '''
    +    String representation of the address, MSB first
    +    '''
    +    result = ':'.join([f'{x:02X}' for x in reversed(self.address_bytes)])
    +    if not self.is_public:
    +        return result
    +    return result + '/P'
    +
    +
    +
    + +
    + + + +
    + +
    + +

    HCI_Packet

    + + +
    + + + +
    + + +

    Abstract Base class for HCI packets

    + + +
    + Source code in bumble/hci.py +
    1834
    +1835
    +1836
    +1837
    +1838
    +1839
    +1840
    +1841
    +1842
    +1843
    +1844
    +1845
    +1846
    +1847
    +1848
    +1849
    +1850
    +1851
    +1852
    +1853
    +1854
    +1855
    +1856
    +1857
    +1858
    class HCI_Packet:
    +    '''
    +    Abstract Base class for HCI packets
    +    '''
    +
    +    @staticmethod
    +    def from_bytes(packet):
    +        packet_type = packet[0]
    +
    +        if packet_type == HCI_COMMAND_PACKET:
    +            return HCI_Command.from_bytes(packet)
    +
    +        if packet_type == HCI_ACL_DATA_PACKET:
    +            return HCI_AclDataPacket.from_bytes(packet)
    +
    +        if packet_type == HCI_EVENT_PACKET:
    +            return HCI_Event.from_bytes(packet)
    +
    +        return HCI_CustomPacket(packet)
    +
    +    def __init__(self, name):
    +        self.name = name
    +
    +    def __repr__(self) -> str:
    +        return self.name
    +
    +
    + + + +
    + + + + + + + + + + + +
    + +
    + +

    HCI Commands

    +

    HCI_Command

    + + +
    + + + +
    +

    + Bases: HCI_Packet

    + + +

    See Bluetooth spec @ Vol 2, Part E - 5.4.1 HCI Command Packet

    + + +
    + Source code in bumble/hci.py +
    1870
    +1871
    +1872
    +1873
    +1874
    +1875
    +1876
    +1877
    +1878
    +1879
    +1880
    +1881
    +1882
    +1883
    +1884
    +1885
    +1886
    +1887
    +1888
    +1889
    +1890
    +1891
    +1892
    +1893
    +1894
    +1895
    +1896
    +1897
    +1898
    +1899
    +1900
    +1901
    +1902
    +1903
    +1904
    +1905
    +1906
    +1907
    +1908
    +1909
    +1910
    +1911
    +1912
    +1913
    +1914
    +1915
    +1916
    +1917
    +1918
    +1919
    +1920
    +1921
    +1922
    +1923
    +1924
    +1925
    +1926
    +1927
    +1928
    +1929
    +1930
    +1931
    +1932
    +1933
    +1934
    +1935
    +1936
    +1937
    +1938
    +1939
    +1940
    +1941
    +1942
    +1943
    +1944
    +1945
    +1946
    +1947
    +1948
    +1949
    +1950
    +1951
    +1952
    +1953
    +1954
    +1955
    +1956
    +1957
    +1958
    +1959
    +1960
    +1961
    +1962
    +1963
    +1964
    +1965
    +1966
    class HCI_Command(HCI_Packet):
         '''
         See Bluetooth spec @ Vol 2, Part E - 5.4.1 HCI Command Packet
         '''
    +
         hci_packet_type = HCI_COMMAND_PACKET
         command_classes = {}
     
         @staticmethod
    -    def command(fields=[], return_parameters_fields=[]):
    +    def command(fields=(), return_parameters_fields=()):
             '''
             Decorator used to declare and register subclasses
             '''
    @@ -1731,8 +1836,10 @@ is set to PUBLIC_DEVICE_ADDRESS.

    # Patch the __init__ method to fix the op_code if fields is not None: + def init(self, parameters=None, **kwargs): return HCI_Command.__init__(self, cls.op_code, parameters, **kwargs) + cls.__init__ = init # Register a factory for this class @@ -1761,8 +1868,8 @@ is set to PUBLIC_DEVICE_ADDRESS.

    HCI_Command.__init__(self, op_code, parameters) HCI_Object.init_from_bytes(self, parameters, 0, fields) return self - else: - return cls.from_parameters(parameters) + + return cls.from_parameters(parameters) @staticmethod def command_name(op_code): @@ -1781,12 +1888,15 @@ is set to PUBLIC_DEVICE_ADDRESS.

    HCI_Object.init_from_fields(self, fields, kwargs) if parameters is None: parameters = HCI_Object.dict_to_bytes(kwargs, fields) - self.op_code = op_code + self.op_code = op_code self.parameters = parameters def to_bytes(self): parameters = b'' if self.parameters is None else self.parameters - return struct.pack('<BHB', HCI_COMMAND_PACKET, self.op_code, len(parameters)) + parameters + return ( + struct.pack('<BHB', HCI_COMMAND_PACKET, self.op_code, len(parameters)) + + parameters + ) def __bytes__(self): return self.to_bytes() @@ -1819,7 +1929,7 @@ is set to PUBLIC_DEVICE_ADDRESS.

    -command(fields=[], return_parameters_fields=[]) +command(fields=(), return_parameters_fields=()) staticmethod @@ -1834,33 +1944,35 @@ is set to PUBLIC_DEVICE_ADDRESS.

    Source code in bumble/hci.py -
    1752
    -1753
    -1754
    -1755
    -1756
    -1757
    -1758
    -1759
    -1760
    -1761
    -1762
    -1763
    -1764
    -1765
    -1766
    -1767
    -1768
    -1769
    -1770
    -1771
    -1772
    -1773
    -1774
    -1775
    -1776
    -1777
    @staticmethod
    -def command(fields=[], return_parameters_fields=[]):
    +        
    1878
    +1879
    +1880
    +1881
    +1882
    +1883
    +1884
    +1885
    +1886
    +1887
    +1888
    +1889
    +1890
    +1891
    +1892
    +1893
    +1894
    +1895
    +1896
    +1897
    +1898
    +1899
    +1900
    +1901
    +1902
    +1903
    +1904
    +1905
    @staticmethod
    +def command(fields=(), return_parameters_fields=()):
         '''
         Decorator used to declare and register subclasses
         '''
    @@ -1875,8 +1987,10 @@ is set to PUBLIC_DEVICE_ADDRESS.

    # Patch the __init__ method to fix the op_code if fields is not None: + def init(self, parameters=None, **kwargs): return HCI_Command.__init__(self, cls.op_code, parameters, **kwargs) + cls.__init__ = init # Register a factory for this class @@ -1914,17 +2028,21 @@ is set to PUBLIC_DEVICE_ADDRESS.

    Source code in bumble/hci.py -
    1874
    -1875
    -1876
    -1877
    -1878
    -1879
    -1880
    -1881
    @HCI_Command.command([
    -    ('connection_handle', 2),
    -    ('reason',            {'size': 1, 'mapper': HCI_Constant.error_name})
    -])
    +          
    2009
    +2010
    +2011
    +2012
    +2013
    +2014
    +2015
    +2016
    +2017
    +2018
    @HCI_Command.command(
    +    [
    +        ('connection_handle', 2),
    +        ('reason', {'size': 1, 'mapper': HCI_Constant.error_name}),
    +    ]
    +)
     class HCI_Disconnect_Command(HCI_Command):
         '''
         See Bluetooth spec @ 7.1.6 Disconnect Command
    diff --git a/apps_and_tools/console.html b/apps_and_tools/console.html
    index 433299aa..0f7bafba 100644
    --- a/apps_and_tools/console.html
    +++ b/apps_and_tools/console.html
    @@ -234,6 +234,34 @@
     
                 
               
    +            
    +              
    +  
    +  
    +  
    +    
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/apps_and_tools/gatt_dump.html b/apps_and_tools/gatt_dump.html index cbf7808d..13e18ac4 100644 --- a/apps_and_tools/gatt_dump.html +++ b/apps_and_tools/gatt_dump.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/apps_and_tools/gg_bridge.html b/apps_and_tools/gg_bridge.html index 059597f3..7d871db3 100644 --- a/apps_and_tools/gg_bridge.html +++ b/apps_and_tools/gg_bridge.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/apps_and_tools/hci_bridge.html b/apps_and_tools/hci_bridge.html index e52f9b88..345b1aff 100644 --- a/apps_and_tools/hci_bridge.html +++ b/apps_and_tools/hci_bridge.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/apps_and_tools/index.html b/apps_and_tools/index.html index 06fae4cd..99f62fd3 100644 --- a/apps_and_tools/index.html +++ b/apps_and_tools/index.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/apps_and_tools/link_relay.html b/apps_and_tools/link_relay.html index ed94868b..129f2a58 100644 --- a/apps_and_tools/link_relay.html +++ b/apps_and_tools/link_relay.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/apps_and_tools/pair.html b/apps_and_tools/pair.html index ed1c207f..e75fe944 100644 --- a/apps_and_tools/pair.html +++ b/apps_and_tools/pair.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/apps_and_tools/show.html b/apps_and_tools/show.html index 03965c9b..d7c73f38 100644 --- a/apps_and_tools/show.html +++ b/apps_and_tools/show.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/apps_and_tools/unbond.html b/apps_and_tools/unbond.html index 2401f0a7..333d1ad6 100644 --- a/apps_and_tools/unbond.html +++ b/apps_and_tools/unbond.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/apps_and_tools/usb_probe.html b/apps_and_tools/usb_probe.html index 34fc74f6..2898b0a7 100644 --- a/apps_and_tools/usb_probe.html +++ b/apps_and_tools/usb_probe.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1221,8 +1249,8 @@

    USB PROBE TOOL

    This tool lists all the USB devices, with details about each device. For each device, the different possible Bumble transport strings that can -refer to it are listed. -If the device is known to be a Bluetooth HCI device, its identifier is printed +refer to it are listed. +If the device is known to be a Bluetooth HCI device, its identifier is printed in reverse colors, and the transport names in cyan color. For other devices, regardless of their type, the transport names are printed in red. Whether that device is actually a Bluetooth device or not depends on @@ -1240,12 +1268,12 @@ When installed from PyPI, run as

    When running from the source distribution:

    $ python3 apps/usb-probe.py
     

    -

    or

    +

    or

    $ python3 apps/usb-probe.py --verbose
     

    Example

    -
    $ python3 apps/usb_probe.py 
    +
    $ python3 apps/usb_probe.py
     
     ID 0A12:0001
     Bumble Transport Names: usb:0 or usb:0A12:0001
    diff --git a/components/controller.html b/components/controller.html
    index 54f9f97e..d6313098 100644
    --- a/components/controller.html
    +++ b/components/controller.html
    @@ -234,6 +234,34 @@
     
                 
               
    +            
    +              
    +  
    +  
    +  
    +    
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/components/gatt.html b/components/gatt.html index 4deafb9b..0074ca2c 100644 --- a/components/gatt.html +++ b/components/gatt.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/components/host.html b/components/host.html index 19b00d90..6e3a1d97 100644 --- a/components/host.html +++ b/components/host.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/components/security_manager.html b/components/security_manager.html index 4392c7cf..bfedb0a7 100644 --- a/components/security_manager.html +++ b/components/security_manager.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/development/code_style.html b/development/code_style.html new file mode 100644 index 00000000..e535d54e --- /dev/null +++ b/development/code_style.html @@ -0,0 +1,1312 @@ + + + + + + + + + + + + + + + + Code Style - Bumble + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    + + + + +

    CODE STYLE

    +

    The Python code style used in this project follows the Black code style.

    +

    Formatting

    +

    For now, we are configuring the black formatter with the option to leave quotes unchanged. +The preferred quote style is single quotes, which isn't a configurable option for Black, so we are not enforcing it. This may change in the future.

    +

    Ignoring Commit for Git Blame

    +

    The adoption of Black as a formatter came in late in the project, with already a large code base. As a result, a large number of files were changed in a single commit, which gets in the way of tracing authorship with git blame. The file git-blame-ignore-revs contains the commit hash of when that mass-formatting event occurred, which you can use to skip it in a git blame analysis:

    +
    +

    Ignoring a commit with git blame

    +
    $ git blame --ignore-revs-file .git-blame-ignore-revs
    +
    +
    +

    Linting

    +

    The project includes a pylint configuration (see the pyproject.toml file for details). +The pre-commit checks only enforce that there are no errors. But we strongly recommend that you run the linter with warnings enabled at least, and possibly the "Refactor" ('R') and "Convention" ('C') categories as well. +To run the linter, use the project.lint invoke command.

    +
    +

    Running the linter with default options

    +

    With the default settings, Errors and Warnings are enabled, but Refactor and Convention categories are not. +

    $ invoke project.lint
    +

    +
    +
    +

    Running the linter with all categories

    +
    $ invoke project.lint --disable=""
    +
    +
    +

    Editor/IDE Integration

    +

    Visual Studio Code

    +

    The project includes a .vscode/settings.json file that specifies the black formatter and enables an editor ruler at 88 columns. +You may want to configure your own environment to "format on save" with black if you find that useful. We are not making that choice at the workspace level.

    + + + + + +
    + +
    +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/development/contributing.html b/development/contributing.html new file mode 100644 index 00000000..51592de4 --- /dev/null +++ b/development/contributing.html @@ -0,0 +1,1287 @@ + + + + + + + + + + + + + + + + Contributing - Bumble + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    + + + + +

    CONTRIBUTING TO THE PROJECT

    +

    To contribute some code to the project, you will need to submit a GitHub Pull Request (a.k.a PR). Please familiarize yourself with how that works (see GitHub Pull Requests)

    +

    You should follow the project's code style, and pre-check your code before submitting a PR. The GitHub project is set up with some Actions that will check that a PR passes at least the basic tests and complies with the coding style, but it is still recommended to check that for yourself before submitting a PR. +To run the basic checks (essentially: running the tests, the linter, and the formatter), use the project.pre-commit invoke command, and address any issues found:

    +
    $ invoke project.pre-commit
    +
    + + + + + +
    + +
    +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/development/python_environments.html b/development/python_environments.html index 973c4b82..614d7c8e 100644 --- a/development/python_environments.html +++ b/development/python_environments.html @@ -311,6 +311,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1287,26 +1315,26 @@

    PYTHON ENVIRONMENTS

    -

    When you don't want to install Bumble in your main/default python environment, +

    When you don't want to install Bumble in your main/default python environment, using a virtual environment, where the package and its dependencies can be installed, isolated from the rest, may be useful.

    -

    There are many flavors of python environments and dependency managers. +

    There are many flavors of python environments and dependency managers. This page describes a few of the most common ones.

    venv

    venv is a standard module that is included with python. Visit the venv documentation page for details.

    Pyenv

    -

    pyenv lets you easily switch between multiple versions of Python. It's simple, unobtrusive, and follows the UNIX tradition of single-purpose tools that do one thing well.
    +

    pyenv lets you easily switch between multiple versions of Python. It's simple, unobtrusive, and follows the UNIX tradition of single-purpose tools that do one thing well. Visit the pyenv site for instructions on how to install and use pyenv

    Conda

    Conda is a convenient package manager and virtual environment. The file environment.yml is a Conda environment file that you can use to create a new Conda environment. Once created, you can simply activate this environment when -working with Bumble.
    +working with Bumble. Visit the Conda site for instructions on how to install and use Conda. -A few useful commands:

    +A few useful commands:

    Create a new bumble Conda environment

    $ conda env create -f environment.yml
     
    @@ -1349,13 +1377,13 @@ This will create a new environment, named bumble, which you can the -
  • + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/getting_started.html b/getting_started.html index be9d3a29..c145e606 100644 --- a/getting_started.html +++ b/getting_started.html @@ -244,6 +244,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1174,16 +1202,16 @@

    Prerequisites

    You need Python 3.8 or above. Python >= 3.9 is recommended, but 3.8 should be sufficient if necessary (there may be some optional functionality that will not work on some platforms with -python 3.8).
    +python 3.8). Visit the Python site for instructions on how to install Python -for your platform.
    +for your platform. Throughout the documentation, when shell commands are shown, it is assumed that you can invoke Python as

    $ python
     
    -If invoking python is different on your platform (it may be python3 for example, or just py or py.exe), +If invoking python is different on your platform (it may be python3 for example, or just py or py.exe), adjust accordingly.

    -

    You may be simply using Bumble as a module for your own application or as a dependency to your own +

    You may be simply using Bumble as a module for your own application or as a dependency to your own module, or you may be working on modifying or contributing to the Bumble module or example code itself.

    Using Bumble As A Python Module

    @@ -1216,13 +1244,14 @@ distribution

    Working On The Bumble Code

    When you work on the Bumble code itself, and run some of the tests or example apps, or import the -module in your own code, you typically either install the package from source in "development mode" as described above, or you may choose to skip the install phase.

    +module in your own code, you typically either install the package from source in "development mode" as described above, or you may choose to skip the install phase.

    +

    If you plan on contributing to the project, please read the contributing section.

    Without Installing

    -

    If you prefer not to install the package (even in development mode), you can load the module directly from its location in the project. +

    If you prefer not to install the package (even in development mode), you can load the module directly from its location in the project. A simple way to do that is to set your PYTHONPATH to point to the root project directory, where the bumble subdirectory is located. You may set PYTHONPATH globally, or locally with each command line execution (on Unix-like systems).

    -

    Example with a global PYTHONPATH, from a unix shell, when the working directory is the root +

    Example with a global PYTHONPATH, from a unix shell, when the working directory is the root directory of the project.

    $ export PYTHONPATH=.
     $ python apps/console.py serial:/dev/tty.usbmodem0006839912171
    @@ -1237,12 +1266,12 @@ $ python run_scanner.py usb:0
     
    $ PYTHONPATH=. python examples/run_advertiser.py examples/device1.json serial:/dev/tty.usbmodem0006839912171
     

    Where To Go Next

    -

    Once you've installed or downloaded Bumble, you can either start using some of the +

    Once you've installed or downloaded Bumble, you can either start using some of the Bundled apps and tools, or look at the examples to get a feel for how to use the APIs, and start writing your own applications.

    Depending on the use case you're interested in exploring, you may need to use a physical Bluetooth controller, like a USB dongle or a board with a Bluetooth radio. Visit the Hardware page -for more information on using a physical radio, and/or the Transports page for more +for more information on using a physical radio, and/or the Transports page for more details on interfacing with either hardware modules or virtual controllers over various transports.

    diff --git a/hardware/index.html b/hardware/index.html index 5b2a4265..c875291e 100644 --- a/hardware/index.html +++ b/hardware/index.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1173,11 +1201,11 @@

    HARDWARE

    -

    The Bumble Host connects to a controller over an HCI Transport. -To use a hardware controller attached to the host on which the host application is running, the transport is typically either HCI over UART or HCI over USB. -On Linux, the VHCI Transport can be used to communicate with any controller hardware managed by the operating system. Alternatively, a remote controller (a phyiscal controller attached to a remote host) can be used by connecting one of the networked transports (such as the TCP Client transport, the TCP Server transport or the UDP Transport) to an HCI Bridge bridging the network transport to a physical controller on a remote host.

    -

    In theory, any controller that is compliant with the HCI over UART or HCI over USB protocols can be used.

    -

    HCI over USB is very common, implemented by a number of commercial Bluetooth dongles.

    +

    The Bumble Host connects to a controller over an HCI Transport. +To use a hardware controller attached to the host on which the host application is running, the transport is typically either HCI over UART or HCI over USB. +On Linux, the VHCI Transport can be used to communicate with any controller hardware managed by the operating system. Alternatively, a remote controller (a phyiscal controller attached to a remote host) can be used by connecting one of the networked transports (such as the TCP Client transport, the TCP Server transport or the UDP Transport) to an HCI Bridge bridging the network transport to a physical controller on a remote host.

    +

    In theory, any controller that is compliant with the HCI over UART or HCI over USB protocols can be used.

    +

    HCI over USB is very common, implemented by a number of commercial Bluetooth dongles.

    It is also possible to use an embedded development board, running a specialized application, such as the HCI UART and HCI USB demo applications from the Zephyr project, or the blehci application from mynewt/nimble

    Some specific USB dongles and embedded boards that are known to work include:

      diff --git a/images/bumble_layers.svg b/images/bumble_layers.svg index 3da9f583..c0dbca17 100644 --- a/images/bumble_layers.svg +++ b/images/bumble_layers.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/index.html b/index.html index e6414431..f0741318 100644 --- a/index.html +++ b/index.html @@ -454,6 +454,34 @@ + + + + + +
    • + + Contributing + +
    • + + + + + + + + + +
    • + + Code Style + +
    • + + + +
    diff --git a/platforms/android.html b/platforms/android.html index 05729ff2..54c9e4df 100644 --- a/platforms/android.html +++ b/platforms/android.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1262,12 +1290,12 @@

    ANDROID PLATFORM

    Using Bumble with Android is not about running the Bumble stack on the Android -OS itself, but rather using Bumble with the Bluetooth support of the Android +OS itself, but rather using Bumble with the Bluetooth support of the Android emulator.

    The two main use cases are:

    • Connecting the Bumble host stack to the Android emulator's virtual controller.
    • -
    • Using Bumble as an HCI bridge to connect the Android emulator to a physical +
    • Using Bumble as an HCI bridge to connect the Android emulator to a physical Bluetooth controller, such as a USB dongle
    @@ -1277,13 +1305,13 @@ be evolving. The information contained here be somewhat out of sync with the version of the emulator you are using. You will need version 31.3.8.0 or later.

    -

    The Android emulator supports Bluetooth in two ways: either by exposing virtual +

    The Android emulator supports Bluetooth in two ways: either by exposing virtual Bluetooth controllers to which you can connect a virtual Bluetooth host stack, or by exposing an way to connect your own virtual controller to the Android Bluetooth stack via a virtual HCI interface. Both ways are controlled via gRPC requests to the Android emulator.

    Launching the Emulator

    -

    If the version of the emulator you are running does not yet support enabling +

    If the version of the emulator you are running does not yet support enabling Bluetooth support by default or automatically, you must launch the emulator from the command line.

    @@ -1299,7 +1327,7 @@ communicate link layer packets between them, thus creating a virtual radio netwo Configuring a Bumble Device instance to use Root Canal as a virtual controller allows that virtual device to communicate with the Android Bluetooth stack, and through it with Android applications as well as system-managed profiles. -To connect a Bumble host stack to a Root Canal virtual controller instance, use +To connect a Bumble host stack to a Root Canal virtual controller instance, use the bumble android-emulator transport in host mode (the default).

    Run the example GATT server connected to the emulator

    @@ -1330,7 +1358,7 @@ before attaching the virtual controller, then re-enable it once attached.

    Other Tools

    The show application that's included with Bumble can be used to parse and pretty-print the HCI packets -from an Android HCI "snoop log" (see this page +from an Android HCI "snoop log" (see this page for details on how to obtain HCI snoop logs from an Android device). Use the --format snoop option to specify that the file is in that specific format.

    diff --git a/platforms/index.html b/platforms/index.html index fbada78f..a3792278 100644 --- a/platforms/index.html +++ b/platforms/index.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/platforms/linux.html b/platforms/linux.html index 1201164b..098bc0dc 100644 --- a/platforms/linux.html +++ b/platforms/linux.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1432,8 +1460,8 @@ The 3 main types of physical Bluetooth controllers are:

    Conflicts with the kernel and BlueZ

    If your use a USB dongle that is recognized by your kernel as a supported Bluetooth device, it is -likely that the kernel driver will claim that USB device and attach it to the BlueZ stack. -If you want to claim ownership of it to use with Bumble, you will need to set the state of the corresponding HCI interface as DOWN. +likely that the kernel driver will claim that USB device and attach it to the BlueZ stack. +If you want to claim ownership of it to use with Bumble, you will need to set the state of the corresponding HCI interface as DOWN. HCI interfaces are numbered, starting from 0 (i.e hci0, hci1, ...).

    For example, to bring hci0 down:

    $ sudo hciconfig hci0 down
    @@ -1450,7 +1478,7 @@ close it, so you may need to bring the interface back UP before usi
     

    USB Permissions

    By default, when running as a regular user, you won't have the permission to use arbitrary USB devices. -You can change the permissions for a specific USB device based on its bus number and +You can change the permissions for a specific USB device based on its bus number and device number (you can use lsusb to find the Bus and Device numbers for your Bluetooth dongle).

    Example: @@ -1474,7 +1502,7 @@ You can bring a HCI controller UP or DOWN with h

    HCI Socket Permissions

    By default, when running as a regular user, you won't have the permission to use an HCI socket to a Bluetooth controller (you may see an exception like PermissionError: [Errno 1] Operation not permitted).

    -

    If you want to run without using sudo, you need to manage the capabilities by adding the appropriate entries in /etc/security/capability.conf to grant a user or group the cap_net_admin capability.
    +

    If you want to run without using sudo, you need to manage the capabilities by adding the appropriate entries in /etc/security/capability.conf to grant a user or group the cap_net_admin capability. See this manpage for details.

    Alternatively, if you are just experimenting temporarily, the capsh command may be useful in order to execute a single command with enhanced permissions, as in this example:

    @@ -1492,20 +1520,20 @@ lists all available HCI controllers and their state.

    pi@raspberrypi:~ $ hciconfig
     hci1:   Type: Primary  Bus: USB
         BD Address: 00:16:A4:5A:40:F2  ACL MTU: 1021:8  SCO MTU: 64:1
    -    DOWN 
    +    DOWN
         RX bytes:84056 acl:0 sco:0 events:51 errors:0
         TX bytes:1980 acl:0 sco:0 commands:90 errors:0
     
     hci0:   Type: Primary  Bus: UART
         BD Address: DC:A6:32:75:2C:97  ACL MTU: 1021:8  SCO MTU: 64:1
    -    DOWN 
    +    DOWN
         RX bytes:68038 acl:0 sco:0 events:692 errors:0
         TX bytes:20105 acl:0 sco:0 commands:843 errors:0
     

    Disabling bluetoothd

    -

    When the Bluetooth daemon, bluetoothd, is running, it will try to use any HCI controller attached to the BlueZ stack, automatically. This means that whenever an HCI socket transport is released, it is likely that bluetoothd will take it over, so you will get a "device busy" condition (ex: OSError: [Errno 16] Device or resource busy). If that happens, you can always use +

    When the Bluetooth daemon, bluetoothd, is running, it will try to use any HCI controller attached to the BlueZ stack, automatically. This means that whenever an HCI socket transport is released, it is likely that bluetoothd will take it over, so you will get a "device busy" condition (ex: OSError: [Errno 16] Device or resource busy). If that happens, you can always use

    $ hciconfig hci0 down
     
    (or hci<X> with <X> being the index of the controller device you want to use), but a simpler solution is to just stop the bluetoothd daemon, with a command like: @@ -1564,7 +1592,7 @@ In both cases, the controller can run locally on the Linux host, or remotely on
    $ hciconfig
     hci0:   Type: Primary  Bus: Virtual
         BD Address: F6:F7:F8:F9:FA:FB  ACL MTU: 27:64  SCO MTU: 0:0
    -    UP RUNNING 
    +    UP RUNNING
         RX bytes:0 acl:0 sco:0 events:43 errors:0
         TX bytes:274 acl:0 sco:0 commands:43 errors:0
     

    diff --git a/platforms/macos.html b/platforms/macos.html index 05ad5ff5..669b98dd 100644 --- a/platforms/macos.html +++ b/platforms/macos.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/platforms/windows.html b/platforms/windows.html index a066a3e8..ac97b048 100644 --- a/platforms/windows.html +++ b/platforms/windows.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1222,7 +1250,7 @@

    USB HCI

    To use a Bluetooth USB dongle on Windows, you need a USB dongle that does not require a vendor Windows driver (the dongle will be used directly through the WinUSB driver rather than through a vendor-supplied Windows driver).

    In order to use the dongle, the WinUSB driver must be assigned to the USB device. It is likely that, by default, when you first plug in the dongle, it will be recognized by Windows as a Bluetooth USB device, and Windows will try to use it with its native Bluetooth stack. You will need to switch the driver, which can be done easily with the Zadig tool. -In the Zadig tool, select your USB dongle device, and associate it with WinUSB.
    +In the Zadig tool, select your USB dongle device, and associate it with WinUSB. Once the WinUSB driver is correctly assigned to your device, you can confirm that by checking the settings with the Windows Device Manager control panel. Your device should appear under "Universal Serial Bus Device" (not under "Bluetooth"), and inspecting the driver details, you should see winusb.sys in the list of driver files.

    USB Driver Details

    diff --git a/sitemap.xml b/sitemap.xml index 9a7baae8..0faa8ea4 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,237 +2,247 @@ None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 daily None - 2022-10-11 + 2022-12-19 + daily + + + None + 2022-12-19 + daily + + + None + 2022-12-19 daily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index efd51a2e..75285101 100644 Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ diff --git a/transports/android_emulator.html b/transports/android_emulator.html index dbd12eeb..2be71650 100644 --- a/transports/android_emulator.html +++ b/transports/android_emulator.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1222,21 +1250,22 @@

    The Android emulator transport either connects, as a host, to a "Root Canal" virtual controller ("host" mode), or attaches a virtual controller to the Android Bluetooth host stack ("controller" mode).

    Moniker

    -

    The moniker syntax for an Android Emulator transport is: android-emulator:[mode=<host|controller>][mode=<host|controller>]. -Both the mode=<host|controller> and mode=<host|controller> parameters are optional (so the moniker android-emulator by itself is a valid moniker, which will create a transport in host mode, connected to localhost on the default gRPC port for the emulator)

    +

    The moniker syntax for an Android Emulator transport is: android-emulator:[mode=<host|controller>][<hostname>:<port>], where +the mode parameter can specify running as a host or a controller, and <hostname>:<port> can specify a host name (or IP address) and TCP port number on which to reach the gRPC server for the emulator. +Both the mode=<host|controller> and <hostname>:<port> parameters are optional (so the moniker android-emulator by itself is a valid moniker, which will create a transport in host mode, connected to localhost on the default gRPC port for the emulator).

    Example

    -

    android-emulator
    +

    android-emulator connect as a host to the emulator on localhost:8554

    Example

    -

    android-emulator:mode=controller
    +

    android-emulator:mode=controller connect as a controller to the emulator on localhost:8554

    Example

    -

    android-emulator:localhost:8555
    +

    android-emulator:localhost:8555 connect as a host to the emulator on localhost:8555

    diff --git a/transports/file.html b/transports/file.html index fffbebeb..3ca661d4 100644 --- a/transports/file.html +++ b/transports/file.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1225,7 +1253,7 @@ This is typically used to open a PTY, or unix driver, not for real files.

    The moniker for a File transport is file:<path>

    Example

    -

    file:/dev/ttys001
    +

    file:/dev/ttys001 Opens the pseudo terminal /dev/ttys001 as a transport

    diff --git a/transports/hci_socket.html b/transports/hci_socket.html index 0790bf97..0381e409 100644 --- a/transports/hci_socket.html +++ b/transports/hci_socket.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1228,7 +1256,7 @@

    The moniker for an HCI Socket transport is either just hci-socket (to use the default/first Bluetooth controller), or hci-socket:<index> where <index> is the 0-based index of a Bluetooth controller device.

    Example

    -

    hci-socket
    +

    hci-socket Use an HCI socket to the first Bluetooth controller (hci0 on Linux)

    diff --git a/transports/index.html b/transports/index.html index 0d3e0634..fe5dcfb7 100644 --- a/transports/index.html +++ b/transports/index.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/transports/pty.html b/transports/pty.html index c66cd51a..304912e3 100644 --- a/transports/pty.html +++ b/transports/pty.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1225,7 +1253,7 @@ Where path, is used, is the path name where a symbolic link to the PTY will be created for convenience (the link will be removed when the transport is closed or when the process exits).

    Example

    -

    pty:virtual_hci
    +

    pty:virtual_hci Creates a PTY entry and a symbolic link, named virtual_hci, linking to the PTY

    diff --git a/transports/serial.html b/transports/serial.html index 4e0cff0e..691dbbfb 100644 --- a/transports/serial.html +++ b/transports/serial.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1225,7 +1253,7 @@ When <speed> is omitted, the default value of 1000000 is used

    Example

    -

    serial:/dev/tty.usbmodem0006839912172,1000000
    +

    serial:/dev/tty.usbmodem0006839912172,1000000 Opens the serial port /dev/tty.usbmodem0006839912172 at 1000000bps

    diff --git a/transports/tcp_client.html b/transports/tcp_client.html index 81931b58..aca8a550 100644 --- a/transports/tcp_client.html +++ b/transports/tcp_client.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1224,7 +1252,7 @@

    The moniker syntax for a TCP client transport is: tcp-client:<remote-host>:<remote-port>

    Example

    -

    tcp-client:127.0.0.1:9001
    +

    tcp-client:127.0.0.1:9001 Connects to port 9001 on the local host

    diff --git a/transports/tcp_server.html b/transports/tcp_server.html index b2d16d3b..476128c9 100644 --- a/transports/tcp_server.html +++ b/transports/tcp_server.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1222,11 +1250,11 @@

    The TCP Client transport uses an incoming TCP connection to a host:port address.

    Moniker

    The moniker syntax for a TCP server transport is: tcp-server:<local-host>:<local-port> -where <local-host> may be the address of a local network interface, or _ to accept +where <local-host> may be the address of a local network interface, or _ to accept connections on all local network interfaces.

    Example

    -

    tcp-server:_:9001
    +

    tcp-server:_:9001 Waits for and accepts connections on port 9001

    diff --git a/transports/udp.html b/transports/udp.html index 845285c0..07b9e23c 100644 --- a/transports/udp.html +++ b/transports/udp.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1224,7 +1252,7 @@

    The moniker syntax for a UDP transport is: udp:<local-host>:<local-port>,<remote-host>:<remote-port>.

    Example

    -

    udp:0.0.0.0:9000,127.0.0.1:9001
    +

    udp:0.0.0.0:9000,127.0.0.1:9001 UDP transport where packets are received on port 9000 and sent to 127.0.0.1 on port 9001

    diff --git a/transports/usb.html b/transports/usb.html index 6ab13f0a..862f7c3f 100644 --- a/transports/usb.html +++ b/transports/usb.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -571,6 +599,13 @@ Alternative + + +
  • + + Libusb + +
  • @@ -1263,6 +1298,13 @@ Alternative +
  • + +
  • + + Libusb + +
  • @@ -1345,9 +1387,9 @@ the first USB interface of the device will be used, regardless of the interface This may be useful for some devices that use a custom class/subclass but may nonetheless work as-is.

    Examples

    -

    usb:04b4:f901
    +

    usb:04b4:f901 The USB dongle with <vendor> equal to 04b4 and <product> equal to f901

    -

    usb:0
    +

    usb:0 The first Bluetooth HCI dongle that's declared as such by Class/Subclass/Protocol

    usb:04b4:f901/0016A45B05D8 The USB dongle with <vendor> equal to 04b4, <product> equal to f901 and <serial> equal to 0016A45B05D8

    @@ -1359,6 +1401,9 @@ The BT USB dongle vendor=0B05 and product=17CB, in "forced" mode.

    Alternative

    The library includes two different implementations of the USB transport, implemented using different python bindings for libusb. Using the transport prefix pyusb: instead of usb: selects the implementation based on PyUSB, using the synchronous API of libusb, whereas the default implementation is based on libusb1, using the asynchronous API of libusb. In order to use the alternative PyUSB-based implementation, you need to ensure that you have installed that python module, as it isn't installed by default as a dependency of Bumble.

    +

    Libusb

    +

    The libusb-1.0 shared library is required to use both usb and pyusb transports. This library should be installed automatically with Bumble, as part of the libusb_package Python package. +If your OS or architecture is not supported by libusb_package, you can install a system-wide library with brew install libusb for Mac or apt install libusb-1.0-0 for Linux.

    Listing Available USB Devices

    With usb_probe

    You can use the usb_probe tool to list all the USB devices attached to your host computer. diff --git a/transports/vhci.html b/transports/vhci.html index 98135c89..a57e1b32 100644 --- a/transports/vhci.html +++ b/transports/vhci.html @@ -234,6 +234,34 @@ + + + + + +

  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1228,7 +1256,7 @@

    The moniker for a VHCI transport is either just vhci (to use the default VHCI device path at /dev/vhci), or vhci:<path> where <path> is the path of a VHCI device.

    Example

    -

    vhci
    +

    vhci Attaches a virtual controller transport to /dev/vhci

    diff --git a/transports/ws_client.html b/transports/ws_client.html index 95546d81..5c47aa13 100644 --- a/transports/ws_client.html +++ b/transports/ws_client.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1224,7 +1252,7 @@

    The moniker syntax for a UDP transport is: udp:<local-host>:<local-port>,<remote-host>:<remote-port>.

    Example

    -

    udp:0.0.0.0:9000,127.0.0.1:9001
    +

    udp:0.0.0.0:9000,127.0.0.1:9001 UDP transport where packets are received on port 9000 and sent to 127.0.0.1 on port 9001

    diff --git a/transports/ws_server.html b/transports/ws_server.html index 96ce56d5..88f75019 100644 --- a/transports/ws_server.html +++ b/transports/ws_server.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1224,7 +1252,7 @@

    The moniker syntax for a UDP transport is: udp:<local-host>:<local-port>,<remote-host>:<remote-port>.

    Example

    -

    udp:0.0.0.0:9000,127.0.0.1:9001
    +

    udp:0.0.0.0:9000,127.0.0.1:9001 UDP transport where packets are received on port 9000 and sent to 127.0.0.1 on port 9001

    diff --git a/use_cases/index.html b/use_cases/index.html index a2f95c06..3d050ab8 100644 --- a/use_cases/index.html +++ b/use_cases/index.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1200,7 +1228,7 @@ diff --git a/use_cases/use_case_1.html b/use_cases/use_case_1.html index 1abbde70..5358b27d 100644 --- a/use_cases/use_case_1.html +++ b/use_cases/use_case_1.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/use_cases/use_case_2.html b/use_cases/use_case_2.html index 871c3763..4fd3aa6d 100644 --- a/use_cases/use_case_2.html +++ b/use_cases/use_case_2.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/use_cases/use_case_3.html b/use_cases/use_case_3.html index c8b1b374..300bc878 100644 --- a/use_cases/use_case_3.html +++ b/use_cases/use_case_3.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/use_cases/use_case_4.html b/use_cases/use_case_4.html index aa0562e3..18b9f63f 100644 --- a/use_cases/use_case_4.html +++ b/use_cases/use_case_4.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1175,7 +1203,7 @@

    USE CASE 4

    Connecting two emulated Bluetooth devices

    Connect two emulated Bluetooth device (ex: an Android emulator, or an embedded device emulator) to each other

    -
    +-----------+             +------------+                +------------+             +-----------+ 
    +
    +-----------+             +------------+                +------------+             +-----------+
     | Emulated  |             | Bumble     |    Bumble      | Bumble     |             | Emulated  |
     | Bluetooth |<--  HCI  -->| Virtual    |<== Local or ==>| Virtual    |<--  HCI  -->| Bluetooth |
     | Device    |  Transport  | Controller |    Remote      | Controller |  Transport  | Device    |
    diff --git a/use_cases/use_case_5.html b/use_cases/use_case_5.html
    index 952bf1cc..32c98601 100644
    --- a/use_cases/use_case_5.html
    +++ b/use_cases/use_case_5.html
    @@ -234,6 +234,34 @@
     
                 
               
    +            
    +              
    +  
    +  
    +  
    +    
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + diff --git a/use_cases/use_case_6.html b/use_cases/use_case_6.html index 67f9b405..2a10ed03 100644 --- a/use_cases/use_case_6.html +++ b/use_cases/use_case_6.html @@ -234,6 +234,34 @@ + + + + + +
  • + + Contributing + +
  • + + + + + + + + + +
  • + + Code Style + +
  • + + + + @@ -1175,7 +1203,7 @@

    USE CASE 6

    Connecting an emulated Bluetooth device to a physical controller

    It can be useful to connect an emulated device (like a phone simulator, or an emulated embedded device) to a physical controller in order to connect to other Bluetooth devices. By doing this via a Bumble HCI bridge, it becomes easy to inspect the HCI packets exchanged with the controller, and possibly filter/change them if needed (for example to support vendor-specific HCI extensions).

    -
    +-----------+             +--------+             +------------+             +-----------+ 
    +
    +-----------+             +--------+             +------------+             +-----------+
     | Emulated  |             | Bumble |             | Physical   |             | Bluetooth |
     | Bluetooth |<--  HCI  -->| HCI    |<--  HCI  -->| Controller |{...radio...}| Device    |
     | Device    |  Transport  | Bridge |  Transport  |            |             |           |