|
35 | 35 | # for __version__
|
36 | 36 | import adafruit_ble
|
37 | 37 |
|
38 |
| -from bleio import Attribute, Characteristic, Descriptor, Peripheral, Service, UUID |
| 38 | +from bleio import Attribute, Characteristic, Peripheral, UUID |
39 | 39 | from .advertising import ServerAdvertisement
|
40 | 40 | from .device_information_service import DeviceInformationService
|
41 | 41 |
|
@@ -208,89 +208,83 @@ class HIDServer:
|
208 | 208 | }
|
209 | 209 |
|
210 | 210 | def __init__(self, name=None, tx_power=0):
|
| 211 | + self._periph = Peripheral(name) |
| 212 | + |
| 213 | + # iOS requires Device Information Service. Android does not. |
| 214 | + DeviceInformationService.add_to_peripheral( |
| 215 | + self._periph, software_revision=adafruit_ble.__version__, |
| 216 | + manufacturer="Adafruit Industries") |
| 217 | + |
| 218 | + service = self._periph.add_service(UUID(_HID_SERVICE_UUID_NUM)) |
| 219 | + |
211 | 220 | self._input_chars = {}
|
212 | 221 | for report_id in sorted(self._INPUT_REPORT_SIZES.keys()):
|
213 |
| - desc = Descriptor(self._REPORT_REF_DESCR_UUID, |
214 |
| - read_perm=Attribute.ENCRYPT_NO_MITM, write_perm=Attribute.NO_ACCESS) |
215 |
| - desc.value = struct.pack('<BB', report_id, _REPORT_TYPE_INPUT) |
216 |
| - report_size = self._INPUT_REPORT_SIZES[report_id] |
217 |
| - self._input_chars[report_id] = Characteristic( |
| 222 | + input_char = service.add_characteristic( |
218 | 223 | self._REPORT_UUID, properties=Characteristic.READ | Characteristic.NOTIFY,
|
219 | 224 | read_perm=Attribute.ENCRYPT_NO_MITM, write_perm=Attribute.NO_ACCESS,
|
220 |
| - max_length=report_size, fixed_length=True, |
221 |
| - descriptors=(desc,)) |
222 |
| - self._input_chars[report_id].value = bytes(report_size) |
| 225 | + max_length=self._INPUT_REPORT_SIZES[report_id], fixed_length=True) |
| 226 | + input_char.add_descriptor( |
| 227 | + self._REPORT_REF_DESCR_UUID, |
| 228 | + read_perm=Attribute.ENCRYPT_NO_MITM, write_perm=Attribute.NO_ACCESS, |
| 229 | + initial_value=struct.pack('<BB', report_id, _REPORT_TYPE_INPUT)) |
| 230 | + self._input_chars[report_id] = input_char |
223 | 231 |
|
224 | 232 | self._output_chars = {}
|
225 | 233 | for report_id in sorted(self._OUTPUT_REPORT_SIZES.keys()):
|
226 |
| - desc = Descriptor(self._REPORT_REF_DESCR_UUID, |
227 |
| - read_perm=Attribute.ENCRYPT_NO_MITM, write_perm=Attribute.NO_ACCESS) |
228 |
| - desc.value = struct.pack('<BB', report_id, _REPORT_TYPE_OUTPUT) |
229 |
| - report_size = self._OUTPUT_REPORT_SIZES[report_id] |
230 |
| - self._output_chars[report_id] = Characteristic( |
| 234 | + output_char = service.add_characteristic( |
231 | 235 | self._REPORT_UUID,
|
232 | 236 | properties=(Characteristic.READ | Characteristic.WRITE |
|
233 | 237 | Characteristic.WRITE_NO_RESPONSE),
|
234 | 238 | read_perm=Attribute.ENCRYPT_NO_MITM, write_perm=Attribute.ENCRYPT_NO_MITM,
|
235 |
| - max_length=report_size, fixed_length=True, |
236 |
| - descriptors=(desc,)) |
237 |
| - self._output_chars[report_id].value = bytes(report_size) |
| 239 | + max_length=self._OUTPUT_REPORT_SIZES[report_id], fixed_length=True) |
| 240 | + output_char.add_descriptor( |
| 241 | + self._REPORT_REF_DESCR_UUID, |
| 242 | + read_perm=Attribute.ENCRYPT_NO_MITM, write_perm=Attribute.NO_ACCESS, |
| 243 | + initial_value=struct.pack('<BB', report_id, _REPORT_TYPE_OUTPUT)) |
| 244 | + self._output_chars[report_id] = output_char |
238 | 245 |
|
239 | 246 | # Protocol mode: boot or report. Make it read-only for now because
|
240 | 247 | # it can't be changed
|
241 | 248 |
|
242 |
| - protocol_mode_char = Characteristic( |
243 |
| - UUID(_PROTOCOL_MODE_UUID_NUM), properties=Characteristic.READ | Characteristic.WRITE_NO_RESPONSE, |
| 249 | + service.add_characteristic( |
| 250 | + UUID(_PROTOCOL_MODE_UUID_NUM), |
| 251 | + properties=Characteristic.READ | Characteristic.WRITE_NO_RESPONSE, |
244 | 252 | read_perm=Attribute.OPEN, write_perm=Attribute.OPEN,
|
245 |
| - max_length=1, fixed_length=True) |
246 |
| - protocol_mode_char.value = _PROTOCOL_MODE_REPORT |
| 253 | + max_length=1, fixed_length=True, |
| 254 | + initial_value=_PROTOCOL_MODE_REPORT) |
247 | 255 |
|
248 |
| - boot_keyboard_input_report = Characteristic( |
| 256 | + service.add_characteristic( |
249 | 257 | UUID(_BOOT_KEYBOARD_INPUT_REPORT_UUID_NUM),
|
250 | 258 | properties=Characteristic.READ | Characteristic.NOTIFY,
|
251 | 259 | read_perm=Attribute.ENCRYPT_NO_MITM, write_perm=Attribute.NO_ACCESS,
|
252 | 260 | max_length=self._INPUT_REPORT_SIZES[self.REPORT_ID_KEYBOARD], fixed_length=True)
|
253 | 261 |
|
254 |
| - boot_keyboard_output_report = Characteristic( |
| 262 | + service.add_characteristic( |
255 | 263 | UUID(_BOOT_KEYBOARD_OUTPUT_REPORT_UUID_NUM),
|
256 | 264 | properties=(Characteristic.READ | Characteristic.WRITE |
|
257 | 265 | Characteristic.WRITE_NO_RESPONSE),
|
258 | 266 | read_perm=Attribute.ENCRYPT_NO_MITM, write_perm=Attribute.ENCRYPT_NO_MITM,
|
259 | 267 | max_length=self._OUTPUT_REPORT_SIZES[self.REPORT_ID_KEYBOARD], fixed_length=True)
|
260 | 268 |
|
261 | 269 | # This is the USB HID descriptor (not to be confused with a BLE Descriptor).
|
262 |
| - report_map_char = Characteristic( |
| 270 | + service.add_characteristic( |
263 | 271 | UUID(_REPORT_MAP_UUID_NUM), properties=Characteristic.READ,
|
264 | 272 | read_perm=Attribute.ENCRYPT_NO_MITM, write_perm=Attribute.NO_ACCESS,
|
265 |
| - max_length=len(self.HID_DESCRIPTOR), fixed_length=True) |
266 |
| - report_map_char.value = self.HID_DESCRIPTOR |
| 273 | + max_length=len(self.HID_DESCRIPTOR), fixed_length=True, |
| 274 | + initial_value=self.HID_DESCRIPTOR) |
267 | 275 |
|
268 | 276 | # bcdHID (version), bCountryCode (0 not localized), Flags: RemoteWake, NormallyConnectable
|
269 |
| - hid_information_char = Characteristic( |
270 |
| - UUID(_HID_INFORMATION_UUID_NUM), properties=Characteristic.READ, |
271 |
| - read_perm=Attribute.ENCRYPT_NO_MITM, write_perm=Attribute.NO_ACCESS) |
272 | 277 | # bcd1.1, country = 0, flag = normal connect
|
273 |
| - hid_information_char.value = b'\x01\x01\x00\x02' |
| 278 | + service.add_characteristic( |
| 279 | + UUID(_HID_INFORMATION_UUID_NUM), properties=Characteristic.READ, |
| 280 | + read_perm=Attribute.ENCRYPT_NO_MITM, write_perm=Attribute.NO_ACCESS, |
| 281 | + initial_value=b'\x01\x01\x00\x02') |
274 | 282 |
|
275 | 283 | # 0 = suspend; 1 = exit suspend
|
276 |
| - self._hid_control_point_char = Characteristic( |
| 284 | + service.add_characteristic( |
277 | 285 | UUID(_HID_CONTROL_POINT_UUID_NUM), properties=Characteristic.WRITE_NO_RESPONSE,
|
278 | 286 | read_perm=Attribute.NO_ACCESS, write_perm=Attribute.ENCRYPT_NO_MITM)
|
279 | 287 |
|
280 |
| - # iOS requires Device Information Service. Android does not. |
281 |
| - dis = DeviceInformationService(software_revision=adafruit_ble.__version__, |
282 |
| - manufacturer="Adafruit Industries") |
283 |
| - hid_service = Service(UUID(_HID_SERVICE_UUID_NUM), |
284 |
| - tuple(self._input_chars.values()) + |
285 |
| - tuple(self._output_chars.values()) + |
286 |
| - (boot_keyboard_input_report, |
287 |
| - boot_keyboard_output_report, |
288 |
| - protocol_mode_char, |
289 |
| - report_map_char, |
290 |
| - hid_information_char, |
291 |
| - self._hid_control_point_char, |
292 |
| - )) |
293 |
| - self._periph = Peripheral((dis, hid_service), name=name) |
294 | 288 | self._advertisement = ServerAdvertisement(self._periph, tx_power=tx_power,
|
295 | 289 | appearance=_APPEARANCE_HID_KEYBOARD)
|
296 | 290 |
|
|
0 commit comments