bumble 0.0.198__py3-none-any.whl → 0.0.200__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bumble/_version.py +2 -2
- bumble/a2dp.py +502 -202
- bumble/apps/controller_info.py +60 -0
- bumble/apps/pair.py +32 -5
- bumble/apps/player/player.py +608 -0
- bumble/apps/speaker/speaker.py +25 -27
- bumble/att.py +57 -41
- bumble/avc.py +1 -2
- bumble/avdtp.py +56 -99
- bumble/avrcp.py +48 -29
- bumble/codecs.py +214 -68
- bumble/decoder.py +14 -10
- bumble/device.py +19 -11
- bumble/drivers/rtk.py +19 -5
- bumble/gatt.py +24 -19
- bumble/gatt_client.py +5 -25
- bumble/gatt_server.py +14 -6
- bumble/hci.py +298 -7
- bumble/hfp.py +52 -48
- bumble/host.py +28 -6
- bumble/pandora/__init__.py +3 -0
- bumble/pandora/l2cap.py +310 -0
- bumble/profiles/aics.py +520 -0
- bumble/profiles/asha.py +295 -0
- bumble/profiles/hap.py +674 -0
- bumble/profiles/vcp.py +5 -3
- bumble/rtp.py +110 -0
- bumble/smp.py +23 -4
- bumble/transport/android_netsim.py +3 -0
- bumble/transport/pyusb.py +20 -2
- {bumble-0.0.198.dist-info → bumble-0.0.200.dist-info}/METADATA +2 -2
- {bumble-0.0.198.dist-info → bumble-0.0.200.dist-info}/RECORD +36 -31
- {bumble-0.0.198.dist-info → bumble-0.0.200.dist-info}/WHEEL +1 -1
- {bumble-0.0.198.dist-info → bumble-0.0.200.dist-info}/entry_points.txt +1 -0
- bumble/profiles/asha_service.py +0 -193
- {bumble-0.0.198.dist-info → bumble-0.0.200.dist-info}/LICENSE +0 -0
- {bumble-0.0.198.dist-info → bumble-0.0.200.dist-info}/top_level.txt +0 -0
bumble/rtp.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Copyright 2024 Google LLC
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
# -----------------------------------------------------------------------------
|
|
16
|
+
# Imports
|
|
17
|
+
# -----------------------------------------------------------------------------
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
import struct
|
|
20
|
+
from typing import List
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# -----------------------------------------------------------------------------
|
|
24
|
+
class MediaPacket:
|
|
25
|
+
@staticmethod
|
|
26
|
+
def from_bytes(data: bytes) -> MediaPacket:
|
|
27
|
+
version = (data[0] >> 6) & 0x03
|
|
28
|
+
padding = (data[0] >> 5) & 0x01
|
|
29
|
+
extension = (data[0] >> 4) & 0x01
|
|
30
|
+
csrc_count = data[0] & 0x0F
|
|
31
|
+
marker = (data[1] >> 7) & 0x01
|
|
32
|
+
payload_type = data[1] & 0x7F
|
|
33
|
+
sequence_number = struct.unpack_from('>H', data, 2)[0]
|
|
34
|
+
timestamp = struct.unpack_from('>I', data, 4)[0]
|
|
35
|
+
ssrc = struct.unpack_from('>I', data, 8)[0]
|
|
36
|
+
csrc_list = [
|
|
37
|
+
struct.unpack_from('>I', data, 12 + i)[0] for i in range(csrc_count)
|
|
38
|
+
]
|
|
39
|
+
payload = data[12 + csrc_count * 4 :]
|
|
40
|
+
|
|
41
|
+
return MediaPacket(
|
|
42
|
+
version,
|
|
43
|
+
padding,
|
|
44
|
+
extension,
|
|
45
|
+
marker,
|
|
46
|
+
sequence_number,
|
|
47
|
+
timestamp,
|
|
48
|
+
ssrc,
|
|
49
|
+
csrc_list,
|
|
50
|
+
payload_type,
|
|
51
|
+
payload,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
def __init__(
|
|
55
|
+
self,
|
|
56
|
+
version: int,
|
|
57
|
+
padding: int,
|
|
58
|
+
extension: int,
|
|
59
|
+
marker: int,
|
|
60
|
+
sequence_number: int,
|
|
61
|
+
timestamp: int,
|
|
62
|
+
ssrc: int,
|
|
63
|
+
csrc_list: List[int],
|
|
64
|
+
payload_type: int,
|
|
65
|
+
payload: bytes,
|
|
66
|
+
) -> None:
|
|
67
|
+
self.version = version
|
|
68
|
+
self.padding = padding
|
|
69
|
+
self.extension = extension
|
|
70
|
+
self.marker = marker
|
|
71
|
+
self.sequence_number = sequence_number & 0xFFFF
|
|
72
|
+
self.timestamp = timestamp & 0xFFFFFFFF
|
|
73
|
+
self.timestamp_seconds = 0.0
|
|
74
|
+
self.ssrc = ssrc
|
|
75
|
+
self.csrc_list = csrc_list
|
|
76
|
+
self.payload_type = payload_type
|
|
77
|
+
self.payload = payload
|
|
78
|
+
|
|
79
|
+
def __bytes__(self) -> bytes:
|
|
80
|
+
header = bytes(
|
|
81
|
+
[
|
|
82
|
+
self.version << 6
|
|
83
|
+
| self.padding << 5
|
|
84
|
+
| self.extension << 4
|
|
85
|
+
| len(self.csrc_list),
|
|
86
|
+
self.marker << 7 | self.payload_type,
|
|
87
|
+
]
|
|
88
|
+
) + struct.pack(
|
|
89
|
+
'>HII',
|
|
90
|
+
self.sequence_number,
|
|
91
|
+
self.timestamp,
|
|
92
|
+
self.ssrc,
|
|
93
|
+
)
|
|
94
|
+
for csrc in self.csrc_list:
|
|
95
|
+
header += struct.pack('>I', csrc)
|
|
96
|
+
return header + self.payload
|
|
97
|
+
|
|
98
|
+
def __str__(self) -> str:
|
|
99
|
+
return (
|
|
100
|
+
f'RTP(v={self.version},'
|
|
101
|
+
f'p={self.padding},'
|
|
102
|
+
f'x={self.extension},'
|
|
103
|
+
f'm={self.marker},'
|
|
104
|
+
f'pt={self.payload_type},'
|
|
105
|
+
f'sn={self.sequence_number},'
|
|
106
|
+
f'ts={self.timestamp},'
|
|
107
|
+
f'ssrc={self.ssrc},'
|
|
108
|
+
f'csrcs={self.csrc_list},'
|
|
109
|
+
f'payload_size={len(self.payload)})'
|
|
110
|
+
)
|
bumble/smp.py
CHANGED
|
@@ -764,7 +764,9 @@ class Session:
|
|
|
764
764
|
self.peer_io_capability = SMP_NO_INPUT_NO_OUTPUT_IO_CAPABILITY
|
|
765
765
|
|
|
766
766
|
# OOB
|
|
767
|
-
self.oob_data_flag =
|
|
767
|
+
self.oob_data_flag = (
|
|
768
|
+
1 if pairing_config.oob and pairing_config.oob.peer_data else 0
|
|
769
|
+
)
|
|
768
770
|
|
|
769
771
|
# Set up addresses
|
|
770
772
|
self_address = connection.self_resolvable_address or connection.self_address
|
|
@@ -1014,8 +1016,10 @@ class Session:
|
|
|
1014
1016
|
self.send_command(response)
|
|
1015
1017
|
|
|
1016
1018
|
def send_pairing_confirm_command(self) -> None:
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
+
|
|
1020
|
+
if self.pairing_method != PairingMethod.OOB:
|
|
1021
|
+
self.r = crypto.r()
|
|
1022
|
+
logger.debug(f'generated random: {self.r.hex()}')
|
|
1019
1023
|
|
|
1020
1024
|
if self.sc:
|
|
1021
1025
|
|
|
@@ -1735,7 +1739,6 @@ class Session:
|
|
|
1735
1739
|
if self.pairing_method in (
|
|
1736
1740
|
PairingMethod.JUST_WORKS,
|
|
1737
1741
|
PairingMethod.NUMERIC_COMPARISON,
|
|
1738
|
-
PairingMethod.OOB,
|
|
1739
1742
|
):
|
|
1740
1743
|
ra = bytes(16)
|
|
1741
1744
|
rb = ra
|
|
@@ -1743,6 +1746,22 @@ class Session:
|
|
|
1743
1746
|
assert self.passkey
|
|
1744
1747
|
ra = self.passkey.to_bytes(16, byteorder='little')
|
|
1745
1748
|
rb = ra
|
|
1749
|
+
elif self.pairing_method == PairingMethod.OOB:
|
|
1750
|
+
if self.is_initiator:
|
|
1751
|
+
if self.peer_oob_data:
|
|
1752
|
+
rb = self.peer_oob_data.r
|
|
1753
|
+
ra = self.r
|
|
1754
|
+
else:
|
|
1755
|
+
rb = bytes(16)
|
|
1756
|
+
ra = self.r
|
|
1757
|
+
else:
|
|
1758
|
+
if self.peer_oob_data:
|
|
1759
|
+
ra = self.peer_oob_data.r
|
|
1760
|
+
rb = self.r
|
|
1761
|
+
else:
|
|
1762
|
+
ra = bytes(16)
|
|
1763
|
+
rb = self.r
|
|
1764
|
+
|
|
1746
1765
|
else:
|
|
1747
1766
|
return
|
|
1748
1767
|
|
|
@@ -70,6 +70,9 @@ def get_ini_dir() -> Optional[pathlib.Path]:
|
|
|
70
70
|
elif sys.platform == 'linux':
|
|
71
71
|
if xdg_runtime_dir := os.environ.get('XDG_RUNTIME_DIR', None):
|
|
72
72
|
return pathlib.Path(xdg_runtime_dir)
|
|
73
|
+
tmpdir = os.environ.get('TMPDIR', '/tmp')
|
|
74
|
+
if pathlib.Path(tmpdir).is_dir():
|
|
75
|
+
return pathlib.Path(tmpdir)
|
|
73
76
|
elif sys.platform == 'win32':
|
|
74
77
|
if local_app_data_dir := os.environ.get('LOCALAPPDATA', None):
|
|
75
78
|
return pathlib.Path(local_app_data_dir) / 'Temp'
|
bumble/transport/pyusb.py
CHANGED
|
@@ -23,7 +23,7 @@ import time
|
|
|
23
23
|
import usb.core
|
|
24
24
|
import usb.util
|
|
25
25
|
|
|
26
|
-
from typing import Optional
|
|
26
|
+
from typing import Optional, Set
|
|
27
27
|
from usb.core import Device as UsbDevice
|
|
28
28
|
from usb.core import USBError
|
|
29
29
|
from usb.util import CTRL_TYPE_CLASS, CTRL_RECIPIENT_OTHER
|
|
@@ -46,6 +46,11 @@ RESET_DELAY = 3
|
|
|
46
46
|
# -----------------------------------------------------------------------------
|
|
47
47
|
logger = logging.getLogger(__name__)
|
|
48
48
|
|
|
49
|
+
# -----------------------------------------------------------------------------
|
|
50
|
+
# Global
|
|
51
|
+
# -----------------------------------------------------------------------------
|
|
52
|
+
devices_in_use: Set[int] = set()
|
|
53
|
+
|
|
49
54
|
|
|
50
55
|
# -----------------------------------------------------------------------------
|
|
51
56
|
async def open_pyusb_transport(spec: str) -> Transport:
|
|
@@ -217,6 +222,8 @@ async def open_pyusb_transport(spec: str) -> Transport:
|
|
|
217
222
|
await self.source.stop()
|
|
218
223
|
await self.sink.stop()
|
|
219
224
|
usb.util.release_interface(self.device, 0)
|
|
225
|
+
if devices_in_use and device.address in devices_in_use:
|
|
226
|
+
devices_in_use.remove(device.address)
|
|
220
227
|
|
|
221
228
|
usb_find = usb.core.find
|
|
222
229
|
try:
|
|
@@ -233,7 +240,18 @@ async def open_pyusb_transport(spec: str) -> Transport:
|
|
|
233
240
|
spec = spec[1:]
|
|
234
241
|
if ':' in spec:
|
|
235
242
|
vendor_id, product_id = spec.split(':')
|
|
236
|
-
device =
|
|
243
|
+
device = None
|
|
244
|
+
devices = usb_find(
|
|
245
|
+
find_all=True, idVendor=int(vendor_id, 16), idProduct=int(product_id, 16)
|
|
246
|
+
)
|
|
247
|
+
for d in devices:
|
|
248
|
+
if d.address in devices_in_use:
|
|
249
|
+
continue
|
|
250
|
+
device = d
|
|
251
|
+
devices_in_use.add(d.address)
|
|
252
|
+
break
|
|
253
|
+
if device is None:
|
|
254
|
+
raise ValueError('device already in use')
|
|
237
255
|
elif '-' in spec:
|
|
238
256
|
|
|
239
257
|
def device_path(device):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: bumble
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.200
|
|
4
4
|
Summary: Bluetooth Stack for Apps, Emulation, Test and Experimentation
|
|
5
5
|
Home-page: https://github.com/google/bumble
|
|
6
6
|
Author: Google
|
|
@@ -27,7 +27,7 @@ Requires-Dist: pyusb>=1.2; platform_system != "Emscripten"
|
|
|
27
27
|
Requires-Dist: websockets>=12.0; platform_system != "Emscripten"
|
|
28
28
|
Requires-Dist: cryptography>=39.0; platform_system == "Emscripten"
|
|
29
29
|
Provides-Extra: avatar
|
|
30
|
-
Requires-Dist: pandora-avatar==0.0.
|
|
30
|
+
Requires-Dist: pandora-avatar==0.0.10; extra == "avatar"
|
|
31
31
|
Requires-Dist: rootcanal==1.10.0; python_version >= "3.10" and extra == "avatar"
|
|
32
32
|
Provides-Extra: build
|
|
33
33
|
Requires-Dist: build>=0.7; extra == "build"
|
|
@@ -1,38 +1,39 @@
|
|
|
1
1
|
bumble/__init__.py,sha256=Q8jkz6rgl95IMAeInQVt_2GLoJl3DcEP2cxtrQ-ho5c,110
|
|
2
|
-
bumble/_version.py,sha256=
|
|
3
|
-
bumble/a2dp.py,sha256=
|
|
2
|
+
bumble/_version.py,sha256=QkvzoUjUmzIu-0WPLCIoPkyy_n8BoMLliGVrvjz6i7A,415
|
|
3
|
+
bumble/a2dp.py,sha256=_dCq-qyG5OglDVlaOFwAgFe_ugvHuEdEYL-kWFf6sWQ,31775
|
|
4
4
|
bumble/at.py,sha256=Giu2VUSJKH-jIh10lOfumiqy-FyO99Ra6nJ7UiWQ0H8,3114
|
|
5
|
-
bumble/att.py,sha256=
|
|
6
|
-
bumble/avc.py,sha256=
|
|
5
|
+
bumble/att.py,sha256=S-ha1Xn2YHf8k_c6JCXDv1QwiGJAJvgpHVLVxo1kkPQ,32755
|
|
6
|
+
bumble/avc.py,sha256=OZz5_DYenPeg2PcNM3dpgV5PUs4D7FBSNOcSqsuRJ2w,16329
|
|
7
7
|
bumble/avctp.py,sha256=yHAjJRjLGtR0Q-iWcLS7cJRz5Jr2YiRmZd6LZV4Xjt4,9935
|
|
8
|
-
bumble/avdtp.py,sha256=
|
|
9
|
-
bumble/avrcp.py,sha256=
|
|
8
|
+
bumble/avdtp.py,sha256=2ki_BE4SHiu3Sx9oHCknfjF-bBcgPB9TsyF5upciUYI,76773
|
|
9
|
+
bumble/avrcp.py,sha256=P_pLVpP3kRtoD2y0Ca0NTEEe1mA4SXO_ldtc4OP6Tcc,69976
|
|
10
10
|
bumble/bridge.py,sha256=T6es5oS1dy8QgkxQ8iOD-YcZ0SWOv8jaqC7TGxqodk4,3003
|
|
11
|
-
bumble/codecs.py,sha256=
|
|
11
|
+
bumble/codecs.py,sha256=75TGfq-XWWtr-mCRRG7QzJYNRebG50Ypt_QGQkoWlxU,20915
|
|
12
12
|
bumble/colors.py,sha256=CC5tBDnN86bvlbYf1KIVdyj7QBLaqEDT_hQVB0p7FeU,3118
|
|
13
13
|
bumble/company_ids.py,sha256=B68e2QPsDeRYP9jjbGs4GGDwEkGxcXGTsON_CHA0uuI,118528
|
|
14
14
|
bumble/controller.py,sha256=XkYTQb2J5MhH_dGfnFkrLXdChFD2s1wSvqXaHQFeo48,59688
|
|
15
15
|
bumble/core.py,sha256=T43ZszjsU_89B0UJwQ9GCzvKU7oj1_RBzsdGr9jX9xY,72440
|
|
16
16
|
bumble/crypto.py,sha256=L6z3dn9-dgKYRtOM6O3F6n6Ju4PwTM3LAFJtCg_ie78,9382
|
|
17
|
-
bumble/decoder.py,sha256=
|
|
18
|
-
bumble/device.py,sha256=
|
|
17
|
+
bumble/decoder.py,sha256=0-VNWZT-u7lvK3qBpAuYT0M6Rz_bMgMi4CjfUXX_6RM,9728
|
|
18
|
+
bumble/device.py,sha256=vroAnNWlBW6_jw1KgmoG4ZWKyauLm8abS1XFrTX084Y,195024
|
|
19
19
|
bumble/gap.py,sha256=dRU2_TWvqTDx80hxeSbXlWIeWvptWH4_XbItG5y948Q,2138
|
|
20
|
-
bumble/gatt.py,sha256=
|
|
21
|
-
bumble/gatt_client.py,sha256=
|
|
22
|
-
bumble/gatt_server.py,sha256=
|
|
23
|
-
bumble/hci.py,sha256=
|
|
20
|
+
bumble/gatt.py,sha256=a07mQ3O0LFt5zgUzSUwa4Jak_FXOXSFX-njxnQNS_zY,39014
|
|
21
|
+
bumble/gatt_client.py,sha256=gIpgNQj5WNm9RirXXT4vuXQZ4WK82IFMOqnfqBtoYRU,42809
|
|
22
|
+
bumble/gatt_server.py,sha256=pafGMeAuGAAELnr_1pB_l3CcR5u4H4Y1-MRHjN53gdE,37449
|
|
23
|
+
bumble/hci.py,sha256=e2JqP-D1h7b7vHxFbmdsLJtOacdiuMizzGgBWmCAhxQ,286058
|
|
24
24
|
bumble/helpers.py,sha256=m0w4UgFFNDEnXwHrDyfRlcBObdVed2fqXGL0lvR3c8s,12733
|
|
25
|
-
bumble/hfp.py,sha256=
|
|
25
|
+
bumble/hfp.py,sha256=h5IcgxKnlFWapeJHcNDTvxup9oAE5CcZju92sOusTGc,75619
|
|
26
26
|
bumble/hid.py,sha256=hJKm6qhNa0kQTGmp_VxNh3-ywgBDdJpPPFcvtFiRL0A,20335
|
|
27
|
-
bumble/host.py,sha256=
|
|
27
|
+
bumble/host.py,sha256=pPH7HTQ6ogOToj4Y5Jl985MKjbVlG_jeOcJrV0NTSqU,49204
|
|
28
28
|
bumble/keys.py,sha256=WbIQ7Ob81mW75qmEPQ2rBLfnqBMA-ts2yowWXP9UaCY,12654
|
|
29
29
|
bumble/l2cap.py,sha256=Bu6oTD3DzqLOKiarynT1cfQefNgR0gCJoKxnwQJl2_o,81398
|
|
30
30
|
bumble/link.py,sha256=MYKsIKpbbAkh_ldxPZKu_GhS90ImC0IQtCAqbY4Ddg4,24034
|
|
31
31
|
bumble/pairing.py,sha256=tgPUba6xNxMi-2plm3xfRlzHq-uPRNZEIGWaN0qNGCs,9853
|
|
32
32
|
bumble/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
33
|
bumble/rfcomm.py,sha256=dh5t5vlDEfw3yHgQfzegMYPnShP8Zo-3ScABUvmXNLI,40751
|
|
34
|
+
bumble/rtp.py,sha256=388X3aCv-QrWJ37r_VPqXYJtvNGWPsHnJasqs41g_-s,3487
|
|
34
35
|
bumble/sdp.py,sha256=aajRQybcMWh_Kc4IuQahix6bXnHg61OXl1gSdrSysl4,45465
|
|
35
|
-
bumble/smp.py,sha256=
|
|
36
|
+
bumble/smp.py,sha256=FNLn-pt2n6CKNttQGJJDnfaeof2SVkxlapwySHWAVJY,77640
|
|
36
37
|
bumble/snoop.py,sha256=1mzwmp9LToUXbPnFsLrt8S4UHs0kqzbu7LDydwbmkZI,5715
|
|
37
38
|
bumble/utils.py,sha256=e0i-4d28-9zP3gYcd1rdNd669rkPnRs5oJCERUEDfxo,15099
|
|
38
39
|
bumble/apps/README.md,sha256=XTwjRAY-EJWDXpl1V8K3Mw8B7kIqzUIUizRjVBVhoIE,1769
|
|
@@ -41,7 +42,7 @@ bumble/apps/auracast.py,sha256=hrG6dW79UkMXqcMLgYjziWEjcVibFUITvjPb4LX1lxM,24686
|
|
|
41
42
|
bumble/apps/bench.py,sha256=nPACg5gQWxJ-6phze12FVCv1_WS2UjrWR7OUWj0o8PU,56350
|
|
42
43
|
bumble/apps/ble_rpa_tool.py,sha256=ZQtsbfnLPd5qUAkEBPpNgJLRynBBc7q_9cDHKUW2SQ0,1701
|
|
43
44
|
bumble/apps/console.py,sha256=rwD9y3g8Mm_mAEvrcXjbtcv5d8mwF3yTbmE6Vet2BEk,45300
|
|
44
|
-
bumble/apps/controller_info.py,sha256=
|
|
45
|
+
bumble/apps/controller_info.py,sha256=WScuK5Ytp5aFEosAcgRTCEeey6SmxDFmyB7KBhgVx6s,11759
|
|
45
46
|
bumble/apps/controller_loopback.py,sha256=VJAFsUdFwm2KgOrRuLADymMpZl5qVO0RGkDSr-1XKtY,7214
|
|
46
47
|
bumble/apps/controllers.py,sha256=R6XJ1XpyuXlyqSCmI7PromVIcoYTcYfpmO-TqTYXnUI,2326
|
|
47
48
|
bumble/apps/device_info.py,sha256=kQSO7F60cmUKw99LHfyly9s_ox2mD0dNGsgxCnKoFOQ,7999
|
|
@@ -49,7 +50,7 @@ bumble/apps/gatt_dump.py,sha256=wwA-NhRnbgUkbj-Ukym7NDG2j2n_36t_tn93dLDVdIg,4487
|
|
|
49
50
|
bumble/apps/gg_bridge.py,sha256=JdW5QT6xN9c2XDDJoHDRo5W3N_RdVkCtTmlcOsJhlx8,14693
|
|
50
51
|
bumble/apps/hci_bridge.py,sha256=KISv352tKnsQsoxjkDiCQbMFmhnPWdnug5wSFAAXxEs,4033
|
|
51
52
|
bumble/apps/l2cap_bridge.py,sha256=524VgEmgCP4g7T0UdgmsePmNVhDFRJECeaZ_uzKsbco,13062
|
|
52
|
-
bumble/apps/pair.py,sha256=
|
|
53
|
+
bumble/apps/pair.py,sha256=NtDxLfdnlOY_ZEtVNGVXWjv6_x_hndok_ydhV6zkFtI,18503
|
|
53
54
|
bumble/apps/pandora_server.py,sha256=5qaoLCpcZE2KsGO21-7t6Vg4dBjBWbnyOQXwrLhxkuE,1397
|
|
54
55
|
bumble/apps/rfcomm_bridge.py,sha256=PSszh4Qh1IsIw8ETs0fevOCAXEdVtqlgnV-ruzqGrZI,17215
|
|
55
56
|
bumble/apps/scan.py,sha256=b6hIppiJqDfR7VFW2wl3-lkPdFvHLqYZKY8VjjNnhls,8366
|
|
@@ -62,26 +63,29 @@ bumble/apps/lea_unicast/liblc3.wasm,sha256=nYMzG9fP8_71K9dQfVI9QPQPkFRPHoqZEEExs
|
|
|
62
63
|
bumble/apps/link_relay/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
63
64
|
bumble/apps/link_relay/link_relay.py,sha256=GOESYPzkMJFrz5VOI_BSmnmgz4Y8EdSLHMWgdA63aDg,10066
|
|
64
65
|
bumble/apps/link_relay/logging.yml,sha256=t-P72RAHsTZOESw0M4I3CQPonymcjkd9SLE0eY_ZNiM,311
|
|
66
|
+
bumble/apps/player/player.py,sha256=hht867HimxaO-ZgPxZB3OYLNJv6eaR55BUgBlCSGR6U,22370
|
|
65
67
|
bumble/apps/speaker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
66
68
|
bumble/apps/speaker/logo.svg,sha256=SQ9XXIqhh07BnGaBZ653nJ7vOslm2Dogdqadhg2MdE4,4205
|
|
67
69
|
bumble/apps/speaker/speaker.css,sha256=nyM5TjzDYkkLwFzsaIOuTSngzSvgDnkLe0Z-fAn1_t4,1234
|
|
68
70
|
bumble/apps/speaker/speaker.html,sha256=kfAZ5oZSFc9ygBFIUuZEn5LUNQnHBvrnuHU6VAptyiU,1188
|
|
69
71
|
bumble/apps/speaker/speaker.js,sha256=DrT831yg3oBXKZ5usnfZjRU9X6Nw3zjIWSkz6sIgVtw,9373
|
|
70
|
-
bumble/apps/speaker/speaker.py,sha256=
|
|
72
|
+
bumble/apps/speaker/speaker.py,sha256=OTqygA9VbQW_XxTxqxS0vRW_wvhnKHssSxDz1lQZ9ZU,24763
|
|
71
73
|
bumble/drivers/__init__.py,sha256=lxqJTghh21rQFThRTurwLysZm385TUcn8ZdpHQSWD88,3196
|
|
72
74
|
bumble/drivers/common.py,sha256=pS783hudolLZAzF8IUWp7g6TXyQsUCEzqCsd1VGeYfQ,1507
|
|
73
75
|
bumble/drivers/intel.py,sha256=-YcJI4ZC_fhHHxWyE8b4eB8V7suOFH1n9uayckGE9Uw,3231
|
|
74
|
-
bumble/drivers/rtk.py,sha256=
|
|
75
|
-
bumble/pandora/__init__.py,sha256=
|
|
76
|
+
bumble/drivers/rtk.py,sha256=nsfAqNzvxvAwbh6UYgxOCSNwgw7XouIBFA03FrLTs4M,22088
|
|
77
|
+
bumble/pandora/__init__.py,sha256=jaPtYCLfLeLUGj8-TmS3Gkv0l1_DBadYj8ZMAPLPAao,3463
|
|
76
78
|
bumble/pandora/config.py,sha256=KD85n3oRbuvD65sRah2H0gpxEW4YbD7HbYbsxdcpDDA,2388
|
|
77
79
|
bumble/pandora/device.py,sha256=LFqCWrgYkQWrFUSKArsAABXkge8sB2DhvaQoEsC4Jn0,5344
|
|
78
80
|
bumble/pandora/host.py,sha256=LnEQ3DJAhmJVgHA7VyokvypQejsi2VcbauSFYn1a9Jk,39235
|
|
81
|
+
bumble/pandora/l2cap.py,sha256=OT-pPprVAQr7xwjYnNwDQujayG2zWUS5FPXVBGNCW3o,11725
|
|
79
82
|
bumble/pandora/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
80
83
|
bumble/pandora/security.py,sha256=YErueKNLsnmcRe6dKo724Ht-buOqmZl2Gauswcc8FW0,21946
|
|
81
84
|
bumble/pandora/utils.py,sha256=Fq4glL0T5cJ2FODoDotmDNdYFOkTOR7DyyL8vkcxp20,3949
|
|
82
85
|
bumble/profiles/__init__.py,sha256=yBGC8Ti5LvZuoh1F42XtfrBilb39T77_yuxESZeX2yI,581
|
|
86
|
+
bumble/profiles/aics.py,sha256=U0K03XqOKtqahXtq7U47WxftsAD7tkiDeUqxfaF4pwk,18540
|
|
83
87
|
bumble/profiles/ascs.py,sha256=Y2_fd_5LOb9hon60LcQl3R-FoAIsOd_J37RZpveh-7c,25471
|
|
84
|
-
bumble/profiles/
|
|
88
|
+
bumble/profiles/asha.py,sha256=QXUp7ImuMD48L0mpuNxPcIkv8VvoENynCuF2PEVqzFM,10373
|
|
85
89
|
bumble/profiles/bap.py,sha256=wLnrbXso203rgw0WNa91qIdMdjuIoGc9VqOHc9Ey_b4,19421
|
|
86
90
|
bumble/profiles/bass.py,sha256=Wiqum0Wsr5PpVzTAPDcyKLTfJoKXJUYOzqB320aSiUs,14950
|
|
87
91
|
bumble/profiles/battery_service.py,sha256=w-uF4jLoDozJOoykimb2RkrKjVyCke6ts2-h-F1PYyc,2292
|
|
@@ -89,6 +93,7 @@ bumble/profiles/cap.py,sha256=6gH7oOnUKjOggMPuB7rtbwj0AneoNmnWzQ_iR3io8e0,1945
|
|
|
89
93
|
bumble/profiles/csip.py,sha256=qpI9W0_FWIpsuJrHhxfbKaa-TD21epxEa3EuCm8gh6c,10156
|
|
90
94
|
bumble/profiles/device_information_service.py,sha256=RfqnXywcwcSTiFalxd1LVTTdeWLxHGsMvlvr9fI0GJI,6193
|
|
91
95
|
bumble/profiles/gap.py,sha256=jUjfy6MPL7k6wgNn3ny3PVgSX6-SLmjUepFYHjGc3IU,3870
|
|
96
|
+
bumble/profiles/hap.py,sha256=IbE1KzjIMEq6FxtFqTgA2DN0pPnpu0996KJRjuN3oaQ,25614
|
|
92
97
|
bumble/profiles/heart_rate_service.py,sha256=_MG1ApmF1B7b4xRzELuahtRWzLm49i9O4m7I6ZFU4mw,8644
|
|
93
98
|
bumble/profiles/le_audio.py,sha256=1x6OpIc0JMa32YVcfM8lq6jnXHlriHUcOkAs0EttJJk,3093
|
|
94
99
|
bumble/profiles/mcp.py,sha256=vIN1r_if4LmOcGCgZuDYTYLMQzU6-1pKUFx1Z3iSAeY,17415
|
|
@@ -96,20 +101,20 @@ bumble/profiles/pacs.py,sha256=bhlU5M6E9e1YKf-qJnJL3GwTqOPuSvYDpY_UYq0Nnd8,8730
|
|
|
96
101
|
bumble/profiles/pbp.py,sha256=51aoQcZMXzTzeatHd0zNVN7kYcv4atzr2OWpzxlSVP8,1630
|
|
97
102
|
bumble/profiles/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
98
103
|
bumble/profiles/tmap.py,sha256=hpz5VYEdEOty4D9ApCRDero9Tf3L9arSZWnLCNkZoHI,3005
|
|
99
|
-
bumble/profiles/vcp.py,sha256=
|
|
104
|
+
bumble/profiles/vcp.py,sha256=Lx1Odg7PQO9nXkpxRpK04MRuy975uIK8kSqcwrk4iSE,8035
|
|
100
105
|
bumble/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
101
106
|
bumble/tools/generate_company_id_list.py,sha256=ysbPb3zmxKFBiSQ_MBG2r15-sqR5P_GWT6i0YUTTXOM,1736
|
|
102
107
|
bumble/tools/rtk_fw_download.py,sha256=KEPG-rDrdPGKBzZ78P4s3udLRYT3p7vesGhXvJTWTic,5453
|
|
103
108
|
bumble/tools/rtk_util.py,sha256=TwZhupHQrQYsYHLdRGyzXKd24pwCk8kkzqK1Rj2guco,5087
|
|
104
109
|
bumble/transport/__init__.py,sha256=Z01fvuKpqAbhJd0wYcGhW09W2tycM71ck80XoZ8a87Q,7012
|
|
105
110
|
bumble/transport/android_emulator.py,sha256=6HR2cEqdU0XbOldwxCtQuXtvwOUYhRfHkPz0TRt3mbo,4382
|
|
106
|
-
bumble/transport/android_netsim.py,sha256=
|
|
111
|
+
bumble/transport/android_netsim.py,sha256=bQ1XSNloAsqanyEQMmcTpZX6csiZNdowoYDh-JskDZY,16447
|
|
107
112
|
bumble/transport/common.py,sha256=bJWYH-vRJJl0nWwlAjGTHrRQFdZayKkH7YoGor5abH8,16659
|
|
108
113
|
bumble/transport/file.py,sha256=eVM2V6Nk2nDAFdE7Rt01ZI3JdTovsH9OEU1gKYPJjpE,2010
|
|
109
114
|
bumble/transport/hci_socket.py,sha256=EdgWi3-O5yvYcH4R4BkPtG79pnUo7GQtXWawuUHDoDQ,6331
|
|
110
115
|
bumble/transport/pty.py,sha256=grTl-yvjMWHflNwuME4ccVqDbk6NIEgQMgH6Y9lf1fU,2732
|
|
111
116
|
bumble/transport/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
112
|
-
bumble/transport/pyusb.py,sha256=
|
|
117
|
+
bumble/transport/pyusb.py,sha256=7l0y3qo3_LYv1wyKtGC5d0Si2t49F574NIA4XZu70jk,16181
|
|
113
118
|
bumble/transport/serial.py,sha256=loQxkeG7uE09enXWg2uGbxi6CeG70wn3kzPbEwULKw4,2446
|
|
114
119
|
bumble/transport/tcp_client.py,sha256=deyUJYpj04QE00Mw_PTU5PHPA6mr1Nui3f5-QCy2zOw,1854
|
|
115
120
|
bumble/transport/tcp_server.py,sha256=tvu7FuPeqiXfoj2HQU8wu4AiwKjDDDCKlKjgtqWc5hg,3779
|
|
@@ -152,9 +157,9 @@ bumble/vendor/android/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
|
|
|
152
157
|
bumble/vendor/android/hci.py,sha256=GZrkhaWmcMt1JpnRhv0NoySGkf2H4lNUV2f_omRZW0I,10741
|
|
153
158
|
bumble/vendor/zephyr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
154
159
|
bumble/vendor/zephyr/hci.py,sha256=d83bC0TvT947eN4roFjLkQefWtHOoNsr4xib2ctSkvA,3195
|
|
155
|
-
bumble-0.0.
|
|
156
|
-
bumble-0.0.
|
|
157
|
-
bumble-0.0.
|
|
158
|
-
bumble-0.0.
|
|
159
|
-
bumble-0.0.
|
|
160
|
-
bumble-0.0.
|
|
160
|
+
bumble-0.0.200.dist-info/LICENSE,sha256=FvaYh4NRWIGgS_OwoBs5gFgkCmAghZ-DYnIGBZPuw-s,12142
|
|
161
|
+
bumble-0.0.200.dist-info/METADATA,sha256=JusrKVEENpezz89ImgV1FiIA5pBG9OoZK6Ic2ass0ac,5673
|
|
162
|
+
bumble-0.0.200.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
|
|
163
|
+
bumble-0.0.200.dist-info/entry_points.txt,sha256=2TAnDAHiYVEo9Gnugk29QIsHpCgRgnPqBszLSgIX2T0,984
|
|
164
|
+
bumble-0.0.200.dist-info/top_level.txt,sha256=tV6JJKaHPYMFiJYiBYFW24PCcfLxTJZdlu6BmH3Cb00,7
|
|
165
|
+
bumble-0.0.200.dist-info/RECORD,,
|
|
@@ -10,6 +10,7 @@ bumble-l2cap-bridge = bumble.apps.l2cap_bridge:main
|
|
|
10
10
|
bumble-link-relay = bumble.apps.link_relay.link_relay:main
|
|
11
11
|
bumble-pair = bumble.apps.pair:main
|
|
12
12
|
bumble-pandora-server = bumble.apps.pandora_server:main
|
|
13
|
+
bumble-player = bumble.apps.player.player:main
|
|
13
14
|
bumble-rfcomm-bridge = bumble.apps.rfcomm_bridge:main
|
|
14
15
|
bumble-rtk-fw-download = bumble.tools.rtk_fw_download:main
|
|
15
16
|
bumble-rtk-util = bumble.tools.rtk_util:main
|
bumble/profiles/asha_service.py
DELETED
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
# Copyright 2021-2022 Google LLC
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# -----------------------------------------------------------------------------
|
|
17
|
-
# Imports
|
|
18
|
-
# -----------------------------------------------------------------------------
|
|
19
|
-
import struct
|
|
20
|
-
import logging
|
|
21
|
-
from typing import List, Optional
|
|
22
|
-
|
|
23
|
-
from bumble import l2cap
|
|
24
|
-
from ..core import AdvertisingData
|
|
25
|
-
from ..device import Device, Connection
|
|
26
|
-
from ..gatt import (
|
|
27
|
-
GATT_ASHA_SERVICE,
|
|
28
|
-
GATT_ASHA_READ_ONLY_PROPERTIES_CHARACTERISTIC,
|
|
29
|
-
GATT_ASHA_AUDIO_CONTROL_POINT_CHARACTERISTIC,
|
|
30
|
-
GATT_ASHA_AUDIO_STATUS_CHARACTERISTIC,
|
|
31
|
-
GATT_ASHA_VOLUME_CHARACTERISTIC,
|
|
32
|
-
GATT_ASHA_LE_PSM_OUT_CHARACTERISTIC,
|
|
33
|
-
TemplateService,
|
|
34
|
-
Characteristic,
|
|
35
|
-
CharacteristicValue,
|
|
36
|
-
)
|
|
37
|
-
from ..utils import AsyncRunner
|
|
38
|
-
|
|
39
|
-
# -----------------------------------------------------------------------------
|
|
40
|
-
# Logging
|
|
41
|
-
# -----------------------------------------------------------------------------
|
|
42
|
-
logger = logging.getLogger(__name__)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
# -----------------------------------------------------------------------------
|
|
46
|
-
class AshaService(TemplateService):
|
|
47
|
-
UUID = GATT_ASHA_SERVICE
|
|
48
|
-
OPCODE_START = 1
|
|
49
|
-
OPCODE_STOP = 2
|
|
50
|
-
OPCODE_STATUS = 3
|
|
51
|
-
PROTOCOL_VERSION = 0x01
|
|
52
|
-
RESERVED_FOR_FUTURE_USE = [00, 00]
|
|
53
|
-
FEATURE_MAP = [0x01] # [LE CoC audio output streaming supported]
|
|
54
|
-
SUPPORTED_CODEC_ID = [0x02, 0x01] # Codec IDs [G.722 at 16 kHz]
|
|
55
|
-
RENDER_DELAY = [00, 00]
|
|
56
|
-
|
|
57
|
-
def __init__(self, capability: int, hisyncid: List[int], device: Device, psm=0):
|
|
58
|
-
self.hisyncid = hisyncid
|
|
59
|
-
self.capability = capability # Device Capabilities [Left, Monaural]
|
|
60
|
-
self.device = device
|
|
61
|
-
self.audio_out_data = b''
|
|
62
|
-
self.psm = psm # a non-zero psm is mainly for testing purpose
|
|
63
|
-
|
|
64
|
-
# Handler for volume control
|
|
65
|
-
def on_volume_write(connection, value):
|
|
66
|
-
logger.info(f'--- VOLUME Write:{value[0]}')
|
|
67
|
-
self.emit('volume', connection, value[0])
|
|
68
|
-
|
|
69
|
-
# Handler for audio control commands
|
|
70
|
-
def on_audio_control_point_write(connection: Optional[Connection], value):
|
|
71
|
-
logger.info(f'--- AUDIO CONTROL POINT Write:{value.hex()}')
|
|
72
|
-
opcode = value[0]
|
|
73
|
-
if opcode == AshaService.OPCODE_START:
|
|
74
|
-
# Start
|
|
75
|
-
audio_type = ('Unknown', 'Ringtone', 'Phone Call', 'Media')[value[2]]
|
|
76
|
-
logger.info(
|
|
77
|
-
f'### START: codec={value[1]}, '
|
|
78
|
-
f'audio_type={audio_type}, '
|
|
79
|
-
f'volume={value[3]}, '
|
|
80
|
-
f'otherstate={value[4]}'
|
|
81
|
-
)
|
|
82
|
-
self.emit(
|
|
83
|
-
'start',
|
|
84
|
-
connection,
|
|
85
|
-
{
|
|
86
|
-
'codec': value[1],
|
|
87
|
-
'audiotype': value[2],
|
|
88
|
-
'volume': value[3],
|
|
89
|
-
'otherstate': value[4],
|
|
90
|
-
},
|
|
91
|
-
)
|
|
92
|
-
elif opcode == AshaService.OPCODE_STOP:
|
|
93
|
-
logger.info('### STOP')
|
|
94
|
-
self.emit('stop', connection)
|
|
95
|
-
elif opcode == AshaService.OPCODE_STATUS:
|
|
96
|
-
logger.info(f'### STATUS: connected={value[1]}')
|
|
97
|
-
|
|
98
|
-
# OPCODE_STATUS does not need audio status point update
|
|
99
|
-
if opcode != AshaService.OPCODE_STATUS:
|
|
100
|
-
AsyncRunner.spawn(
|
|
101
|
-
device.notify_subscribers(
|
|
102
|
-
self.audio_status_characteristic, force=True
|
|
103
|
-
)
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
self.read_only_properties_characteristic = Characteristic(
|
|
107
|
-
GATT_ASHA_READ_ONLY_PROPERTIES_CHARACTERISTIC,
|
|
108
|
-
Characteristic.Properties.READ,
|
|
109
|
-
Characteristic.READABLE,
|
|
110
|
-
bytes(
|
|
111
|
-
[
|
|
112
|
-
AshaService.PROTOCOL_VERSION, # Version
|
|
113
|
-
self.capability,
|
|
114
|
-
]
|
|
115
|
-
)
|
|
116
|
-
+ bytes(self.hisyncid)
|
|
117
|
-
+ bytes(AshaService.FEATURE_MAP)
|
|
118
|
-
+ bytes(AshaService.RENDER_DELAY)
|
|
119
|
-
+ bytes(AshaService.RESERVED_FOR_FUTURE_USE)
|
|
120
|
-
+ bytes(AshaService.SUPPORTED_CODEC_ID),
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
self.audio_control_point_characteristic = Characteristic(
|
|
124
|
-
GATT_ASHA_AUDIO_CONTROL_POINT_CHARACTERISTIC,
|
|
125
|
-
Characteristic.Properties.WRITE
|
|
126
|
-
| Characteristic.Properties.WRITE_WITHOUT_RESPONSE,
|
|
127
|
-
Characteristic.WRITEABLE,
|
|
128
|
-
CharacteristicValue(write=on_audio_control_point_write),
|
|
129
|
-
)
|
|
130
|
-
self.audio_status_characteristic = Characteristic(
|
|
131
|
-
GATT_ASHA_AUDIO_STATUS_CHARACTERISTIC,
|
|
132
|
-
Characteristic.Properties.READ | Characteristic.Properties.NOTIFY,
|
|
133
|
-
Characteristic.READABLE,
|
|
134
|
-
bytes([0]),
|
|
135
|
-
)
|
|
136
|
-
self.volume_characteristic = Characteristic(
|
|
137
|
-
GATT_ASHA_VOLUME_CHARACTERISTIC,
|
|
138
|
-
Characteristic.Properties.WRITE_WITHOUT_RESPONSE,
|
|
139
|
-
Characteristic.WRITEABLE,
|
|
140
|
-
CharacteristicValue(write=on_volume_write),
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
# Register an L2CAP CoC server
|
|
144
|
-
def on_coc(channel):
|
|
145
|
-
def on_data(data):
|
|
146
|
-
logging.debug(f'<<< data received:{data}')
|
|
147
|
-
|
|
148
|
-
self.emit('data', channel.connection, data)
|
|
149
|
-
self.audio_out_data += data
|
|
150
|
-
|
|
151
|
-
channel.sink = on_data
|
|
152
|
-
|
|
153
|
-
# let the server find a free PSM
|
|
154
|
-
self.psm = device.create_l2cap_server(
|
|
155
|
-
spec=l2cap.LeCreditBasedChannelSpec(psm=self.psm, max_credits=8),
|
|
156
|
-
handler=on_coc,
|
|
157
|
-
).psm
|
|
158
|
-
self.le_psm_out_characteristic = Characteristic(
|
|
159
|
-
GATT_ASHA_LE_PSM_OUT_CHARACTERISTIC,
|
|
160
|
-
Characteristic.Properties.READ,
|
|
161
|
-
Characteristic.READABLE,
|
|
162
|
-
struct.pack('<H', self.psm),
|
|
163
|
-
)
|
|
164
|
-
|
|
165
|
-
characteristics = [
|
|
166
|
-
self.read_only_properties_characteristic,
|
|
167
|
-
self.audio_control_point_characteristic,
|
|
168
|
-
self.audio_status_characteristic,
|
|
169
|
-
self.volume_characteristic,
|
|
170
|
-
self.le_psm_out_characteristic,
|
|
171
|
-
]
|
|
172
|
-
|
|
173
|
-
super().__init__(characteristics)
|
|
174
|
-
|
|
175
|
-
def get_advertising_data(self):
|
|
176
|
-
# Advertisement only uses 4 least significant bytes of the HiSyncId.
|
|
177
|
-
return bytes(
|
|
178
|
-
AdvertisingData(
|
|
179
|
-
[
|
|
180
|
-
(
|
|
181
|
-
AdvertisingData.SERVICE_DATA_16_BIT_UUID,
|
|
182
|
-
bytes(GATT_ASHA_SERVICE)
|
|
183
|
-
+ bytes(
|
|
184
|
-
[
|
|
185
|
-
AshaService.PROTOCOL_VERSION,
|
|
186
|
-
self.capability,
|
|
187
|
-
]
|
|
188
|
-
)
|
|
189
|
-
+ bytes(self.hisyncid[:4]),
|
|
190
|
-
),
|
|
191
|
-
]
|
|
192
|
-
)
|
|
193
|
-
)
|
|
File without changes
|
|
File without changes
|