Skip to content

Commit 9c91cc4

Browse files
ArcaneNibbledlech
authored andcommitted
pbio/drv/usb: Migrate USB string descriptors to common implementation
Now that we have C11 enabled, we can declare these directly as UTF-16 strings and embed them as constant data. This deduplicates code for manually laying out the string descriptors.
1 parent e076751 commit 9c91cc4

8 files changed

Lines changed: 123 additions & 110 deletions

File tree

lib/lego/lego/usb.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
/** Official LEGO USB Vendor ID. */
1212
#define LEGO_USB_VID 0x0694
13+
/** Official LEGO USB Product ID for MINDSTORMS NXT. */
14+
#define LEGO_USB_PID_NXT 0x0002
1315
/** Official LEGO USB Product ID for MINDSTORMS EV3. */
1416
#define LEGO_USB_PID_EV3 0x0005
1517
/** Official LEGO USB Product ID for MINDSTORMS EV3. */
@@ -28,12 +30,14 @@
2830
#define LEGO_USB_PID_ROBOT_INVENTOR_DFU 0x0011
2931

3032
/** Official LEGO USB Manufacturer String. */
31-
#define LEGO_USB_MFG_STR "LEGO System A/S"
33+
#define LEGO_USB_MFG_STR u"LEGO System A/S"
34+
/** NXT does not officially come with a product string */
35+
#define LEGO_USB_PROD_STR_NXT u"NXT"
3236
/** Official LEGO USB Product String for MINDSTORMS EV3. */
33-
#define LEGO_USB_PROD_STR_EV3 "LEGO MINDSTORMS EV3"
37+
#define LEGO_USB_PROD_STR_EV3 u"LEGO MINDSTORMS EV3"
3438
/** Official LEGO USB Product String for SPIKE Prime and MINDSTORMS Robot Inventor. */
35-
#define LEGO_USB_PROD_STR_TECHNIC_LARGE_HUB "LEGO Technic Large Hub"
39+
#define LEGO_USB_PROD_STR_TECHNIC_LARGE_HUB u"LEGO Technic Large Hub"
3640
/** Official LEGO USB Product String for SPIKE Essential. */
37-
#define LEGO_USB_PROD_STR_TECHNIC_SMALL_HUB "LEGO Technic Small Hub"
41+
#define LEGO_USB_PROD_STR_TECHNIC_SMALL_HUB u"LEGO Technic Small Hub"
3842

3943
#endif // _LEGO_USB_H_

lib/pbio/drv/usb/stm32_usbd/usbd_desc.c

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -98,20 +98,11 @@ pbdrv_usb_dev_desc_union_t USBD_DeviceDesc = {
9898
}; /* USB_DeviceDescriptor */
9999

100100
/* USB Standard Device Descriptor */
101-
__ALIGN_BEGIN static const uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
102-
USB_LEN_LANGID_STR_DESC,
103-
USB_DESC_TYPE_STRING,
104-
LOBYTE(USBD_LANGID_STRING),
105-
HIBYTE(USBD_LANGID_STRING),
106-
};
107-
108101
__ALIGN_BEGIN static uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = {
109102
USB_SIZ_STRING_SERIAL,
110103
USB_DESC_TYPE_STRING,
111104
};
112105

113-
__ALIGN_BEGIN static uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
114-
115106

116107
/**
117108
* @brief Convert Hex 32Bits value into char
@@ -180,8 +171,8 @@ static uint8_t *USBD_Pybricks_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint1
180171
/* Prevent unused argument(s) compilation warning */
181172
UNUSED(speed);
182173

183-
*length = sizeof(USBD_LangIDDesc);
184-
return (uint8_t *)USBD_LangIDDesc;
174+
*length = sizeof(pbdrv_usb_str_desc_langid.s);
175+
return (uint8_t *)&pbdrv_usb_str_desc_langid;
185176
}
186177

187178
/**
@@ -191,8 +182,11 @@ static uint8_t *USBD_Pybricks_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint1
191182
* @retval Pointer to descriptor buffer
192183
*/
193184
static uint8_t *USBD_Pybricks_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) {
194-
USBD_GetString((uint8_t *)PBDRV_CONFIG_USB_PROD_STR, USBD_StrDesc, length);
195-
return USBD_StrDesc;
185+
/* Prevent unused argument(s) compilation warning */
186+
UNUSED(speed);
187+
188+
*length = sizeof(pbdrv_usb_str_desc_prod.s);
189+
return (uint8_t *)&pbdrv_usb_str_desc_prod;
196190
}
197191

198192
/**
@@ -205,8 +199,8 @@ static uint8_t *USBD_Pybricks_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
205199
/* Prevent unused argument(s) compilation warning */
206200
UNUSED(speed);
207201

