Skip to content

Commit 29fdafe

Browse files
authored
Merge pull request #43 from twelho/dfu-custom-alt-setting
Enable specifying the alternate setting for the DFU interface per-target
2 parents d1428ca + 5ad3db6 commit 29fdafe

2 files changed

Lines changed: 55 additions & 17 deletions

File tree

src/usb_conf.c

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,28 +45,62 @@ static const struct usb_device_descriptor dev = {
4545
.bNumConfigurations = 1,
4646
};
4747

48-
static const struct usb_interface_descriptor dfu_iface = {
49-
.bLength = USB_DT_INTERFACE_SIZE,
50-
.bDescriptorType = USB_DT_INTERFACE,
51-
.bInterfaceNumber = INTF_DFU,
52-
.bAlternateSetting = 0,
53-
.bNumEndpoints = 0,
54-
.bInterfaceClass = 0xFE,
55-
.bInterfaceSubClass = 1,
56-
.bInterfaceProtocol = 2,
57-
.iInterface = 4,
58-
59-
.endpoint = NULL,
60-
61-
.extra = &dfu_function,
62-
.extralen = sizeof(dfu_function),
48+
// Macro to create a dummy (no-op) USB interface descriptor with the given alternate setting
49+
#define ALT_DUMMY(N) { \
50+
.bLength = USB_DT_INTERFACE_SIZE, \
51+
.bDescriptorType = USB_DT_INTERFACE, \
52+
.bInterfaceNumber = INTF_DFU, \
53+
.bAlternateSetting = (N), \
54+
.bNumEndpoints = 0, \
55+
.bInterfaceClass = 0, \
56+
.bInterfaceSubClass = 0, \
57+
.bInterfaceProtocol = 0, \
58+
.iInterface = 0, \
59+
.endpoint = NULL, \
60+
.extra = NULL, \
61+
.extralen = 0, \
62+
},
63+
64+
// Functionality for creating repetitive ALT_DUMMY structs with an increasing count during compile time.
65+
// It doesn't look very nice, but C doesn't allow loops in preprocessor macros, so this needs to be hard-coded.
66+
#define ALT0
67+
#define ALT1 ALT_DUMMY(0)
68+
#define ALT2 ALT1 ALT_DUMMY(1)
69+
#define ALT3 ALT2 ALT_DUMMY(2)
70+
#define ALT4 ALT3 ALT_DUMMY(3)
71+
#define ALT5 ALT4 ALT_DUMMY(4)
72+
#define ALTW(n) ALT##n // Wrapper macro for expansion
73+
#define ALTN(n) ALTW(n)
74+
75+
static const struct usb_interface_descriptor altsettings[] = {
76+
ALTN(USB_DFU_ALTN) // Prepend USB_DFU_ALTN dummy USB interface descriptors to "pad" the real one
77+
{
78+
.bLength = USB_DT_INTERFACE_SIZE,
79+
.bDescriptorType = USB_DT_INTERFACE,
80+
.bInterfaceNumber = INTF_DFU,
81+
.bAlternateSetting = USB_DFU_ALTN,
82+
.bNumEndpoints = 0,
83+
.bInterfaceClass = 0xFE,
84+
.bInterfaceSubClass = 1,
85+
.bInterfaceProtocol = 2,
86+
.iInterface = 4,
87+
88+
.endpoint = NULL,
89+
90+
.extra = &dfu_function,
91+
.extralen = sizeof(dfu_function),
92+
}
6393
};
6494

95+
// Tracking this is mandatory if exposing multiple altsettings
96+
static uint8_t cur_altsetting = 0;
97+
6598
static const struct usb_interface interfaces[] = {
6699
/* DFU interface */
67100
{
68-
.num_altsetting = 1,
69-
.altsetting = &dfu_iface,
101+
.cur_altsetting = &cur_altsetting,
102+
.num_altsetting = USB_DFU_ALTN + 1,
103+
.altsetting = (const struct usb_interface_descriptor*)&altsettings,
70104
}
71105
};
72106

src/usb_conf.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
#define USB_PID 0xdb42
3434
#endif
3535

36+
// The DFU interface doesn't have any special alternate setting by default
37+
#ifndef USB_DFU_ALTN
38+
#define USB_DFU_ALTN 0
39+
#endif
3640

3741
#ifndef USB_PRODUCT_STRING
3842

0 commit comments

Comments
 (0)