1737
1738
1739
1740
@@ -1464,7 +1409,62 @@ address[0] is the LSB of the address, address[5] is the MSB.
1820
1821
1822
-1823 | class Address:
+1823
+1824
+1825
+1826
+1827
+1828
+1829
+1830
+1831
+1832
+1833
+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
+1859
+1860
+1861
+1862
+1863
+1864
+1865
+1866
+1867
+1868
+1869
+1870
+1871
+1872
+1873
+1874
+1875
+1876
+1877
+1878
| 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
@@ -1641,33 +1641,33 @@ the type is set to PUBLIC_DEVICE_ADDRESS.
Source code in bumble/hci.py
- 1738
-1739
-1740
-1741
-1742
-1743
-1744
-1745
-1746
-1747
-1748
-1749
-1750
-1751
-1752
-1753
-1754
-1755
-1756
-1757
-1758
-1759
-1760
-1761
-1762
-1763
-1764 | def __init__(
+ 1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+1801
+1802
+1803
+1804
+1805
+1806
+1807
+1808
+1809
+1810
+1811
+1812
+1813
+1814
+1815
+1816
+1817
+1818
+1819 | def __init__(
self, address: Union[bytes, str], address_type: int = RANDOM_DEVICE_ADDRESS
):
'''
@@ -1717,15 +1717,15 @@ qualifier.
Source code in bumble/hci.py
- 1800
-1801
-1802
-1803
-1804
-1805
-1806
-1807
-1808 | def to_string(self, with_type_qualifier=True):
+ 1855
+1856
+1857
+1858
+1859
+1860
+1861
+1862
+1863 | def to_string(self, with_type_qualifier=True):
'''
String representation of the address, MSB first, with an optional type
qualifier.
@@ -1761,36 +1761,36 @@ qualifier.
Source code in bumble/hci.py
- 1854
-1855
-1856
-1857
-1858
-1859
-1860
-1861
-1862
-1863
-1864
-1865
-1866
-1867
-1868
-1869
-1870
-1871
-1872
-1873
-1874
-1875
-1876
-1877
-1878
-1879
-1880
-1881
-1882
-1883 | class HCI_Packet:
+ 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 | class HCI_Packet:
'''
Abstract Base class for HCI packets
'''
@@ -1798,7 +1798,7 @@ qualifier.
hci_packet_type: int
@staticmethod
- def from_bytes(packet):
+ def from_bytes(packet: bytes) -> HCI_Packet:
packet_type = packet[0]
if packet_type == HCI_COMMAND_PACKET:
@@ -1859,62 +1859,7 @@ qualifier.
Source code in bumble/hci.py
- 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
+ 1953
1954
1955
1956
@@ -1955,12 +1900,91 @@ qualifier.
1991
1992
1993
-1994 | class HCI_Command(HCI_Packet):
+1994
+1995
+1996
+1997
+1998
+1999
+2000
+2001
+2002
+2003
+2004
+2005
+2006
+2007
+2008
+2009
+2010
+2011
+2012
+2013
+2014
+2015
+2016
+2017
+2018
+2019
+2020
+2021
+2022
+2023
+2024
+2025
+2026
+2027
+2028
+2029
+2030
+2031
+2032
+2033
+2034
+2035
+2036
+2037
+2038
+2039
+2040
+2041
+2042
+2043
+2044
+2045
+2046
+2047
+2048
+2049
+2050
+2051
+2052
+2053
+2054
+2055
+2056
+2057
+2058
+2059
+2060
+2061
+2062
+2063
+2064
+2065
+2066
+2067
+2068
+2069
+2070
+2071
+2072
| 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_names: Dict[int, str] = {}
command_classes: Dict[int, Type[HCI_Command]] = {}
@staticmethod
@@ -1971,9 +1995,9 @@ qualifier.
def inner(cls):
cls.name = cls.__name__.upper()
- cls.op_code = key_with_value(HCI_COMMAND_NAMES, cls.name)
+ cls.op_code = key_with_value(cls.command_names, cls.name)
if cls.op_code is None:
- raise KeyError(f'command {cls.name} not found in HCI_COMMAND_NAMES')
+ raise KeyError(f'command {cls.name} not found in command_names')
cls.fields = fields
cls.return_parameters_fields = return_parameters_fields
@@ -1993,7 +2017,19 @@ qualifier.
return inner
@staticmethod
- def from_bytes(packet):
+ def command_map(symbols: Dict[str, Any]) -> Dict[int, str]:
+ return {
+ command_code: command_name
+ for (command_name, command_code) in symbols.items()
+ if command_name.startswith('HCI_') and command_name.endswith('_COMMAND')
+ }
+
+ @classmethod
+ def register_commands(cls, symbols: Dict[str, Any]) -> None:
+ cls.command_names.update(cls.command_map(symbols))
+
+ @staticmethod
+ def from_bytes(packet: bytes) -> HCI_Command:
op_code, length = struct.unpack_from('<HB', packet, 1)
parameters = packet[4:]
if len(parameters) != length:
@@ -2012,11 +2048,11 @@ qualifier.
HCI_Object.init_from_bytes(self, parameters, 0, fields)
return self
- return cls.from_parameters(parameters)
+ return cls.from_parameters(parameters) # type: ignore
@staticmethod
def command_name(op_code):
- name = HCI_COMMAND_NAMES.get(op_code)
+ name = HCI_Command.command_names.get(op_code)
if name is not None:
return name
return f'[OGF=0x{op_code >> 10:02x}, OCF=0x{op_code & 0x3FF:04x}]'
@@ -2025,6 +2061,16 @@ qualifier.
def create_return_parameters(cls, **kwargs):
return HCI_Object(cls.return_parameters_fields, **kwargs)
+ @classmethod
+ def parse_return_parameters(cls, parameters):
+ if not cls.return_parameters_fields:
+ return None
+ return_parameters = HCI_Object.from_bytes(
+ parameters, 0, cls.return_parameters_fields
+ )
+ return_parameters.fields = cls.return_parameters_fields
+ return return_parameters
+
def __init__(self, op_code, parameters=None, **kwargs):
super().__init__(HCI_Command.command_name(op_code))
if (fields := getattr(self, 'fields', None)) and kwargs:
@@ -2087,34 +2133,34 @@ qualifier.
Source code in bumble/hci.py
- 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 | @staticmethod
+ 1962
+1963
+1964
+1965
+1966
+1967
+1968
+1969
+1970
+1971
+1972
+1973
+1974
+1975
+1976
+1977
+1978
+1979
+1980
+1981
+1982
+1983
+1984
+1985
+1986
+1987
+1988
+1989 | @staticmethod
def command(fields=(), return_parameters_fields=()):
'''
Decorator used to declare and register subclasses
@@ -2122,9 +2168,9 @@ qualifier.
def inner(cls):
cls.name = cls.__name__.upper()
- cls.op_code = key_with_value(HCI_COMMAND_NAMES, cls.name)
+ cls.op_code = key_with_value(cls.command_names, cls.name)
if cls.op_code is None:
- raise KeyError(f'command {cls.name} not found in HCI_COMMAND_NAMES')
+ raise KeyError(f'command {cls.name} not found in command_names')
cls.fields = fields
cls.return_parameters_fields = return_parameters_fields
@@ -2171,16 +2217,16 @@ qualifier.
Source code in bumble/hci.py
- 2037
-2038
-2039
-2040
-2041
-2042
-2043
-2044
-2045
-2046 | @HCI_Command.command(
+ 2118
+2119
+2120
+2121
+2122
+2123
+2124
+2125
+2126
+2127 | @HCI_Command.command(
[
('connection_handle', 2),
('reason', {'size': 1, 'mapper': HCI_Constant.error_name}),
diff --git a/downloads/zephyr/hci_usb.zip b/downloads/zephyr/hci_usb.zip
new file mode 100644
index 00000000..5e1dfc94
Binary files /dev/null and b/downloads/zephyr/hci_usb.zip differ
diff --git a/sitemap.xml.gz b/sitemap.xml.gz
index d3e3c18d..450de874 100644
Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ
diff --git a/transports/ws_client.html b/transports/ws_client.html
index ab2a8edb..e9e8fd06 100644
--- a/transports/ws_client.html
+++ b/transports/ws_client.html
@@ -63,7 +63,7 @@
-
+
Skip to content
@@ -1350,14 +1350,14 @@
- UDP TRANSPORT
- The UDP transport is a UDP socket, receiving packets on a specified port number, and sending packets to a specified host and port number.
+ WEBSOCKET CLIENT TRANSPORT
+ The WebSocket Client transport is WebSocket connection to a WebSocket server over which HCI packets
+are sent and received.
Moniker
- The moniker syntax for a UDP transport is: udp:<local-host>:<local-port>,<remote-host>:<remote-port>.
+ The moniker syntax for a WebSocket Client transport is: ws-client:<ws-url>
Example
- 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
+ ws-client:ws://localhost:1234/some/path
diff --git a/transports/ws_server.html b/transports/ws_server.html
index 35223f0b..2413a464 100644
--- a/transports/ws_server.html
+++ b/transports/ws_server.html
@@ -63,7 +63,7 @@
-
+
Skip to content
@@ -1350,14 +1350,15 @@
- UDP TRANSPORT
- The UDP transport is a UDP socket, receiving packets on a specified port number, and sending packets to a specified host and port number.
+ WEBSOCKET SERVER TRANSPORT
+ The WebSocket Server transport is WebSocket server that accepts connections from a WebSocket
+client. HCI packets are sent and received over the connection.
Moniker
- The moniker syntax for a UDP transport is: udp:<local-host>:<local-port>,<remote-host>:<remote-port>.
+ The moniker syntax for a WebSocket Server transport is: ws-server:<host>:<port>,
+where <host> may be the address of a local network interface, or _to accept connections on all local network interfaces. <port> is the TCP port number on which to accept connections.
Example
- 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
+ ws-server:_:9001
|
|
|
|
|
|
|
|
|
|
|
|
|