208-
USBD_GetString((uint8_t *)PBDRV_CONFIG_USB_MFG_STR, USBD_StrDesc, length);
209-
return USBD_StrDesc;
202+
*length = sizeof(pbdrv_usb_str_desc_mfg.s);
203+
return (uint8_t *)&pbdrv_usb_str_desc_mfg;
210204
}
211205

212206
/**

lib/pbio/drv/usb/usb_ch9.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ typedef struct PBDRV_PACKED {
136136
uint8_t iInterface;
137137
} pbdrv_usb_iface_desc_t;
138138

139+
// This LangID is used for string descriptors
140+
// English (United States)
141+
#define PBDRV_USB_STRING_LANGID_EN_US 0x0409
142+
139143
// Endpoint descriptor
140144
typedef struct PBDRV_PACKED {
141145
uint8_t bLength;

lib/pbio/drv/usb/usb_common_desc.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,28 @@ const pbdrv_usb_bos_desc_set_union_t pbdrv_usb_bos_desc_set = {
9393
}
9494
};
9595

96+
const pbdrv_usb_langid_union_t pbdrv_usb_str_desc_langid = {
97+
.s = {
98+
.bLength = 4,
99+
.bDescriptorType = DESC_TYPE_STRING,
100+
.langID = {PBDRV_USB_STRING_LANGID_EN_US},
101+
}
102+
};
103+
104+
const pbdrv_usb_str_mfg_union_t pbdrv_usb_str_desc_mfg = {
105+
.s = {
106+
.bLength = sizeof(pbdrv_usb_str_mfg_t),
107+
.bDescriptorType = DESC_TYPE_STRING,
108+
.str = PBDRV_CONFIG_USB_MFG_STR,
109+
}
110+
};
111+
112+
const pbdrv_usb_str_prod_union_t pbdrv_usb_str_desc_prod = {
113+
.s = {
114+
.bLength = sizeof(pbdrv_usb_str_prod_t),
115+
.bDescriptorType = DESC_TYPE_STRING,
116+
.str = PBDRV_CONFIG_USB_PROD_STR,
117+
}
118+
};
119+
96120
#endif // PBDRV_CONFIG_USB

lib/pbio/drv/usb/usb_common_desc.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99

1010
#include <pbio/util.h>
1111

12+
#include <lego/usb.h>
13+
#include "pbdrvconfig.h"
14+
1215
#include "usb_ch9.h"
1316

1417
/**
@@ -56,4 +59,32 @@ PBDRV_USB_TYPE_PUNNING_HELPER(pbdrv_usb_bos_desc_set);
5659

5760
extern const pbdrv_usb_bos_desc_set_union_t pbdrv_usb_bos_desc_set;
5861

62+
// (Human-readable) string descriptors
63+
typedef struct PBDRV_PACKED {
64+
uint8_t bLength;
65+
uint8_t bDescriptorType;
66+
uint16_t langID[1];
67+
} pbdrv_usb_langid_t;
68+
PBDRV_USB_TYPE_PUNNING_HELPER(pbdrv_usb_langid);
69+
70+
extern const pbdrv_usb_langid_union_t pbdrv_usb_str_desc_langid;
71+
72+
typedef struct PBDRV_PACKED {
73+
uint8_t bLength;
74+
uint8_t bDescriptorType;
75+
uint16_t str[PBIO_ARRAY_SIZE(PBDRV_CONFIG_USB_MFG_STR) - 1];
76+
} pbdrv_usb_str_mfg_t;
77+
PBDRV_USB_TYPE_PUNNING_HELPER(pbdrv_usb_str_mfg);
78+
79+
extern const pbdrv_usb_str_mfg_union_t pbdrv_usb_str_desc_mfg;
80+
81+
typedef struct PBDRV_PACKED {
82+
uint8_t bLength;
83+
uint8_t bDescriptorType;
84+
uint16_t str[PBIO_ARRAY_SIZE(PBDRV_CONFIG_USB_PROD_STR) - 1];
85+
} pbdrv_usb_str_prod_t;
86+
PBDRV_USB_TYPE_PUNNING_HELPER(pbdrv_usb_str_prod);
87+
88+
extern const pbdrv_usb_str_prod_union_t pbdrv_usb_str_desc_prod;
89+
5990
#endif // _INTERNAL_PBDRV_USB_COMMON_DESC_H_

lib/pbio/drv/usb/usb_ev3.c

Lines changed: 8 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#include <pbio/util.h>
1919

2020
#include <lego/usb.h>
21-
#include "pbdrvconfig.h"
2221

2322
#include <tiam1808/armv5/am1808/interrupt.h>
2423
#include <tiam1808/cppi41dma.h>
@@ -180,22 +179,8 @@ static const pbdrv_usb_ev3_conf_1_union_t configuration_1_desc_fs = {
180179
}
181180
};
182181

183-
typedef struct PBDRV_PACKED {
184-
uint8_t bLength;
185-
uint8_t bDescriptorType;
186-
uint16_t langID[1];
187-
} pbdrv_usb_langid_t;
188-
PBDRV_USB_TYPE_PUNNING_HELPER(pbdrv_usb_langid);
189-
190-
pbdrv_usb_langid_union_t usb_str_desc_langid = {
191-
.s = {
192-
.bLength = 4,
193-
.bDescriptorType = DESC_TYPE_STRING,
194-
.langID = {0x0409}, // English (United States)
195-
}
196-
};
197-
198-
// We generate string descriptors at runtime, so this dynamic buffer is needed
182+
// We generate a serial number string descriptors at runtime
183+
// so this dynamic buffer is needed
199184
#define STRING_DESC_MAX_SZ 64
200185
static union {
201186
uint8_t b[STRING_DESC_MAX_SZ];
@@ -456,36 +441,18 @@ static bool usb_get_descriptor(uint16_t wValue) {
456441
case DESC_TYPE_STRING:
457442
switch (desc_idx) {
458443
case STRING_DESC_LANGID:
459-
pbdrv_usb_setup_data_to_send = usb_str_desc_langid.u;
460-
pbdrv_usb_setup_data_to_send_sz = sizeof(usb_str_desc_langid);
444+
pbdrv_usb_setup_data_to_send = pbdrv_usb_str_desc_langid.u;
445+
pbdrv_usb_setup_data_to_send_sz = sizeof(pbdrv_usb_str_desc_langid.s);
461446
return true;
462447

463448
case STRING_DESC_MFG:
464-
usb_string_desc_buffer.b[1] = DESC_TYPE_STRING;
465-
i = 0;
466-
while (PBDRV_CONFIG_USB_MFG_STR[i]) {
467-
usb_string_desc_buffer.b[2 + 2 * i] = PBDRV_CONFIG_USB_MFG_STR[i];
468-
usb_string_desc_buffer.b[2 + 2 * i + 1] = 0;
469-
i++;
470-
}
471-
usb_string_desc_buffer.b[0] = 2 * i + 2;
472-
473-
pbdrv_usb_setup_data_to_send = usb_string_desc_buffer.u;
474-
pbdrv_usb_setup_data_to_send_sz = usb_string_desc_buffer.b[0];
449+
pbdrv_usb_setup_data_to_send = pbdrv_usb_str_desc_mfg.u;
450+
pbdrv_usb_setup_data_to_send_sz = sizeof(pbdrv_usb_str_desc_mfg.s);
475451
return true;
476452

477453
case STRING_DESC_PRODUCT:
478-
usb_string_desc_buffer.b[1] = DESC_TYPE_STRING;
479-
i = 0;
480-
while (PBDRV_CONFIG_USB_PROD_STR[i]) {
481-
usb_string_desc_buffer.b[2 + 2 * i] = PBDRV_CONFIG_USB_PROD_STR[i];
482-
usb_string_desc_buffer.b[2 + 2 * i + 1] = 0;
483-
i++;
484-
}
485-
usb_string_desc_buffer.b[0] = 2 * i + 2;
486-
487-
pbdrv_usb_setup_data_to_send = usb_string_desc_buffer.u;
488-
pbdrv_usb_setup_data_to_send_sz = usb_string_desc_buffer.b[0];
454+
pbdrv_usb_setup_data_to_send = pbdrv_usb_str_desc_prod.u;
455+
pbdrv_usb_setup_data_to_send_sz = sizeof(pbdrv_usb_str_desc_prod.s);
489456
return true;
490457

491458
case STRING_DESC_SERIAL:

lib/pbio/drv/usb/usb_nxt.c

Lines changed: 35 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include "nxos/drivers/aic.h"
2828
#include "nxos/util.h"
2929

30+
#include <lego/usb.h>
31+
3032
#include "usb_ch9.h"
3133
#include "usb_common_desc.h"
3234

@@ -86,6 +88,15 @@
8688

8789
#define USB_WVALUE_INDEX 0xFF
8890

91+
/**
92+
* Indices for string descriptors
93+
*/
94+
enum {
95+
STRING_DESC_LANGID,
96+
STRING_DESC_MFG,
97+
STRING_DESC_PRODUCT,
98+
};
99+
89100
/* The following definitions are 'raw' USB setup packets. They are all
90101
* standard responses to various setup requests by the USB host. These
91102
* packets are all constant, and mostly boilerplate. Don't be too
@@ -110,8 +121,8 @@ static const pbdrv_usb_dev_desc_t pbdrv_usb_nxt_device_descriptor = {
110121
.idVendor = 0x0694, /* Vendor ID : LEGO */
111122
.idProduct = 0x0002, /* Product ID : NXT */
112123
.bcdDevice = 0x0200, /* Product revision: 2.0.0. */
113-
.iManufacturer = 1,
114-
.iProduct = 2,
124+
.iManufacturer = STRING_DESC_MFG,
125+
.iProduct = STRING_DESC_PRODUCT,
115126
.iSerialNumber = 0, // TODO: implement a serial number
116127
.bNumConfigurations = 1,
117128
};
@@ -185,45 +196,6 @@ static const pbdrv_usb_nxt_conf_t pbdrv_usb_nxt_full_config = {
185196
},
186197
};
187198

