bumble 0.0.214__py3-none-any.whl → 0.0.215__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 +16 -3
- bumble/a2dp.py +15 -16
- bumble/apps/auracast.py +13 -38
- bumble/apps/bench.py +9 -10
- bumble/apps/ble_rpa_tool.py +1 -0
- bumble/apps/console.py +22 -25
- bumble/apps/controller_info.py +19 -19
- bumble/apps/controller_loopback.py +2 -2
- bumble/apps/controllers.py +1 -1
- bumble/apps/device_info.py +3 -3
- bumble/apps/gatt_dump.py +1 -1
- bumble/apps/gg_bridge.py +5 -6
- bumble/apps/hci_bridge.py +3 -3
- bumble/apps/l2cap_bridge.py +3 -3
- bumble/apps/lea_unicast/app.py +15 -25
- bumble/apps/pair.py +30 -43
- bumble/apps/pandora_server.py +5 -4
- bumble/apps/player/player.py +19 -22
- bumble/apps/rfcomm_bridge.py +3 -8
- bumble/apps/scan.py +16 -6
- bumble/apps/show.py +3 -4
- bumble/apps/speaker/speaker.py +22 -22
- bumble/apps/unbond.py +2 -1
- bumble/apps/usb_probe.py +1 -2
- bumble/att.py +241 -246
- bumble/audio/io.py +5 -9
- bumble/avc.py +2 -2
- bumble/avctp.py +6 -7
- bumble/avdtp.py +19 -22
- bumble/avrcp.py +1096 -588
- bumble/codecs.py +2 -0
- bumble/controller.py +52 -13
- bumble/core.py +567 -248
- bumble/crypto/__init__.py +2 -2
- bumble/crypto/builtin.py +1 -1
- bumble/crypto/cryptography.py +2 -4
- bumble/data_types.py +1025 -0
- bumble/device.py +280 -278
- bumble/drivers/__init__.py +3 -2
- bumble/drivers/intel.py +3 -4
- bumble/drivers/rtk.py +26 -9
- bumble/gap.py +4 -4
- bumble/gatt.py +3 -2
- bumble/gatt_adapters.py +3 -11
- bumble/gatt_client.py +69 -81
- bumble/gatt_server.py +124 -124
- bumble/hci.py +67 -18
- bumble/helpers.py +19 -26
- bumble/hfp.py +10 -21
- bumble/hid.py +22 -16
- bumble/host.py +181 -103
- bumble/keys.py +5 -3
- bumble/l2cap.py +121 -74
- bumble/link.py +8 -9
- bumble/pairing.py +7 -6
- bumble/pandora/__init__.py +8 -7
- bumble/pandora/config.py +3 -1
- bumble/pandora/device.py +3 -2
- bumble/pandora/host.py +38 -36
- bumble/pandora/l2cap.py +22 -21
- bumble/pandora/security.py +15 -15
- bumble/pandora/utils.py +5 -3
- bumble/profiles/aics.py +11 -11
- bumble/profiles/ams.py +7 -8
- bumble/profiles/ancs.py +6 -7
- bumble/profiles/ascs.py +4 -9
- bumble/profiles/asha.py +8 -12
- bumble/profiles/bap.py +11 -23
- bumble/profiles/bass.py +2 -7
- bumble/profiles/battery_service.py +3 -4
- bumble/profiles/cap.py +1 -2
- bumble/profiles/csip.py +2 -6
- bumble/profiles/device_information_service.py +2 -2
- bumble/profiles/gap.py +4 -4
- bumble/profiles/gatt_service.py +1 -4
- bumble/profiles/gmap.py +5 -5
- bumble/profiles/hap.py +62 -59
- bumble/profiles/heart_rate_service.py +5 -4
- bumble/profiles/le_audio.py +3 -1
- bumble/profiles/mcp.py +3 -7
- bumble/profiles/pacs.py +3 -6
- bumble/profiles/pbp.py +2 -0
- bumble/profiles/tmap.py +2 -3
- bumble/profiles/vcs.py +2 -8
- bumble/profiles/vocs.py +8 -8
- bumble/rfcomm.py +11 -14
- bumble/rtp.py +1 -0
- bumble/sdp.py +10 -8
- bumble/smp.py +142 -153
- bumble/snoop.py +5 -5
- bumble/tools/generate_company_id_list.py +1 -0
- bumble/tools/intel_fw_download.py +3 -3
- bumble/tools/intel_util.py +4 -4
- bumble/tools/rtk_fw_download.py +6 -3
- bumble/tools/rtk_util.py +24 -7
- bumble/transport/__init__.py +19 -15
- bumble/transport/android_emulator.py +8 -13
- bumble/transport/android_netsim.py +19 -18
- bumble/transport/common.py +12 -15
- bumble/transport/file.py +1 -1
- bumble/transport/hci_socket.py +4 -6
- bumble/transport/pty.py +5 -6
- bumble/transport/pyusb.py +7 -10
- bumble/transport/serial.py +2 -1
- bumble/transport/tcp_client.py +2 -2
- bumble/transport/tcp_server.py +11 -14
- bumble/transport/udp.py +3 -3
- bumble/transport/unix.py +67 -1
- bumble/transport/usb.py +6 -6
- bumble/transport/vhci.py +0 -1
- bumble/transport/ws_client.py +2 -1
- bumble/transport/ws_server.py +3 -2
- bumble/utils.py +20 -5
- bumble/vendor/android/hci.py +1 -2
- bumble/vendor/zephyr/hci.py +0 -1
- {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/METADATA +2 -1
- bumble-0.0.215.dist-info/RECORD +183 -0
- bumble-0.0.214.dist-info/RECORD +0 -182
- {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/WHEEL +0 -0
- {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/entry_points.txt +0 -0
- {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/licenses/LICENSE +0 -0
- {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/top_level.txt +0 -0
bumble/core.py
CHANGED
|
@@ -17,14 +17,26 @@
|
|
|
17
17
|
# -----------------------------------------------------------------------------
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
|
+
import dataclasses
|
|
20
21
|
import enum
|
|
21
22
|
import struct
|
|
22
|
-
from typing import
|
|
23
|
+
from typing import (
|
|
24
|
+
TYPE_CHECKING,
|
|
25
|
+
Any,
|
|
26
|
+
ClassVar,
|
|
27
|
+
Iterable,
|
|
28
|
+
Literal,
|
|
29
|
+
Optional,
|
|
30
|
+
Type,
|
|
31
|
+
Union,
|
|
32
|
+
cast,
|
|
33
|
+
overload,
|
|
34
|
+
)
|
|
35
|
+
|
|
23
36
|
from typing_extensions import Self
|
|
24
37
|
|
|
25
|
-
from bumble.company_ids import COMPANY_IDENTIFIERS
|
|
26
38
|
from bumble import utils
|
|
27
|
-
|
|
39
|
+
from bumble.company_ids import COMPANY_IDENTIFIERS
|
|
28
40
|
|
|
29
41
|
# -----------------------------------------------------------------------------
|
|
30
42
|
# Constants
|
|
@@ -331,6 +343,9 @@ class UUID:
|
|
|
331
343
|
result += f' ({self.name})'
|
|
332
344
|
return result
|
|
333
345
|
|
|
346
|
+
def __repr__(self) -> str:
|
|
347
|
+
return self.to_hex_str()
|
|
348
|
+
|
|
334
349
|
|
|
335
350
|
# -----------------------------------------------------------------------------
|
|
336
351
|
# Common UUID constants
|
|
@@ -447,26 +462,25 @@ BT_HDP_SINK_SERVICE = UUID.from_16_bits(0x1402,
|
|
|
447
462
|
|
|
448
463
|
|
|
449
464
|
# -----------------------------------------------------------------------------
|
|
450
|
-
#
|
|
465
|
+
# ClassOfDevice
|
|
466
|
+
# See Bluetooth - Assigned Numbers - 2.8 Class of Device
|
|
451
467
|
# -----------------------------------------------------------------------------
|
|
452
|
-
|
|
468
|
+
@dataclasses.dataclass
|
|
469
|
+
class ClassOfDevice:
|
|
453
470
|
# fmt: off
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
INFORMATION_SERVICE_CLASS = (1 << 10)
|
|
468
|
-
|
|
469
|
-
SERVICE_CLASS_LABELS = [
|
|
471
|
+
class MajorServiceClasses(utils.CompatibleIntFlag):
|
|
472
|
+
LIMITED_DISCOVERABLE_MODE = (1 << 0)
|
|
473
|
+
LE_AUDIO = (1 << 1)
|
|
474
|
+
POSITIONING = (1 << 3)
|
|
475
|
+
NETWORKING = (1 << 4)
|
|
476
|
+
RENDERING = (1 << 5)
|
|
477
|
+
CAPTURING = (1 << 6)
|
|
478
|
+
OBJECT_TRANSFER = (1 << 7)
|
|
479
|
+
AUDIO = (1 << 8)
|
|
480
|
+
TELEPHONY = (1 << 9)
|
|
481
|
+
INFORMATION = (1 << 10)
|
|
482
|
+
|
|
483
|
+
MAJOR_SERVICE_CLASS_LABELS: ClassVar[list[str]] = [
|
|
470
484
|
'Limited Discoverable Mode',
|
|
471
485
|
'LE audio',
|
|
472
486
|
'(reserved)',
|
|
@@ -477,220 +491,440 @@ class DeviceClass:
|
|
|
477
491
|
'Object Transfer',
|
|
478
492
|
'Audio',
|
|
479
493
|
'Telephony',
|
|
480
|
-
'Information'
|
|
494
|
+
'Information',
|
|
481
495
|
]
|
|
482
496
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
497
|
+
class MajorDeviceClass(utils.OpenIntEnum):
|
|
498
|
+
MISCELLANEOUS = 0x00
|
|
499
|
+
COMPUTER = 0x01
|
|
500
|
+
PHONE = 0x02
|
|
501
|
+
LAN_NETWORK_ACCESS_POINT = 0x03
|
|
502
|
+
AUDIO_VIDEO = 0x04
|
|
503
|
+
PERIPHERAL = 0x05
|
|
504
|
+
IMAGING = 0x06
|
|
505
|
+
WEARABLE = 0x07
|
|
506
|
+
TOY = 0x08
|
|
507
|
+
HEALTH = 0x09
|
|
508
|
+
UNCATEGORIZED = 0x1F
|
|
509
|
+
|
|
510
|
+
MAJOR_DEVICE_CLASS_LABELS: ClassVar[dict[MajorDeviceClass, str]] = {
|
|
511
|
+
MajorDeviceClass.MISCELLANEOUS: 'Miscellaneous',
|
|
512
|
+
MajorDeviceClass.COMPUTER: 'Computer',
|
|
513
|
+
MajorDeviceClass.PHONE: 'Phone',
|
|
514
|
+
MajorDeviceClass.LAN_NETWORK_ACCESS_POINT: 'LAN/Network Access Point',
|
|
515
|
+
MajorDeviceClass.AUDIO_VIDEO: 'Audio/Video',
|
|
516
|
+
MajorDeviceClass.PERIPHERAL: 'Peripheral',
|
|
517
|
+
MajorDeviceClass.IMAGING: 'Imaging',
|
|
518
|
+
MajorDeviceClass.WEARABLE: 'Wearable',
|
|
519
|
+
MajorDeviceClass.TOY: 'Toy',
|
|
520
|
+
MajorDeviceClass.HEALTH: 'Health',
|
|
521
|
+
MajorDeviceClass.UNCATEGORIZED: 'Uncategorized',
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
class ComputerMinorDeviceClass(utils.OpenIntEnum):
|
|
525
|
+
UNCATEGORIZED = 0x00
|
|
526
|
+
DESKTOP_WORKSTATION = 0x01
|
|
527
|
+
SERVER_CLASS_COMPUTER = 0x02
|
|
528
|
+
LAPTOP_COMPUTER = 0x03
|
|
529
|
+
HANDHELD_PC_PDA = 0x04
|
|
530
|
+
PALM_SIZE_PC_PDA = 0x05
|
|
531
|
+
WEARABLE_COMPUTER = 0x06
|
|
532
|
+
TABLET = 0x07
|
|
533
|
+
|
|
534
|
+
COMPUTER_MINOR_DEVICE_CLASS_LABELS: ClassVar[dict[ComputerMinorDeviceClass, str]] = {
|
|
535
|
+
ComputerMinorDeviceClass.UNCATEGORIZED: 'Uncategorized',
|
|
536
|
+
ComputerMinorDeviceClass.DESKTOP_WORKSTATION: 'Desktop workstation',
|
|
537
|
+
ComputerMinorDeviceClass.SERVER_CLASS_COMPUTER: 'Server-class computer',
|
|
538
|
+
ComputerMinorDeviceClass.LAPTOP_COMPUTER: 'Laptop',
|
|
539
|
+
ComputerMinorDeviceClass.HANDHELD_PC_PDA: 'Handheld PC/PDA',
|
|
540
|
+
ComputerMinorDeviceClass.PALM_SIZE_PC_PDA: 'Palm-size PC/PDA',
|
|
541
|
+
ComputerMinorDeviceClass.WEARABLE_COMPUTER: 'Wearable computer',
|
|
542
|
+
ComputerMinorDeviceClass.TABLET: 'Tablet',
|
|
508
543
|
}
|
|
509
544
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
COMPUTER_PALM_SIZE_PC_PDA_MINOR_DEVICE_CLASS: 'Palm-size PC/PDA',
|
|
526
|
-
COMPUTER_WEARABLE_COMPUTER_MINOR_DEVICE_CLASS: 'Wearable computer',
|
|
527
|
-
COMPUTER_TABLET_MINOR_DEVICE_CLASS: 'Tablet'
|
|
545
|
+
class PhoneMinorDeviceClass(utils.OpenIntEnum):
|
|
546
|
+
UNCATEGORIZED = 0x00
|
|
547
|
+
CELLULAR = 0x01
|
|
548
|
+
CORDLESS = 0x02
|
|
549
|
+
SMARTPHONE = 0x03
|
|
550
|
+
WIRED_MODEM_OR_VOICE_GATEWAY = 0x04
|
|
551
|
+
COMMON_ISDN = 0x05
|
|
552
|
+
|
|
553
|
+
PHONE_MINOR_DEVICE_CLASS_LABELS: ClassVar[dict[PhoneMinorDeviceClass, str]] = {
|
|
554
|
+
PhoneMinorDeviceClass.UNCATEGORIZED: 'Uncategorized',
|
|
555
|
+
PhoneMinorDeviceClass.CELLULAR: 'Cellular',
|
|
556
|
+
PhoneMinorDeviceClass.CORDLESS: 'Cordless',
|
|
557
|
+
PhoneMinorDeviceClass.SMARTPHONE: 'Smartphone',
|
|
558
|
+
PhoneMinorDeviceClass.WIRED_MODEM_OR_VOICE_GATEWAY: 'Wired modem or voice gateway',
|
|
559
|
+
PhoneMinorDeviceClass.COMMON_ISDN: 'Common ISDN access',
|
|
528
560
|
}
|
|
529
561
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
562
|
+
class LanNetworkMinorDeviceClass(utils.OpenIntEnum):
|
|
563
|
+
FULLY_AVAILABLE = 0x00
|
|
564
|
+
_1_TO_17_PERCENT_UTILIZED = 0x01
|
|
565
|
+
_17_TO_33_PERCENT_UTILIZED = 0x02
|
|
566
|
+
_33_TO_50_PERCENT_UTILIZED = 0x03
|
|
567
|
+
_50_TO_67_PERCENT_UTILIZED = 0x04
|
|
568
|
+
_67_TO_83_PERCENT_UTILIZED = 0x05
|
|
569
|
+
_83_TO_99_PERCENT_UTILIZED = 0x06
|
|
570
|
+
_NO_SERVICE_AVAILABLE = 0x07
|
|
571
|
+
|
|
572
|
+
LAN_NETWORK_MINOR_DEVICE_CLASS_LABELS: ClassVar[dict[LanNetworkMinorDeviceClass, str]] = {
|
|
573
|
+
LanNetworkMinorDeviceClass.FULLY_AVAILABLE: 'Fully availbable',
|
|
574
|
+
LanNetworkMinorDeviceClass._1_TO_17_PERCENT_UTILIZED: '1% to 17% utilized',
|
|
575
|
+
LanNetworkMinorDeviceClass._17_TO_33_PERCENT_UTILIZED: '17% to 33% utilized',
|
|
576
|
+
LanNetworkMinorDeviceClass._33_TO_50_PERCENT_UTILIZED: '33% to 50% utilized',
|
|
577
|
+
LanNetworkMinorDeviceClass._50_TO_67_PERCENT_UTILIZED: '50% to 67% utilized',
|
|
578
|
+
LanNetworkMinorDeviceClass._67_TO_83_PERCENT_UTILIZED: '67% to 83% utilized',
|
|
579
|
+
LanNetworkMinorDeviceClass._83_TO_99_PERCENT_UTILIZED: '83% to 99% utilized',
|
|
580
|
+
LanNetworkMinorDeviceClass._NO_SERVICE_AVAILABLE: 'No service available',
|
|
544
581
|
}
|
|
545
582
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
583
|
+
class AudioVideoMinorDeviceClass(utils.OpenIntEnum):
|
|
584
|
+
UNCATEGORIZED = 0x00
|
|
585
|
+
WEARABLE_HEADSET_DEVICE = 0x01
|
|
586
|
+
HANDS_FREE_DEVICE = 0x02
|
|
587
|
+
# (RESERVED) = 0x03
|
|
588
|
+
MICROPHONE = 0x04
|
|
589
|
+
LOUDSPEAKER = 0x05
|
|
590
|
+
HEADPHONES = 0x06
|
|
591
|
+
PORTABLE_AUDIO = 0x07
|
|
592
|
+
CAR_AUDIO = 0x08
|
|
593
|
+
SET_TOP_BOX = 0x09
|
|
594
|
+
HIFI_AUDIO_DEVICE = 0x0A
|
|
595
|
+
VCR = 0x0B
|
|
596
|
+
VIDEO_CAMERA = 0x0C
|
|
597
|
+
CAMCORDER = 0x0D
|
|
598
|
+
VIDEO_MONITOR = 0x0E
|
|
599
|
+
VIDEO_DISPLAY_AND_LOUDSPEAKER = 0x0F
|
|
600
|
+
VIDEO_CONFERENCING = 0x10
|
|
601
|
+
# (RESERVED) = 0x11
|
|
602
|
+
GAMING_OR_TOY = 0x12
|
|
603
|
+
|
|
604
|
+
AUDIO_VIDEO_MINOR_DEVICE_CLASS_LABELS: ClassVar[dict[AudioVideoMinorDeviceClass, str]] = {
|
|
605
|
+
AudioVideoMinorDeviceClass.UNCATEGORIZED: 'Uncategorized',
|
|
606
|
+
AudioVideoMinorDeviceClass.WEARABLE_HEADSET_DEVICE: 'Wearable Headset Device',
|
|
607
|
+
AudioVideoMinorDeviceClass.HANDS_FREE_DEVICE: 'Hands-free Device',
|
|
608
|
+
AudioVideoMinorDeviceClass.MICROPHONE: 'Microphone',
|
|
609
|
+
AudioVideoMinorDeviceClass.LOUDSPEAKER: 'Loudspeaker',
|
|
610
|
+
AudioVideoMinorDeviceClass.HEADPHONES: 'Headphones',
|
|
611
|
+
AudioVideoMinorDeviceClass.PORTABLE_AUDIO: 'Portable Audio',
|
|
612
|
+
AudioVideoMinorDeviceClass.CAR_AUDIO: 'Car audio',
|
|
613
|
+
AudioVideoMinorDeviceClass.SET_TOP_BOX: 'Set-top box',
|
|
614
|
+
AudioVideoMinorDeviceClass.HIFI_AUDIO_DEVICE: 'HiFi Audio Device',
|
|
615
|
+
AudioVideoMinorDeviceClass.VCR: 'VCR',
|
|
616
|
+
AudioVideoMinorDeviceClass.VIDEO_CAMERA: 'Video Camera',
|
|
617
|
+
AudioVideoMinorDeviceClass.CAMCORDER: 'Camcorder',
|
|
618
|
+
AudioVideoMinorDeviceClass.VIDEO_MONITOR: 'Video Monitor',
|
|
619
|
+
AudioVideoMinorDeviceClass.VIDEO_DISPLAY_AND_LOUDSPEAKER: 'Video Display and Loudspeaker',
|
|
620
|
+
AudioVideoMinorDeviceClass.VIDEO_CONFERENCING: 'Video Conferencing',
|
|
621
|
+
AudioVideoMinorDeviceClass.GAMING_OR_TOY: 'Gaming/Toy',
|
|
584
622
|
}
|
|
585
623
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
624
|
+
class PeripheralMinorDeviceClass(utils.OpenIntEnum):
|
|
625
|
+
UNCATEGORIZED = 0x00
|
|
626
|
+
KEYBOARD = 0x10
|
|
627
|
+
POINTING_DEVICE = 0x20
|
|
628
|
+
COMBO_KEYBOARD_POINTING_DEVICE = 0x30
|
|
629
|
+
JOYSTICK = 0x01
|
|
630
|
+
GAMEPAD = 0x02
|
|
631
|
+
REMOTE_CONTROL = 0x03
|
|
632
|
+
SENSING_DEVICE = 0x04
|
|
633
|
+
DIGITIZER_TABLET = 0x05
|
|
634
|
+
CARD_READER = 0x06
|
|
635
|
+
DIGITAL_PEN = 0x07
|
|
636
|
+
HANDHELD_SCANNER = 0x08
|
|
637
|
+
HANDHELD_GESTURAL_INPUT_DEVICE = 0x09
|
|
638
|
+
|
|
639
|
+
PERIPHERAL_MINOR_DEVICE_CLASS_LABELS: ClassVar[dict[PeripheralMinorDeviceClass, str]] = {
|
|
640
|
+
PeripheralMinorDeviceClass.UNCATEGORIZED: 'Uncategorized',
|
|
641
|
+
PeripheralMinorDeviceClass.KEYBOARD: 'Keyboard',
|
|
642
|
+
PeripheralMinorDeviceClass.POINTING_DEVICE: 'Pointing device',
|
|
643
|
+
PeripheralMinorDeviceClass.COMBO_KEYBOARD_POINTING_DEVICE: 'Combo keyboard/pointing device',
|
|
644
|
+
PeripheralMinorDeviceClass.JOYSTICK: 'Joystick',
|
|
645
|
+
PeripheralMinorDeviceClass.GAMEPAD: 'Gamepad',
|
|
646
|
+
PeripheralMinorDeviceClass.REMOTE_CONTROL: 'Remote control',
|
|
647
|
+
PeripheralMinorDeviceClass.SENSING_DEVICE: 'Sensing device',
|
|
648
|
+
PeripheralMinorDeviceClass.DIGITIZER_TABLET: 'Digitizer tablet',
|
|
649
|
+
PeripheralMinorDeviceClass.CARD_READER: 'Card Reader',
|
|
650
|
+
PeripheralMinorDeviceClass.DIGITAL_PEN: 'Digital Pen',
|
|
651
|
+
PeripheralMinorDeviceClass.HANDHELD_SCANNER: 'Handheld scanner',
|
|
652
|
+
PeripheralMinorDeviceClass.HANDHELD_GESTURAL_INPUT_DEVICE: 'Handheld gestural input device',
|
|
614
653
|
}
|
|
615
654
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
655
|
+
class WearableMinorDeviceClass(utils.OpenIntEnum):
|
|
656
|
+
UNCATEGORIZED = 0x00
|
|
657
|
+
WRISTWATCH = 0x01
|
|
658
|
+
PAGER = 0x02
|
|
659
|
+
JACKET = 0x03
|
|
660
|
+
HELMET = 0x04
|
|
661
|
+
GLASSES = 0x05
|
|
662
|
+
|
|
663
|
+
WEARABLE_MINOR_DEVICE_CLASS_LABELS: ClassVar[dict[WearableMinorDeviceClass, str]] = {
|
|
664
|
+
WearableMinorDeviceClass.UNCATEGORIZED: 'Uncategorized',
|
|
665
|
+
WearableMinorDeviceClass.WRISTWATCH: 'Wristwatch',
|
|
666
|
+
WearableMinorDeviceClass.PAGER: 'Pager',
|
|
667
|
+
WearableMinorDeviceClass.JACKET: 'Jacket',
|
|
668
|
+
WearableMinorDeviceClass.HELMET: 'Helmet',
|
|
669
|
+
WearableMinorDeviceClass.GLASSES: 'Glasses',
|
|
630
670
|
}
|
|
631
671
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
672
|
+
class ToyMinorDeviceClass(utils.OpenIntEnum):
|
|
673
|
+
UNCATEGORIZED = 0x00
|
|
674
|
+
ROBOT = 0x01
|
|
675
|
+
VEHICLE = 0x02
|
|
676
|
+
DOLL_ACTION_FIGURE = 0x03
|
|
677
|
+
CONTROLLER = 0x04
|
|
678
|
+
GAME = 0x05
|
|
679
|
+
|
|
680
|
+
TOY_MINOR_DEVICE_CLASS_LABELS: ClassVar[dict[ToyMinorDeviceClass, str]] = {
|
|
681
|
+
ToyMinorDeviceClass.UNCATEGORIZED: 'Uncategorized',
|
|
682
|
+
ToyMinorDeviceClass.ROBOT: 'Robot',
|
|
683
|
+
ToyMinorDeviceClass.VEHICLE: 'Vehicle',
|
|
684
|
+
ToyMinorDeviceClass.DOLL_ACTION_FIGURE: 'Doll/Action figure',
|
|
685
|
+
ToyMinorDeviceClass.CONTROLLER: 'Controller',
|
|
686
|
+
ToyMinorDeviceClass.GAME: 'Game',
|
|
646
687
|
}
|
|
647
688
|
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
689
|
+
class HealthMinorDeviceClass(utils.OpenIntEnum):
|
|
690
|
+
UNDEFINED = 0x00
|
|
691
|
+
BLOOD_PRESSURE_MONITOR = 0x01
|
|
692
|
+
THERMOMETER = 0x02
|
|
693
|
+
WEIGHING_SCALE = 0x03
|
|
694
|
+
GLUCOSE_METER = 0x04
|
|
695
|
+
PULSE_OXIMETER = 0x05
|
|
696
|
+
HEART_PULSE_RATE_MONITOR = 0x06
|
|
697
|
+
HEALTH_DATA_DISPLAY = 0x07
|
|
698
|
+
STEP_COUNTER = 0x08
|
|
699
|
+
BODY_COMPOSITION_ANALYZER = 0x09
|
|
700
|
+
PEAK_FLOW_MONITOR = 0x0A
|
|
701
|
+
MEDICATION_MONITOR = 0x0B
|
|
702
|
+
KNEE_PROSTHESIS = 0x0C
|
|
703
|
+
ANKLE_PROSTHESIS = 0x0D
|
|
704
|
+
GENERIC_HEALTH_MANAGER = 0x0E
|
|
705
|
+
PERSONAL_MOBILITY_DEVICE = 0x0F
|
|
706
|
+
|
|
707
|
+
HEALTH_MINOR_DEVICE_CLASS_LABELS: ClassVar[dict[HealthMinorDeviceClass, str]] = {
|
|
708
|
+
HealthMinorDeviceClass.UNDEFINED: 'Undefined',
|
|
709
|
+
HealthMinorDeviceClass.BLOOD_PRESSURE_MONITOR: 'Blood Pressure Monitor',
|
|
710
|
+
HealthMinorDeviceClass.THERMOMETER: 'Thermometer',
|
|
711
|
+
HealthMinorDeviceClass.WEIGHING_SCALE: 'Weighing Scale',
|
|
712
|
+
HealthMinorDeviceClass.GLUCOSE_METER: 'Glucose Meter',
|
|
713
|
+
HealthMinorDeviceClass.PULSE_OXIMETER: 'Pulse Oximeter',
|
|
714
|
+
HealthMinorDeviceClass.HEART_PULSE_RATE_MONITOR: 'Heart/Pulse Rate Monitor',
|
|
715
|
+
HealthMinorDeviceClass.HEALTH_DATA_DISPLAY: 'Health Data Display',
|
|
716
|
+
HealthMinorDeviceClass.STEP_COUNTER: 'Step Counter',
|
|
717
|
+
HealthMinorDeviceClass.BODY_COMPOSITION_ANALYZER: 'Body Composition Analyzer',
|
|
718
|
+
HealthMinorDeviceClass.PEAK_FLOW_MONITOR: 'Peak Flow Monitor',
|
|
719
|
+
HealthMinorDeviceClass.MEDICATION_MONITOR: 'Medication Monitor',
|
|
720
|
+
HealthMinorDeviceClass.KNEE_PROSTHESIS: 'Knee Prosthesis',
|
|
721
|
+
HealthMinorDeviceClass.ANKLE_PROSTHESIS: 'Ankle Prosthesis',
|
|
722
|
+
HealthMinorDeviceClass.GENERIC_HEALTH_MANAGER: 'Generic Health Manager',
|
|
723
|
+
HealthMinorDeviceClass.PERSONAL_MOBILITY_DEVICE: 'Personal Mobility Device',
|
|
682
724
|
}
|
|
683
725
|
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
726
|
+
MINOR_DEVICE_CLASS_LABELS: ClassVar[dict[MajorDeviceClass, dict[Any, str]]] = {
|
|
727
|
+
MajorDeviceClass.COMPUTER: COMPUTER_MINOR_DEVICE_CLASS_LABELS,
|
|
728
|
+
MajorDeviceClass.PHONE: PHONE_MINOR_DEVICE_CLASS_LABELS,
|
|
729
|
+
MajorDeviceClass.LAN_NETWORK_ACCESS_POINT: LAN_NETWORK_MINOR_DEVICE_CLASS_LABELS,
|
|
730
|
+
MajorDeviceClass.AUDIO_VIDEO: AUDIO_VIDEO_MINOR_DEVICE_CLASS_LABELS,
|
|
731
|
+
MajorDeviceClass.PERIPHERAL: PERIPHERAL_MINOR_DEVICE_CLASS_LABELS,
|
|
732
|
+
MajorDeviceClass.WEARABLE: WEARABLE_MINOR_DEVICE_CLASS_LABELS,
|
|
733
|
+
MajorDeviceClass.TOY: TOY_MINOR_DEVICE_CLASS_LABELS,
|
|
734
|
+
MajorDeviceClass.HEALTH: HEALTH_MINOR_DEVICE_CLASS_LABELS,
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
_MINOR_DEVICE_CLASSES: ClassVar[dict[MajorDeviceClass, Type]] = {
|
|
738
|
+
MajorDeviceClass.COMPUTER: ComputerMinorDeviceClass,
|
|
739
|
+
MajorDeviceClass.PHONE: PhoneMinorDeviceClass,
|
|
740
|
+
MajorDeviceClass.LAN_NETWORK_ACCESS_POINT: LanNetworkMinorDeviceClass,
|
|
741
|
+
MajorDeviceClass.AUDIO_VIDEO: AudioVideoMinorDeviceClass,
|
|
742
|
+
MajorDeviceClass.PERIPHERAL: PeripheralMinorDeviceClass,
|
|
743
|
+
MajorDeviceClass.WEARABLE: WearableMinorDeviceClass,
|
|
744
|
+
MajorDeviceClass.TOY: ToyMinorDeviceClass,
|
|
745
|
+
MajorDeviceClass.HEALTH: HealthMinorDeviceClass,
|
|
692
746
|
}
|
|
693
747
|
|
|
748
|
+
# fmt: on
|
|
749
|
+
|
|
750
|
+
major_service_classes: MajorServiceClasses
|
|
751
|
+
major_device_class: MajorDeviceClass
|
|
752
|
+
minor_device_class: Union[
|
|
753
|
+
ComputerMinorDeviceClass,
|
|
754
|
+
PhoneMinorDeviceClass,
|
|
755
|
+
LanNetworkMinorDeviceClass,
|
|
756
|
+
AudioVideoMinorDeviceClass,
|
|
757
|
+
PeripheralMinorDeviceClass,
|
|
758
|
+
WearableMinorDeviceClass,
|
|
759
|
+
ToyMinorDeviceClass,
|
|
760
|
+
HealthMinorDeviceClass,
|
|
761
|
+
int,
|
|
762
|
+
]
|
|
763
|
+
|
|
764
|
+
@classmethod
|
|
765
|
+
def from_int(cls, class_of_device: int) -> Self:
|
|
766
|
+
major_service_classes = cls.MajorServiceClasses(class_of_device >> 13 & 0x7FF)
|
|
767
|
+
major_device_class = cls.MajorDeviceClass(class_of_device >> 8 & 0x1F)
|
|
768
|
+
minor_device_class_int = class_of_device >> 2 & 0x3F
|
|
769
|
+
if minor_device_class_object := cls._MINOR_DEVICE_CLASSES.get(
|
|
770
|
+
major_device_class
|
|
771
|
+
):
|
|
772
|
+
minor_device_class = minor_device_class_object(minor_device_class_int)
|
|
773
|
+
else:
|
|
774
|
+
minor_device_class = minor_device_class_int
|
|
775
|
+
return cls(major_service_classes, major_device_class, minor_device_class)
|
|
776
|
+
|
|
777
|
+
def __int__(self) -> int:
|
|
778
|
+
return (
|
|
779
|
+
self.major_service_classes << 13
|
|
780
|
+
| self.major_device_class << 8
|
|
781
|
+
| self.minor_device_class << 2
|
|
782
|
+
)
|
|
783
|
+
|
|
784
|
+
def __str__(self) -> str:
|
|
785
|
+
minor_device_class_name = (
|
|
786
|
+
self.minor_device_class.name
|
|
787
|
+
if hasattr(self.minor_device_class, 'name')
|
|
788
|
+
else hex(self.minor_device_class)
|
|
789
|
+
)
|
|
790
|
+
return (
|
|
791
|
+
f"ClassOfDevice({self.major_service_classes.composite_name},"
|
|
792
|
+
f"{self.major_device_class.name}/{minor_device_class_name})"
|
|
793
|
+
)
|
|
794
|
+
|
|
795
|
+
def major_service_classes_labels(self) -> str:
|
|
796
|
+
return "|".join(
|
|
797
|
+
bit_flags_to_strings(
|
|
798
|
+
self.major_service_classes, self.MAJOR_SERVICE_CLASS_LABELS
|
|
799
|
+
)
|
|
800
|
+
)
|
|
801
|
+
|
|
802
|
+
def major_device_class_label(self) -> str:
|
|
803
|
+
return name_or_number(
|
|
804
|
+
cast(dict[int, str], self.MAJOR_DEVICE_CLASS_LABELS),
|
|
805
|
+
self.major_device_class,
|
|
806
|
+
)
|
|
807
|
+
|
|
808
|
+
def minor_device_class_label(self) -> str:
|
|
809
|
+
class_names = self.MINOR_DEVICE_CLASS_LABELS.get(self.major_device_class)
|
|
810
|
+
if class_names is None:
|
|
811
|
+
return f'#{self.minor_device_class:02X}'
|
|
812
|
+
return name_or_number(class_names, self.minor_device_class)
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
# -----------------------------------------------------------------------------
|
|
816
|
+
# DeviceClass
|
|
817
|
+
# -----------------------------------------------------------------------------
|
|
818
|
+
class DeviceClass:
|
|
819
|
+
"""Legacy only. Use ClassOfDevice instead"""
|
|
820
|
+
|
|
821
|
+
# fmt: off
|
|
822
|
+
# pylint: disable=line-too-long
|
|
823
|
+
|
|
824
|
+
# Major Service Classes (flags combined with OR)
|
|
825
|
+
LIMITED_DISCOVERABLE_MODE_SERVICE_CLASS = ClassOfDevice.MajorServiceClasses.LIMITED_DISCOVERABLE_MODE
|
|
826
|
+
LE_AUDIO_SERVICE_CLASS = ClassOfDevice.MajorServiceClasses.LE_AUDIO
|
|
827
|
+
POSITIONING_SERVICE_CLASS = ClassOfDevice.MajorServiceClasses.POSITIONING
|
|
828
|
+
NETWORKING_SERVICE_CLASS = ClassOfDevice.MajorServiceClasses.NETWORKING
|
|
829
|
+
RENDERING_SERVICE_CLASS = ClassOfDevice.MajorServiceClasses.RENDERING
|
|
830
|
+
CAPTURING_SERVICE_CLASS = ClassOfDevice.MajorServiceClasses.CAPTURING
|
|
831
|
+
OBJECT_TRANSFER_SERVICE_CLASS = ClassOfDevice.MajorServiceClasses.OBJECT_TRANSFER
|
|
832
|
+
AUDIO_SERVICE_CLASS = ClassOfDevice.MajorServiceClasses.AUDIO
|
|
833
|
+
TELEPHONY_SERVICE_CLASS = ClassOfDevice.MajorServiceClasses.TELEPHONY
|
|
834
|
+
INFORMATION_SERVICE_CLASS = ClassOfDevice.MajorServiceClasses.INFORMATION
|
|
835
|
+
|
|
836
|
+
# Major Device Classes
|
|
837
|
+
MISCELLANEOUS_MAJOR_DEVICE_CLASS = ClassOfDevice.MajorDeviceClass.MISCELLANEOUS
|
|
838
|
+
COMPUTER_MAJOR_DEVICE_CLASS = ClassOfDevice.MajorDeviceClass.COMPUTER
|
|
839
|
+
PHONE_MAJOR_DEVICE_CLASS = ClassOfDevice.MajorDeviceClass.PHONE
|
|
840
|
+
LAN_NETWORK_ACCESS_POINT_MAJOR_DEVICE_CLASS = ClassOfDevice.MajorDeviceClass.LAN_NETWORK_ACCESS_POINT
|
|
841
|
+
AUDIO_VIDEO_MAJOR_DEVICE_CLASS = ClassOfDevice.MajorDeviceClass.AUDIO_VIDEO
|
|
842
|
+
PERIPHERAL_MAJOR_DEVICE_CLASS = ClassOfDevice.MajorDeviceClass.PERIPHERAL
|
|
843
|
+
IMAGING_MAJOR_DEVICE_CLASS = ClassOfDevice.MajorDeviceClass.IMAGING
|
|
844
|
+
WEARABLE_MAJOR_DEVICE_CLASS = ClassOfDevice.MajorDeviceClass.WEARABLE
|
|
845
|
+
TOY_MAJOR_DEVICE_CLASS = ClassOfDevice.MajorDeviceClass.TOY
|
|
846
|
+
HEALTH_MAJOR_DEVICE_CLASS = ClassOfDevice.MajorDeviceClass.HEALTH
|
|
847
|
+
UNCATEGORIZED_MAJOR_DEVICE_CLASS = ClassOfDevice.MajorDeviceClass.UNCATEGORIZED
|
|
848
|
+
|
|
849
|
+
COMPUTER_UNCATEGORIZED_MINOR_DEVICE_CLASS = ClassOfDevice.ComputerMinorDeviceClass.UNCATEGORIZED
|
|
850
|
+
COMPUTER_DESKTOP_WORKSTATION_MINOR_DEVICE_CLASS = ClassOfDevice.ComputerMinorDeviceClass.DESKTOP_WORKSTATION
|
|
851
|
+
COMPUTER_SERVER_CLASS_COMPUTER_MINOR_DEVICE_CLASS = ClassOfDevice.ComputerMinorDeviceClass.SERVER_CLASS_COMPUTER
|
|
852
|
+
COMPUTER_LAPTOP_COMPUTER_MINOR_DEVICE_CLASS = ClassOfDevice.ComputerMinorDeviceClass.LAPTOP_COMPUTER
|
|
853
|
+
COMPUTER_HANDHELD_PC_PDA_MINOR_DEVICE_CLASS = ClassOfDevice.ComputerMinorDeviceClass.HANDHELD_PC_PDA
|
|
854
|
+
COMPUTER_PALM_SIZE_PC_PDA_MINOR_DEVICE_CLASS = ClassOfDevice.ComputerMinorDeviceClass.PALM_SIZE_PC_PDA
|
|
855
|
+
COMPUTER_WEARABLE_COMPUTER_MINOR_DEVICE_CLASS = ClassOfDevice.ComputerMinorDeviceClass.WEARABLE_COMPUTER
|
|
856
|
+
COMPUTER_TABLET_MINOR_DEVICE_CLASS = ClassOfDevice.ComputerMinorDeviceClass.TABLET
|
|
857
|
+
|
|
858
|
+
PHONE_UNCATEGORIZED_MINOR_DEVICE_CLASS = ClassOfDevice.PhoneMinorDeviceClass.UNCATEGORIZED
|
|
859
|
+
PHONE_CELLULAR_MINOR_DEVICE_CLASS = ClassOfDevice.PhoneMinorDeviceClass.CELLULAR
|
|
860
|
+
PHONE_CORDLESS_MINOR_DEVICE_CLASS = ClassOfDevice.PhoneMinorDeviceClass.CORDLESS
|
|
861
|
+
PHONE_SMARTPHONE_MINOR_DEVICE_CLASS = ClassOfDevice.PhoneMinorDeviceClass.SMARTPHONE
|
|
862
|
+
PHONE_WIRED_MODEM_OR_VOICE_GATEWAY_MINOR_DEVICE_CLASS = ClassOfDevice.PhoneMinorDeviceClass.WIRED_MODEM_OR_VOICE_GATEWAY
|
|
863
|
+
PHONE_COMMON_ISDN_MINOR_DEVICE_CLASS = ClassOfDevice.PhoneMinorDeviceClass.COMMON_ISDN
|
|
864
|
+
|
|
865
|
+
AUDIO_VIDEO_UNCATEGORIZED_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.UNCATEGORIZED
|
|
866
|
+
AUDIO_VIDEO_WEARABLE_HEADSET_DEVICE_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.WEARABLE_HEADSET_DEVICE
|
|
867
|
+
AUDIO_VIDEO_HANDS_FREE_DEVICE_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.HANDS_FREE_DEVICE
|
|
868
|
+
AUDIO_VIDEO_MICROPHONE_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.MICROPHONE
|
|
869
|
+
AUDIO_VIDEO_LOUDSPEAKER_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.LOUDSPEAKER
|
|
870
|
+
AUDIO_VIDEO_HEADPHONES_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.HEADPHONES
|
|
871
|
+
AUDIO_VIDEO_PORTABLE_AUDIO_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.PORTABLE_AUDIO
|
|
872
|
+
AUDIO_VIDEO_CAR_AUDIO_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.CAR_AUDIO
|
|
873
|
+
AUDIO_VIDEO_SET_TOP_BOX_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.SET_TOP_BOX
|
|
874
|
+
AUDIO_VIDEO_HIFI_AUDIO_DEVICE_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.HIFI_AUDIO_DEVICE
|
|
875
|
+
AUDIO_VIDEO_VCR_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.VCR
|
|
876
|
+
AUDIO_VIDEO_VIDEO_CAMERA_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.VIDEO_CAMERA
|
|
877
|
+
AUDIO_VIDEO_CAMCORDER_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.CAMCORDER
|
|
878
|
+
AUDIO_VIDEO_VIDEO_MONITOR_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.VIDEO_MONITOR
|
|
879
|
+
AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.VIDEO_DISPLAY_AND_LOUDSPEAKER
|
|
880
|
+
AUDIO_VIDEO_VIDEO_CONFERENCING_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.VIDEO_CONFERENCING
|
|
881
|
+
AUDIO_VIDEO_GAMING_OR_TOY_MINOR_DEVICE_CLASS = ClassOfDevice.AudioVideoMinorDeviceClass.GAMING_OR_TOY
|
|
882
|
+
|
|
883
|
+
PERIPHERAL_UNCATEGORIZED_MINOR_DEVICE_CLASS = ClassOfDevice.PeripheralMinorDeviceClass.UNCATEGORIZED
|
|
884
|
+
PERIPHERAL_KEYBOARD_MINOR_DEVICE_CLASS = ClassOfDevice.PeripheralMinorDeviceClass.KEYBOARD
|
|
885
|
+
PERIPHERAL_POINTING_DEVICE_MINOR_DEVICE_CLASS = ClassOfDevice.PeripheralMinorDeviceClass.POINTING_DEVICE
|
|
886
|
+
PERIPHERAL_COMBO_KEYBOARD_POINTING_DEVICE_MINOR_DEVICE_CLASS = ClassOfDevice.PeripheralMinorDeviceClass.COMBO_KEYBOARD_POINTING_DEVICE
|
|
887
|
+
PERIPHERAL_JOYSTICK_MINOR_DEVICE_CLASS = ClassOfDevice.PeripheralMinorDeviceClass.JOYSTICK
|
|
888
|
+
PERIPHERAL_GAMEPAD_MINOR_DEVICE_CLASS = ClassOfDevice.PeripheralMinorDeviceClass.GAMEPAD
|
|
889
|
+
PERIPHERAL_REMOTE_CONTROL_MINOR_DEVICE_CLASS = ClassOfDevice.PeripheralMinorDeviceClass.REMOTE_CONTROL
|
|
890
|
+
PERIPHERAL_SENSING_DEVICE_MINOR_DEVICE_CLASS = ClassOfDevice.PeripheralMinorDeviceClass.SENSING_DEVICE
|
|
891
|
+
PERIPHERAL_DIGITIZER_TABLET_MINOR_DEVICE_CLASS = ClassOfDevice.PeripheralMinorDeviceClass.DIGITIZER_TABLET
|
|
892
|
+
PERIPHERAL_CARD_READER_MINOR_DEVICE_CLASS = ClassOfDevice.PeripheralMinorDeviceClass.CARD_READER
|
|
893
|
+
PERIPHERAL_DIGITAL_PEN_MINOR_DEVICE_CLASS = ClassOfDevice.PeripheralMinorDeviceClass.DIGITAL_PEN
|
|
894
|
+
PERIPHERAL_HANDHELD_SCANNER_MINOR_DEVICE_CLASS = ClassOfDevice.PeripheralMinorDeviceClass.HANDHELD_SCANNER
|
|
895
|
+
PERIPHERAL_HANDHELD_GESTURAL_INPUT_DEVICE_MINOR_DEVICE_CLASS = ClassOfDevice.PeripheralMinorDeviceClass.HANDHELD_GESTURAL_INPUT_DEVICE
|
|
896
|
+
|
|
897
|
+
WEARABLE_UNCATEGORIZED_MINOR_DEVICE_CLASS = ClassOfDevice.WearableMinorDeviceClass.UNCATEGORIZED
|
|
898
|
+
WEARABLE_WRISTWATCH_MINOR_DEVICE_CLASS = ClassOfDevice.WearableMinorDeviceClass.WRISTWATCH
|
|
899
|
+
WEARABLE_PAGER_MINOR_DEVICE_CLASS = ClassOfDevice.WearableMinorDeviceClass.PAGER
|
|
900
|
+
WEARABLE_JACKET_MINOR_DEVICE_CLASS = ClassOfDevice.WearableMinorDeviceClass.JACKET
|
|
901
|
+
WEARABLE_HELMET_MINOR_DEVICE_CLASS = ClassOfDevice.WearableMinorDeviceClass.HELMET
|
|
902
|
+
WEARABLE_GLASSES_MINOR_DEVICE_CLASS = ClassOfDevice.WearableMinorDeviceClass.GLASSES
|
|
903
|
+
|
|
904
|
+
TOY_UNCATEGORIZED_MINOR_DEVICE_CLASS = ClassOfDevice.ToyMinorDeviceClass.UNCATEGORIZED
|
|
905
|
+
TOY_ROBOT_MINOR_DEVICE_CLASS = ClassOfDevice.ToyMinorDeviceClass.ROBOT
|
|
906
|
+
TOY_VEHICLE_MINOR_DEVICE_CLASS = ClassOfDevice.ToyMinorDeviceClass.VEHICLE
|
|
907
|
+
TOY_DOLL_ACTION_FIGURE_MINOR_DEVICE_CLASS = ClassOfDevice.ToyMinorDeviceClass.DOLL_ACTION_FIGURE
|
|
908
|
+
TOY_CONTROLLER_MINOR_DEVICE_CLASS = ClassOfDevice.ToyMinorDeviceClass.CONTROLLER
|
|
909
|
+
TOY_GAME_MINOR_DEVICE_CLASS = ClassOfDevice.ToyMinorDeviceClass.GAME
|
|
910
|
+
|
|
911
|
+
HEALTH_UNDEFINED_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.UNDEFINED
|
|
912
|
+
HEALTH_BLOOD_PRESSURE_MONITOR_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.BLOOD_PRESSURE_MONITOR
|
|
913
|
+
HEALTH_THERMOMETER_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.THERMOMETER
|
|
914
|
+
HEALTH_WEIGHING_SCALE_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.WEIGHING_SCALE
|
|
915
|
+
HEALTH_GLUCOSE_METER_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.GLUCOSE_METER
|
|
916
|
+
HEALTH_PULSE_OXIMETER_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.PULSE_OXIMETER
|
|
917
|
+
HEALTH_HEART_PULSE_RATE_MONITOR_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.HEART_PULSE_RATE_MONITOR
|
|
918
|
+
HEALTH_HEALTH_DATA_DISPLAY_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.HEALTH_DATA_DISPLAY
|
|
919
|
+
HEALTH_STEP_COUNTER_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.STEP_COUNTER
|
|
920
|
+
HEALTH_BODY_COMPOSITION_ANALYZER_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.BODY_COMPOSITION_ANALYZER
|
|
921
|
+
HEALTH_PEAK_FLOW_MONITOR_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.PEAK_FLOW_MONITOR
|
|
922
|
+
HEALTH_MEDICATION_MONITOR_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.MEDICATION_MONITOR
|
|
923
|
+
HEALTH_KNEE_PROSTHESIS_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.KNEE_PROSTHESIS
|
|
924
|
+
HEALTH_ANKLE_PROSTHESIS_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.ANKLE_PROSTHESIS
|
|
925
|
+
HEALTH_GENERIC_HEALTH_MANAGER_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.GENERIC_HEALTH_MANAGER
|
|
926
|
+
HEALTH_PERSONAL_MOBILITY_DEVICE_MINOR_DEVICE_CLASS = ClassOfDevice.HealthMinorDeviceClass.PERSONAL_MOBILITY_DEVICE
|
|
927
|
+
|
|
694
928
|
# fmt: on
|
|
695
929
|
# pylint: enable=line-too-long
|
|
696
930
|
|
|
@@ -711,16 +945,16 @@ class DeviceClass:
|
|
|
711
945
|
@staticmethod
|
|
712
946
|
def service_class_labels(service_class_flags):
|
|
713
947
|
return bit_flags_to_strings(
|
|
714
|
-
service_class_flags,
|
|
948
|
+
service_class_flags, ClassOfDevice.MAJOR_SERVICE_CLASS_LABELS
|
|
715
949
|
)
|
|
716
950
|
|
|
717
951
|
@staticmethod
|
|
718
952
|
def major_device_class_name(device_class):
|
|
719
|
-
return name_or_number(
|
|
953
|
+
return name_or_number(ClassOfDevice.MAJOR_DEVICE_CLASS_LABELS, device_class)
|
|
720
954
|
|
|
721
955
|
@staticmethod
|
|
722
956
|
def minor_device_class_name(major_device_class, minor_device_class):
|
|
723
|
-
class_names =
|
|
957
|
+
class_names = ClassOfDevice.MINOR_DEVICE_CLASS_LABELS.get(major_device_class)
|
|
724
958
|
if class_names is None:
|
|
725
959
|
return f'#{minor_device_class:02X}'
|
|
726
960
|
return name_or_number(class_names, minor_device_class)
|
|
@@ -1255,6 +1489,10 @@ class Appearance:
|
|
|
1255
1489
|
category = cls.Category(appearance >> 6)
|
|
1256
1490
|
return cls(category, appearance & 0x3F)
|
|
1257
1491
|
|
|
1492
|
+
@classmethod
|
|
1493
|
+
def from_bytes(cls, data: bytes):
|
|
1494
|
+
return cls.from_int(int.from_bytes(data, byteorder="little"))
|
|
1495
|
+
|
|
1258
1496
|
def __init__(self, category: Category, subcategory: int) -> None:
|
|
1259
1497
|
self.category = category
|
|
1260
1498
|
if subcategory_class := self.SUBCATEGORY_CLASSES.get(category):
|
|
@@ -1265,6 +1503,9 @@ class Appearance:
|
|
|
1265
1503
|
def __int__(self) -> int:
|
|
1266
1504
|
return self.category << 6 | self.subcategory
|
|
1267
1505
|
|
|
1506
|
+
def __bytes__(self) -> bytes:
|
|
1507
|
+
return int(self).to_bytes(2, byteorder="little")
|
|
1508
|
+
|
|
1268
1509
|
def __repr__(self) -> str:
|
|
1269
1510
|
return (
|
|
1270
1511
|
'Appearance('
|
|
@@ -1276,6 +1517,61 @@ class Appearance:
|
|
|
1276
1517
|
def __str__(self) -> str:
|
|
1277
1518
|
return f'{self.category.name}/{self.subcategory.name}'
|
|
1278
1519
|
|
|
1520
|
+
def __eq__(self, value: Any) -> bool:
|
|
1521
|
+
return (
|
|
1522
|
+
isinstance(value, Appearance)
|
|
1523
|
+
and self.category == value.category
|
|
1524
|
+
and self.subcategory == value.subcategory
|
|
1525
|
+
)
|
|
1526
|
+
|
|
1527
|
+
|
|
1528
|
+
# -----------------------------------------------------------------------------
|
|
1529
|
+
# Classes representing "Data Types" defined in
|
|
1530
|
+
# "Supplement to the Bluetooth Core Specification", Part A
|
|
1531
|
+
# -----------------------------------------------------------------------------
|
|
1532
|
+
# TODO: use ABC, figure out multiple base classes with metaclasses
|
|
1533
|
+
class DataType:
|
|
1534
|
+
# Human-reable label/name for the type
|
|
1535
|
+
label = ""
|
|
1536
|
+
|
|
1537
|
+
# Advertising Data type ID for this data type.
|
|
1538
|
+
ad_type: AdvertisingData.Type = 0 # type: ignore
|
|
1539
|
+
|
|
1540
|
+
def value_string(self) -> str:
|
|
1541
|
+
"""Human-reable string representation of the value."""
|
|
1542
|
+
raise NotImplementedError()
|
|
1543
|
+
|
|
1544
|
+
def to_string(self, use_label: bool = False) -> str:
|
|
1545
|
+
if use_label:
|
|
1546
|
+
return f"[{self.label}]: {self.value_string()}"
|
|
1547
|
+
|
|
1548
|
+
return f"{self.__class__.__name__}({self.value_string()})"
|
|
1549
|
+
|
|
1550
|
+
@classmethod
|
|
1551
|
+
def from_advertising_data(cls, advertising_data: AdvertisingData) -> Optional[Self]:
|
|
1552
|
+
if (data := advertising_data.get(cls.ad_type, raw=True)) is None:
|
|
1553
|
+
return None
|
|
1554
|
+
|
|
1555
|
+
return cls.from_bytes(data)
|
|
1556
|
+
|
|
1557
|
+
@classmethod
|
|
1558
|
+
def all_from_advertising_data(cls, advertising_data: AdvertisingData) -> list[Self]:
|
|
1559
|
+
return [
|
|
1560
|
+
cls.from_bytes(data)
|
|
1561
|
+
for data in advertising_data.get_all(cls.ad_type, raw=True)
|
|
1562
|
+
]
|
|
1563
|
+
|
|
1564
|
+
@classmethod
|
|
1565
|
+
def from_bytes(cls, data: bytes) -> Self:
|
|
1566
|
+
"""Create an instance from a serialized form."""
|
|
1567
|
+
raise NotImplementedError()
|
|
1568
|
+
|
|
1569
|
+
def __bytes__(self) -> bytes:
|
|
1570
|
+
raise NotImplementedError()
|
|
1571
|
+
|
|
1572
|
+
def __str__(self) -> str:
|
|
1573
|
+
return self.to_string()
|
|
1574
|
+
|
|
1279
1575
|
|
|
1280
1576
|
# -----------------------------------------------------------------------------
|
|
1281
1577
|
# Advertising Data
|
|
@@ -1351,7 +1647,7 @@ class AdvertisingData:
|
|
|
1351
1647
|
THREE_D_INFORMATION_DATA = 0x3D
|
|
1352
1648
|
MANUFACTURER_SPECIFIC_DATA = 0xFF
|
|
1353
1649
|
|
|
1354
|
-
class Flags(
|
|
1650
|
+
class Flags(utils.CompatibleIntFlag):
|
|
1355
1651
|
LE_LIMITED_DISCOVERABLE_MODE = 1 << 0
|
|
1356
1652
|
LE_GENERAL_DISCOVERABLE_MODE = 1 << 1
|
|
1357
1653
|
BR_EDR_NOT_SUPPORTED = 1 << 2
|
|
@@ -1419,15 +1715,25 @@ class AdvertisingData:
|
|
|
1419
1715
|
BR_EDR_CONTROLLER_FLAG = Flags.SIMULTANEOUS_LE_BR_EDR_CAPABLE
|
|
1420
1716
|
BR_EDR_HOST_FLAG = 0x10 # Deprecated
|
|
1421
1717
|
|
|
1422
|
-
ad_structures: list[tuple[
|
|
1718
|
+
ad_structures: list[tuple[AdvertisingData.Type, bytes]]
|
|
1423
1719
|
|
|
1424
1720
|
# fmt: on
|
|
1425
1721
|
# pylint: enable=line-too-long
|
|
1426
1722
|
|
|
1427
|
-
def __init__(
|
|
1723
|
+
def __init__(
|
|
1724
|
+
self,
|
|
1725
|
+
ad_structures: Optional[Iterable[Union[tuple[int, bytes], DataType]]] = None,
|
|
1726
|
+
) -> None:
|
|
1428
1727
|
if ad_structures is None:
|
|
1429
1728
|
ad_structures = []
|
|
1430
|
-
self.ad_structures =
|
|
1729
|
+
self.ad_structures = [
|
|
1730
|
+
(
|
|
1731
|
+
(element.ad_type, bytes(element))
|
|
1732
|
+
if isinstance(element, DataType)
|
|
1733
|
+
else (AdvertisingData.Type(element[0]), element[1])
|
|
1734
|
+
)
|
|
1735
|
+
for element in ad_structures
|
|
1736
|
+
]
|
|
1431
1737
|
|
|
1432
1738
|
@classmethod
|
|
1433
1739
|
def from_bytes(cls, data: bytes) -> AdvertisingData:
|
|
@@ -1444,11 +1750,10 @@ class AdvertisingData:
|
|
|
1444
1750
|
'LE Limited Discoverable Mode',
|
|
1445
1751
|
'LE General Discoverable Mode',
|
|
1446
1752
|
'BR/EDR Not Supported',
|
|
1447
|
-
'Simultaneous LE and BR/EDR
|
|
1448
|
-
'Simultaneous LE and BR/EDR (Host)',
|
|
1753
|
+
'Simultaneous LE and BR/EDR',
|
|
1449
1754
|
]
|
|
1450
1755
|
)
|
|
1451
|
-
return ','.join(bit_flags_to_strings(flags, flag_names))
|
|
1756
|
+
return ', '.join(bit_flags_to_strings(flags, flag_names))
|
|
1452
1757
|
|
|
1453
1758
|
@staticmethod
|
|
1454
1759
|
def uuid_list_to_objects(ad_data: bytes, uuid_size: int) -> list[UUID]:
|
|
@@ -1604,7 +1909,7 @@ class AdvertisingData:
|
|
|
1604
1909
|
if length > 0:
|
|
1605
1910
|
ad_type = data[offset]
|
|
1606
1911
|
ad_data = data[offset + 1 : offset + length]
|
|
1607
|
-
self.ad_structures.append((ad_type, ad_data))
|
|
1912
|
+
self.ad_structures.append((AdvertisingData.Type(ad_type), ad_data))
|
|
1608
1913
|
offset += length
|
|
1609
1914
|
|
|
1610
1915
|
@overload
|
|
@@ -1623,6 +1928,7 @@ class AdvertisingData:
|
|
|
1623
1928
|
],
|
|
1624
1929
|
raw: Literal[False] = False,
|
|
1625
1930
|
) -> list[list[UUID]]: ...
|
|
1931
|
+
|
|
1626
1932
|
@overload
|
|
1627
1933
|
def get_all(
|
|
1628
1934
|
self,
|
|
@@ -1633,6 +1939,7 @@ class AdvertisingData:
|
|
|
1633
1939
|
],
|
|
1634
1940
|
raw: Literal[False] = False,
|
|
1635
1941
|
) -> list[tuple[UUID, bytes]]: ...
|
|
1942
|
+
|
|
1636
1943
|
@overload
|
|
1637
1944
|
def get_all(
|
|
1638
1945
|
self,
|
|
@@ -1644,6 +1951,7 @@ class AdvertisingData:
|
|
|
1644
1951
|
],
|
|
1645
1952
|
raw: Literal[False] = False,
|
|
1646
1953
|
) -> list[str]: ...
|
|
1954
|
+
|
|
1647
1955
|
@overload
|
|
1648
1956
|
def get_all(
|
|
1649
1957
|
self,
|
|
@@ -1655,26 +1963,31 @@ class AdvertisingData:
|
|
|
1655
1963
|
],
|
|
1656
1964
|
raw: Literal[False] = False,
|
|
1657
1965
|
) -> list[int]: ...
|
|
1966
|
+
|
|
1658
1967
|
@overload
|
|
1659
1968
|
def get_all(
|
|
1660
1969
|
self,
|
|
1661
1970
|
type_id: Literal[AdvertisingData.Type.PERIPHERAL_CONNECTION_INTERVAL_RANGE,],
|
|
1662
1971
|
raw: Literal[False] = False,
|
|
1663
1972
|
) -> list[tuple[int, int]]: ...
|
|
1973
|
+
|
|
1664
1974
|
@overload
|
|
1665
1975
|
def get_all(
|
|
1666
1976
|
self,
|
|
1667
1977
|
type_id: Literal[AdvertisingData.Type.MANUFACTURER_SPECIFIC_DATA,],
|
|
1668
1978
|
raw: Literal[False] = False,
|
|
1669
1979
|
) -> list[tuple[int, bytes]]: ...
|
|
1980
|
+
|
|
1670
1981
|
@overload
|
|
1671
1982
|
def get_all(
|
|
1672
1983
|
self,
|
|
1673
1984
|
type_id: Literal[AdvertisingData.Type.APPEARANCE,],
|
|
1674
1985
|
raw: Literal[False] = False,
|
|
1675
1986
|
) -> list[Appearance]: ...
|
|
1987
|
+
|
|
1676
1988
|
@overload
|
|
1677
1989
|
def get_all(self, type_id: int, raw: Literal[True]) -> list[bytes]: ...
|
|
1990
|
+
|
|
1678
1991
|
@overload
|
|
1679
1992
|
def get_all(
|
|
1680
1993
|
self, type_id: int, raw: bool = False
|
|
@@ -1682,7 +1995,7 @@ class AdvertisingData:
|
|
|
1682
1995
|
|
|
1683
1996
|
def get_all(self, type_id: int, raw: bool = False) -> list[AdvertisingDataObject]: # type: ignore[misc]
|
|
1684
1997
|
'''
|
|
1685
|
-
Get
|
|
1998
|
+
Get all advertising data elements as simple AdvertisingDataObject objects.
|
|
1686
1999
|
|
|
1687
2000
|
Returns a (possibly empty) list of matches.
|
|
1688
2001
|
'''
|
|
@@ -1708,6 +2021,7 @@ class AdvertisingData:
|
|
|
1708
2021
|
],
|
|
1709
2022
|
raw: Literal[False] = False,
|
|
1710
2023
|
) -> Optional[list[UUID]]: ...
|
|
2024
|
+
|
|
1711
2025
|
@overload
|
|
1712
2026
|
def get(
|
|
1713
2027
|
self,
|
|
@@ -1718,6 +2032,7 @@ class AdvertisingData:
|
|
|
1718
2032
|
],
|
|
1719
2033
|
raw: Literal[False] = False,
|
|
1720
2034
|
) -> Optional[tuple[UUID, bytes]]: ...
|
|
2035
|
+
|
|
1721
2036
|
@overload
|
|
1722
2037
|
def get(
|
|
1723
2038
|
self,
|
|
@@ -1729,6 +2044,7 @@ class AdvertisingData:
|
|
|
1729
2044
|
],
|
|
1730
2045
|
raw: Literal[False] = False,
|
|
1731
2046
|
) -> Optional[Optional[str]]: ...
|
|
2047
|
+
|
|
1732
2048
|
@overload
|
|
1733
2049
|
def get(
|
|
1734
2050
|
self,
|
|
@@ -1740,26 +2056,31 @@ class AdvertisingData:
|
|
|
1740
2056
|
],
|
|
1741
2057
|
raw: Literal[False] = False,
|
|
1742
2058
|
) -> Optional[int]: ...
|
|
2059
|
+
|
|
1743
2060
|
@overload
|
|
1744
2061
|
def get(
|
|
1745
2062
|
self,
|
|
1746
2063
|
type_id: Literal[AdvertisingData.Type.PERIPHERAL_CONNECTION_INTERVAL_RANGE,],
|
|
1747
2064
|
raw: Literal[False] = False,
|
|
1748
2065
|
) -> Optional[tuple[int, int]]: ...
|
|
2066
|
+
|
|
1749
2067
|
@overload
|
|
1750
2068
|
def get(
|
|
1751
2069
|
self,
|
|
1752
2070
|
type_id: Literal[AdvertisingData.Type.MANUFACTURER_SPECIFIC_DATA,],
|
|
1753
2071
|
raw: Literal[False] = False,
|
|
1754
2072
|
) -> Optional[tuple[int, bytes]]: ...
|
|
2073
|
+
|
|
1755
2074
|
@overload
|
|
1756
2075
|
def get(
|
|
1757
2076
|
self,
|
|
1758
2077
|
type_id: Literal[AdvertisingData.Type.APPEARANCE,],
|
|
1759
2078
|
raw: Literal[False] = False,
|
|
1760
2079
|
) -> Optional[Appearance]: ...
|
|
2080
|
+
|
|
1761
2081
|
@overload
|
|
1762
2082
|
def get(self, type_id: int, raw: Literal[True]) -> Optional[bytes]: ...
|
|
2083
|
+
|
|
1763
2084
|
@overload
|
|
1764
2085
|
def get(
|
|
1765
2086
|
self, type_id: int, raw: bool = False
|
|
@@ -1767,7 +2088,7 @@ class AdvertisingData:
|
|
|
1767
2088
|
|
|
1768
2089
|
def get(self, type_id: int, raw: bool = False) -> Optional[AdvertisingDataObject]:
|
|
1769
2090
|
'''
|
|
1770
|
-
Get
|
|
2091
|
+
Get advertising data as a simple AdvertisingDataObject object.
|
|
1771
2092
|
|
|
1772
2093
|
Returns the first entry, or None if no structure matches.
|
|
1773
2094
|
'''
|
|
@@ -1789,23 +2110,6 @@ class AdvertisingData:
|
|
|
1789
2110
|
return self.to_string()
|
|
1790
2111
|
|
|
1791
2112
|
|
|
1792
|
-
# -----------------------------------------------------------------------------
|
|
1793
|
-
# Connection Parameters
|
|
1794
|
-
# -----------------------------------------------------------------------------
|
|
1795
|
-
class ConnectionParameters:
|
|
1796
|
-
def __init__(self, connection_interval, peripheral_latency, supervision_timeout):
|
|
1797
|
-
self.connection_interval = connection_interval
|
|
1798
|
-
self.peripheral_latency = peripheral_latency
|
|
1799
|
-
self.supervision_timeout = supervision_timeout
|
|
1800
|
-
|
|
1801
|
-
def __str__(self):
|
|
1802
|
-
return (
|
|
1803
|
-
f'ConnectionParameters(connection_interval={self.connection_interval}, '
|
|
1804
|
-
f'peripheral_latency={self.peripheral_latency}, '
|
|
1805
|
-
f'supervision_timeout={self.supervision_timeout}'
|
|
1806
|
-
)
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
2113
|
# -----------------------------------------------------------------------------
|
|
1810
2114
|
# Connection PHY
|
|
1811
2115
|
# -----------------------------------------------------------------------------
|
|
@@ -1822,7 +2126,22 @@ class ConnectionPHY:
|
|
|
1822
2126
|
# LE Role
|
|
1823
2127
|
# -----------------------------------------------------------------------------
|
|
1824
2128
|
class LeRole(enum.IntEnum):
|
|
1825
|
-
|
|
1826
|
-
|
|
2129
|
+
# fmt: off
|
|
2130
|
+
PERIPHERAL_ONLY = 0x00
|
|
2131
|
+
CENTRAL_ONLY = 0x01
|
|
1827
2132
|
BOTH_PERIPHERAL_PREFERRED = 0x02
|
|
1828
|
-
BOTH_CENTRAL_PREFERRED
|
|
2133
|
+
BOTH_CENTRAL_PREFERRED = 0x03
|
|
2134
|
+
|
|
2135
|
+
|
|
2136
|
+
# -----------------------------------------------------------------------------
|
|
2137
|
+
# Security Manager OOB Flag
|
|
2138
|
+
# -----------------------------------------------------------------------------
|
|
2139
|
+
class SecurityManagerOutOfBandFlag(utils.CompatibleIntFlag):
|
|
2140
|
+
"""
|
|
2141
|
+
See Supplement to the Bluetooth Core Specification, Part A
|
|
2142
|
+
1.7 SECURITY MANAGER OUT OF BAND (OOB)
|
|
2143
|
+
"""
|
|
2144
|
+
|
|
2145
|
+
OOB_FLAGS_FIELD = 1 << 0
|
|
2146
|
+
LE_SUPPORTED = 1 << 1
|
|
2147
|
+
ADDRESS_TYPE = 1 << 3
|