|
43 | 43 | ****************************************************************************** |
44 | 44 | */ |
45 | 45 | /* Includes ------------------------------------------------------------------*/ |
| 46 | +#include <string.h> |
46 | 47 |
|
47 | 48 | #include <lego_usb.h> |
48 | 49 |
|
| 50 | +#include <pbdrv/bluetooth.h> |
49 | 51 | #include <pbdrv/config.h> |
50 | 52 | #include <pbio/protocol.h> |
| 53 | +#include <pbio/version.h> |
| 54 | +#include <pbsys/storage.h> |
51 | 55 |
|
52 | 56 | #include "usbd_core.h" |
53 | 57 | #include "usbd_conf.h" |
|
59 | 63 | #define USBD_CONFIGURATION_FS_STRING "Pybricks Config" |
60 | 64 | #define USBD_INTERFACE_FS_STRING "Pybricks Interface" |
61 | 65 |
|
| 66 | +static const char firmware_version[] = PBIO_VERSION_STR; |
| 67 | +static const char software_version[] = PBIO_PROTOCOL_VERSION_STR; |
| 68 | + |
62 | 69 | #define DEVICE_ID1 (0x1FFF7A10) |
63 | 70 | #define DEVICE_ID2 (0x1FFF7A14) |
64 | 71 | #define DEVICE_ID3 (0x1FFF7A18) |
65 | 72 |
|
66 | 73 | #define USB_DEV_CAP_TYPE_PLATFORM (5) |
67 | 74 |
|
68 | 75 | #define USB_SIZ_STRING_SERIAL 0x1A |
69 | | -#define USB_SIZ_BOS_DESC 33 |
| 76 | +#define USB_SIZ_BOS_DESC_CONST (5 + 28) |
| 77 | +#define USB_SIZ_UUID (128 / 8) |
| 78 | +#define USB_SIZ_PLATFORM_HDR (4 + USB_SIZ_UUID) |
| 79 | +#define USB_SIZ_HUB_NAME_MAX (16) |
| 80 | +#define USB_SIZ_BOS_DESC (USB_SIZ_BOS_DESC_CONST + \ |
| 81 | + USB_SIZ_PLATFORM_HDR + USB_SIZ_HUB_NAME_MAX + \ |
| 82 | + USB_SIZ_PLATFORM_HDR + sizeof(firmware_version) - 1 + \ |
| 83 | + USB_SIZ_PLATFORM_HDR + sizeof(software_version) - 1 + \ |
| 84 | + USB_SIZ_PLATFORM_HDR + PBIO_PYBRICKS_HUB_CAPABILITIES_VALUE_SIZE) |
70 | 85 |
|
71 | 86 | /* USB Standard Device Descriptor */ |
72 | 87 | __ALIGN_BEGIN static |
@@ -128,6 +143,8 @@ __ALIGN_BEGIN static uint8_t USBD_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END = |
128 | 143 | 0x00 /* bAltEnumCode = Does not support alternate enumeration */ |
129 | 144 | }; |
130 | 145 |
|
| 146 | +static uint16_t USBD_BOSDesc_Len; |
| 147 | + |
131 | 148 | __ALIGN_BEGIN const uint8_t USBD_OSDescSet[USBD_SIZ_MS_OS_DSCRPTR_SET] __ALIGN_END = |
132 | 149 | { |
133 | 150 | 0x0A, 0x00, /* wLength = 10 */ |
@@ -275,6 +292,38 @@ static void Get_SerialNum(void) { |
275 | 292 | } |
276 | 293 | } |
277 | 294 |
|
| 295 | +/** |
| 296 | + * @brief Add the short BLE UUID to the buffer in little-endian format. |
| 297 | + * @param dst The destination buffer |
| 298 | + * @param dst The short BLE UUID to add |
| 299 | + * @retval None |
| 300 | + */ |
| 301 | +static void add_ble_short_uuid_le(uint8_t *dst, uint16_t short_uuid) { |
| 302 | + /* 32-bit */ |
| 303 | + dst[0] = LOBYTE(short_uuid); |
| 304 | + dst[1] = HIBYTE(short_uuid); |
| 305 | + dst[2] = 0x00; |
| 306 | + dst[3] = 0x00; |
| 307 | + |
| 308 | + /* 16-bit */ |
| 309 | + dst[4] = 0x00; |
| 310 | + dst[5] = 0x00; |
| 311 | + |
| 312 | + /* 16-bit */ |
| 313 | + dst[6] = 0x00; |
| 314 | + dst[7] = 0x10; |
| 315 | + |
| 316 | + /* 8-byte buffer */ |
| 317 | + dst[8] = 0x80; |
| 318 | + dst[9] = 0x00; |
| 319 | + dst[10] = 0x00; |
| 320 | + dst[11] = 0x80; |
| 321 | + dst[12] = 0x5F; |
| 322 | + dst[13] = 0x9B; |
| 323 | + dst[14] = 0x34; |
| 324 | + dst[15] = 0xFB; |
| 325 | +} |
| 326 | + |
278 | 327 | /** |
279 | 328 | * @brief Returns the device descriptor. |
280 | 329 | * @param speed: Current device speed |
@@ -372,7 +421,7 @@ static uint8_t *USBD_Pybricks_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *l |
372 | 421 | /* Prevent unused argument(s) compilation warning */ |
373 | 422 | UNUSED(speed); |
374 | 423 |
|
375 | | - *length = sizeof(USBD_BOSDesc); |
| 424 | + *length = USBD_BOSDesc_Len; |
376 | 425 | return (uint8_t *)USBD_BOSDesc; |
377 | 426 | } |
378 | 427 |
|
@@ -400,4 +449,79 @@ void USBD_Pybricks_Desc_Init(void) { |
400 | 449 | USBD_DeviceDesc[11] = HIBYTE(PBDRV_CONFIG_USB_PID_1); |
401 | 450 | } |
402 | 451 | #endif |
| 452 | + |
| 453 | + const char *str; |
| 454 | + size_t len; |
| 455 | + |
| 456 | + uint8_t *ptr = &USBD_BOSDesc[USB_SIZ_BOS_DESC_CONST]; |
| 457 | + |
| 458 | + /* Add device name */ |
| 459 | + str = pbdrv_bluetooth_get_hub_name(); |
| 460 | + len = MIN(strlen(str), USB_SIZ_HUB_NAME_MAX); |
| 461 | + |
| 462 | + *ptr++ = USB_SIZ_PLATFORM_HDR + len; // bLength |
| 463 | + *ptr++ = USB_DEVICE_CAPABITY_TYPE; // bDescriptorType |
| 464 | + *ptr++ = USB_DEV_CAP_TYPE_PLATFORM; // bDevCapabilityType |
| 465 | + *ptr++ = 0x00; // bReserved |
| 466 | + |
| 467 | + // PlatformCapabilityUUID |
| 468 | + add_ble_short_uuid_le(ptr, pbio_gatt_device_name_char_uuid); |
| 469 | + ptr += USB_SIZ_UUID; |
| 470 | + |
| 471 | + // CapabilityData: Device Name |
| 472 | + memcpy(ptr, str, len); |
| 473 | + ptr += len; |
| 474 | + |
| 475 | + /* Add firmware version */ |
| 476 | + *ptr++ = USB_SIZ_PLATFORM_HDR + sizeof(firmware_version) - 1; // bLength |
| 477 | + *ptr++ = USB_DEVICE_CAPABITY_TYPE; // bDescriptorType |
| 478 | + *ptr++ = USB_DEV_CAP_TYPE_PLATFORM; // bDevCapabilityType |
| 479 | + *ptr++ = 0x00; // bReserved |
| 480 | + |
| 481 | + // PlatformCapabilityUUID |
| 482 | + add_ble_short_uuid_le(ptr, pbio_gatt_firmware_version_char_uuid); |
| 483 | + ptr += USB_SIZ_UUID; |
| 484 | + |
| 485 | + // CapabilityData: Firmware Version |
| 486 | + memcpy(ptr, firmware_version, sizeof(firmware_version) - 1); |
| 487 | + ptr += sizeof(firmware_version) - 1; |
| 488 | + |
| 489 | + /* Add software (protocol) version */ |
| 490 | + *ptr++ = USB_SIZ_PLATFORM_HDR + sizeof(software_version) - 1; // bLength |
| 491 | + *ptr++ = USB_DEVICE_CAPABITY_TYPE; // bDescriptorType |
| 492 | + *ptr++ = USB_DEV_CAP_TYPE_PLATFORM; // bDevCapabilityType |
| 493 | + *ptr++ = 0x00; // bReserved |
| 494 | + |
| 495 | + // PlatformCapabilityUUID |
| 496 | + add_ble_short_uuid_le(ptr, pbio_gatt_software_version_char_uuid); |
| 497 | + ptr += USB_SIZ_UUID; |
| 498 | + |
| 499 | + // CapabilityData: Software Version |
| 500 | + memcpy(ptr, software_version, sizeof(software_version) - 1); |
| 501 | + ptr += sizeof(software_version) - 1; |
| 502 | + |
| 503 | + /* Add hub capabilities */ |
| 504 | + *ptr++ = USB_SIZ_PLATFORM_HDR + PBIO_PYBRICKS_HUB_CAPABILITIES_VALUE_SIZE; // bLength |
| 505 | + *ptr++ = USB_DEVICE_CAPABITY_TYPE; // bDescriptorType |
| 506 | + *ptr++ = USB_DEV_CAP_TYPE_PLATFORM; // bDevCapabilityType |
| 507 | + *ptr++ = 0x00; // bReserved |
| 508 | + |
| 509 | + // PlatformCapabilityUUID |
| 510 | + pbio_uuid128_le_copy(ptr, pbio_pybricks_hub_capabilities_char_uuid); |
| 511 | + ptr += USB_SIZ_UUID; |
| 512 | + |
| 513 | + // CapabilityData: Hub Capabilities |
| 514 | + pbio_pybricks_hub_capabilities(ptr, |
| 515 | + USBD_PYBRICKS_MAX_PACKET_SIZE - 1, |
| 516 | + PBSYS_CONFIG_APP_FEATURE_FLAGS, |
| 517 | + pbsys_storage_get_maximum_program_size()); |
| 518 | + ptr += PBIO_PYBRICKS_HUB_CAPABILITIES_VALUE_SIZE; |
| 519 | + |
| 520 | + /* Update wTotalLength field in BOS Descriptor */ |
| 521 | + USBD_BOSDesc_Len = ptr - USBD_BOSDesc; |
| 522 | + USBD_BOSDesc[2] = LOBYTE(USBD_BOSDesc_Len); |
| 523 | + USBD_BOSDesc[3] = HIBYTE(USBD_BOSDesc_Len); |
| 524 | + |
| 525 | + /* Update bNumDeviceCaps field in BOS Descriptor */ |
| 526 | + USBD_BOSDesc[4] += 4; |
403 | 527 | } |
0 commit comments