188-
static const uint8_t pbdrv_usb_nxt_string_desc[] = {
189-
4, USB_DESC_TYPE_STR, /* Descriptor length and type. */
190-
0x09, 0x04, /* Supported language ID (US English). */
191-
};
192-
193-
static const uint8_t pbdrv_usb_lego_str[] = {
194-
10, USB_DESC_TYPE_STR,
195-
'L', 0,
196-
'E', 0,
197-
'G', 0,
198-
'O', 0,
199-
};
200-
201-
static const uint8_t pbdrv_usb_nxt_str[] = {
202-
30, USB_DESC_TYPE_STR,
203-
'N', 0,
204-
'X', 0,
205-
'T', 0,
206-
' ', 0,
207-
'+', 0,
208-
' ', 0,
209-
'P', 0,
210-
'y', 0,
211-
'b', 0,
212-
'r', 0,
213-
'i', 0,
214-
'c', 0,
215-
'k', 0,
216-
's', 0,
217-
};
218-
219-
/* Internal lookup table mapping string descriptors to their indices
220-
* in the USB string descriptor table.
221-
*/
222-
static const uint8_t *pbdrv_usb_nxt_strings[] = {
223-
pbdrv_usb_lego_str,
224-
pbdrv_usb_nxt_str,
225-
};
226-
227199
typedef enum {
228200
USB_UNINITIALIZED,
229201
USB_READY,
@@ -495,17 +467,30 @@ static void pbdrv_usb_handle_std_request(pbdrv_usb_nxt_setup_packet_t *packet) {
495467
break;
496468

497469
case USB_DESC_TYPE_STR: /* String or language info. */
498-
if ((packet->value & USB_WVALUE_INDEX) == 0) {
499-
pbdrv_usb_nxt_write_data(0, pbdrv_usb_nxt_string_desc,
500-
MIN(pbdrv_usb_nxt_string_desc[0], packet->length));
470+
{
471+
const void *desc = 0;
472+
switch (index) {
473+
case STRING_DESC_LANGID:
474+
desc = &pbdrv_usb_str_desc_langid;
475+
size = sizeof(pbdrv_usb_str_desc_langid.s);
476+
break;
477+
case STRING_DESC_MFG:
478+
desc = &pbdrv_usb_str_desc_mfg;
479+
size = sizeof(pbdrv_usb_str_desc_mfg.s);
480+
break;
481+
case STRING_DESC_PRODUCT:
482+
desc = &pbdrv_usb_str_desc_prod;
483+
size = sizeof(pbdrv_usb_str_desc_prod.s);
484+
break;
485+
}
486+
487+
if (desc) {
488+
pbdrv_usb_nxt_write_data(0, desc, MIN(size, packet->length));
501489
} else {
502-
/* The host wants a specific string. */
503-
/* TODO: This should check if the requested string exists. */
504-
pbdrv_usb_nxt_write_data(0, pbdrv_usb_nxt_strings[index - 1],
505-
MIN(pbdrv_usb_nxt_strings[index - 1][0],
506-
packet->length));
490+
pbdrv_usb_nxt_send_stall(0);
507491
}
508-
break;
492+
}
493+
break;
509494

510495
case USB_DESC_TYPE_DEVICE_QUALIFIER: /* Device qualifier descriptor. */
511496
size = pbdrv_usb_nxt_dev_qualifier_desc.bLength;

lib/pbio/platform/nxt/pbdrvconfig.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,7 @@
5050

5151
#define PBDRV_CONFIG_USB (1)
5252
#define PBDRV_CONFIG_USB_NXT (1)
53+
#define PBDRV_CONFIG_USB_VID LEGO_USB_VID
54+
#define PBDRV_CONFIG_USB_PID LEGO_USB_PID_NXT
55+
#define PBDRV_CONFIG_USB_MFG_STR LEGO_USB_MFG_STR
56+
#define PBDRV_CONFIG_USB_PROD_STR LEGO_USB_PROD_STR_NXT " + Pybricks"

0 commit comments

Comments
 (0)