Skip to content

Commit

Permalink
Add versions and capabilities to BOS descriptor
Browse files Browse the repository at this point in the history
Adds versions and capabilities to the BOS Descriptor by
appending dynamically-generated platform descriptors that
use the same UUIDs that are used with BLE and contain the
following values:

 * Firmware version
 * Software (protocol) version
 * Hub capabilities
  • Loading branch information
nkarstens committed Nov 9, 2023
1 parent e7883fe commit 72d3412
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 1 deletion.
68 changes: 67 additions & 1 deletion lib/pbio/drv/usb/stm32_usbd/usbd_desc.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,19 @@
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include <string.h>

#include "usbd_core.h"
#include "usbd_conf.h"
#include "usbd_pybricks.h"

#include "pbio/protocol.h"
#include "pbio/version.h"
#include "pbsys/app.h"
#include "pbsys/program_load.h"
#include "pbdrvconfig.h"
#include "sys/config.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define USBD_VID 0x0483
Expand All @@ -57,12 +66,21 @@
#define USBD_CONFIGURATION_FS_STRING "Pybricks Config"
#define USBD_INTERFACE_FS_STRING "Pybricks Interface"

static const char firmware_version[] = PBIO_VERSION_STR;
static const char software_version[] = PBIO_PROTOCOL_VERSION_STR;

#define DEVICE_ID1 (0x1FFF7A10)
#define DEVICE_ID2 (0x1FFF7A14)
#define DEVICE_ID3 (0x1FFF7A18)

#define USB_SIZ_STRING_SERIAL 0x1A
#define USB_SIZ_BOS_DESC 33
#define USB_SIZ_BOS_DESC_CONST (5 + 28)
#define USB_SIZ_UUID (128 / 8)
#define USB_SIZ_PLATFORM_HDR (4 + USB_SIZ_UUID)
#define USB_SIZ_BOS_DESC (USB_SIZ_BOS_DESC_CONST + \
USB_SIZ_PLATFORM_HDR + sizeof(firmware_version) + \
USB_SIZ_PLATFORM_HDR + sizeof(software_version) + \
USB_SIZ_PLATFORM_HDR + PBIO_PYBRICKS_HUB_CAPABILITIES_VALUE_SIZE)

/* USB Standard Device Descriptor */
__ALIGN_BEGIN uint8_t USBD_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
Expand Down Expand Up @@ -378,6 +396,54 @@ static uint8_t *USBD_Pybricks_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *l
/* Prevent unused argument(s) compilation warning */
UNUSED(speed);

static uint8_t created = 0;
uint8_t *ptr;

/* Generate BOS Descriptor on first attempt */
if (!created) {
created = 1;
ptr = &USBD_BOSDesc[USB_SIZ_BOS_DESC_CONST];

/* Add firmware version */
*ptr++ = USB_SIZ_PLATFORM_HDR + sizeof(firmware_version);
*ptr++ = USB_DEVICE_CAPABITY_TYPE;
*ptr++ = 0x05;
*ptr++ = 0x00;

pbio_uuid128_le_copy(ptr, pbio_gatt_firmware_version_char_uuid_128);
ptr += USB_SIZ_UUID;

memcpy(ptr, firmware_version, sizeof(firmware_version));
ptr += sizeof(firmware_version);

/* Add software (protocol) version */
*ptr++ = USB_SIZ_PLATFORM_HDR + sizeof(software_version);
*ptr++ = USB_DEVICE_CAPABITY_TYPE;
*ptr++ = 0x05;
*ptr++ = 0x00;

pbio_uuid128_le_copy(ptr, pbio_gatt_software_version_char_uuid_128);
ptr += USB_SIZ_UUID;

memcpy(ptr, software_version, sizeof(software_version));
ptr += sizeof(software_version);

/* Add hub capabilities */
*ptr++ = USB_SIZ_PLATFORM_HDR + PBIO_PYBRICKS_HUB_CAPABILITIES_VALUE_SIZE;
*ptr++ = USB_DEVICE_CAPABITY_TYPE;
*ptr++ = 0x05;
*ptr++ = 0x00;

pbio_uuid128_le_copy(ptr, pbio_pybricks_hub_capabilities_char_uuid);
ptr += USB_SIZ_UUID;

pbio_pybricks_hub_capabilities(ptr, 0, PBSYS_APP_HUB_FEATURE_FLAGS, PBSYS_PROGRAM_LOAD_MAX_PROGRAM_SIZE);
ptr += PBIO_PYBRICKS_HUB_CAPABILITIES_VALUE_SIZE;

/* Update bNumDeviceCaps field in BOS Descriptor */
USBD_BOSDesc[4] += 3;
}

