Coverage for src / bluetooth_sig / gatt / descriptors / report_reference.py: 71%
31 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-18 11:17 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-18 11:17 +0000
1"""Report Reference Descriptor implementation."""
3from __future__ import annotations
5from enum import IntEnum
7import msgspec
9from ..characteristics.utils import DataParser
10from .base import BaseDescriptor
13class ReportType(IntEnum):
14 """Report type values for Report Reference descriptor."""
16 INPUT_REPORT = 0x01
17 OUTPUT_REPORT = 0x02
18 FEATURE_REPORT = 0x03
21class ReportReferenceData(msgspec.Struct, frozen=True, kw_only=True):
22 """Report Reference descriptor data."""
24 report_id: int
25 report_type: int
28class ReportReferenceDescriptor(BaseDescriptor):
29 """Report Reference Descriptor (0x2908).
31 Contains report ID and report type information.
32 Used in HID (Human Interface Device) profiles.
33 """
35 def _has_structured_data(self) -> bool:
36 return True
38 def _get_data_format(self) -> str:
39 return "struct"
41 def _parse_descriptor_value(self, data: bytes) -> ReportReferenceData:
42 """Parse Report Reference value.
44 Format: 2 bytes
45 - Report ID (1 byte)
46 - Report Type (1 byte)
48 Args:
49 data: Raw bytes (should be 2 bytes)
51 Returns:
52 ReportReferenceData with report ID and type
54 Raises:
55 ValueError: If data is not exactly 2 bytes
56 """
57 return ReportReferenceData(
58 report_id=DataParser.parse_int8(data, offset=0),
59 report_type=DataParser.parse_int8(data, offset=1),
60 )
62 def get_report_id(self, data: bytes) -> int:
63 """Get the report ID."""
64 parsed = self._parse_descriptor_value(data)
65 return parsed.report_id
67 def get_report_type(self, data: bytes) -> int:
68 """Get the report type."""
69 parsed = self._parse_descriptor_value(data)
70 return parsed.report_type
72 def is_input_report(self, data: bytes) -> bool:
73 """Check if this is an input report."""
74 return self.get_report_type(data) == ReportType.INPUT_REPORT
76 def is_output_report(self, data: bytes) -> bool:
77 """Check if this is an output report."""
78 return self.get_report_type(data) == ReportType.OUTPUT_REPORT
80 def is_feature_report(self, data: bytes) -> bool:
81 """Check if this is a feature report."""
82 return self.get_report_type(data) == ReportType.FEATURE_REPORT