*length = sizeof(USBD_BOSDesc);
return (uint8_t *)USBD_BOSDesc;
}
Expand Down
2 changes: 2 additions & 0 deletions lib/pbio/include/pbio/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,9 @@ extern const uint8_t pbio_pybricks_hub_capabilities_char_uuid[];

extern const uint16_t pbio_gatt_device_info_service_uuid;
extern const uint16_t pbio_gatt_firmware_version_char_uuid;
extern const uint8_t pbio_gatt_firmware_version_char_uuid_128[];
extern const uint16_t pbio_gatt_software_version_char_uuid;
extern const uint8_t pbio_gatt_software_version_char_uuid_128[];
extern const uint16_t pbio_gatt_pnp_id_char_uuid;

extern const uint8_t pbio_lwp3_hub_service_uuid[];
Expand Down
1 change: 1 addition & 0 deletions lib/pbio/include/pbio/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ void pbio_set_uint32_be(uint8_t *buf, uint32_t value) {
buf[3] = value;
}

void pbio_uuid128_le_copy(uint8_t *dst, const uint8_t *src);
bool pbio_uuid128_reverse_compare(const uint8_t *uuid1, const uint8_t *uuid2);
void pbio_uuid128_reverse_copy(uint8_t *dst, const uint8_t *src);

Expand Down
8 changes: 8 additions & 0 deletions lib/pbio/src/protocol/pybricks.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,17 @@ const uint16_t pbio_gatt_device_info_service_uuid = 0x180A;

/** Bluetooth Firmware Version Characteristic UUID. */
const uint16_t pbio_gatt_firmware_version_char_uuid = 0x2A26;
const uint8_t pbio_gatt_firmware_version_char_uuid_128[] = {
0x00, 0x00, 0x2A, 0x26, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
};

/** Bluetooth Software Version Characteristic UUID (Pybricks protocol version). */
const uint16_t pbio_gatt_software_version_char_uuid = 0x2A28;
const uint8_t pbio_gatt_software_version_char_uuid_128[] = {
0x00, 0x00, 0x2A, 0x28, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
};

/** Bluetooth PnP ID Characteristic UUID. */
const uint16_t pbio_gatt_pnp_id_char_uuid = 0x2A50;
Expand Down
28 changes: 28 additions & 0 deletions lib/pbio/src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,34 @@

#include <stdbool.h>
#include <stdint.h>
#include <string.h>

/**
* Copies a 128-bit UUID from @p src to a buffer @p dst,
* which is a buffer used by a little endian medium.
*
* According to RFC 4122, the UUID is grouped into the following:
* 1) One 32-bit
* 2) Two 16-bit
* 3) Eight 8-bit
*
* @param [in] dst The destination array.
* @param [in] src The UUID to reverse and copy.
*/
void pbio_uuid128_le_copy(uint8_t *dst, const uint8_t *src) {
dst[0] = src[3];
dst[1] = src[2];
dst[2] = src[1];
dst[3] = src[0];

dst[4] = src[5];
dst[5] = src[4];

dst[6] = src[7];
dst[7] = src[6];

memcpy(&dst[8], &src[8], 8);
}

/**
* Compares two 128-bit UUIDs with opposite byte ordering for equality.
Expand Down

0 comments on commit 72d3412

Please sign in to comment.