|
| 1 | +/* |
| 2 | + * Copyright (c) 2021, Dennis Marttinen |
| 3 | + * |
| 4 | + * Permission to use, copy, modify, and/or distribute this software |
| 5 | + * for any purpose with or without fee is hereby granted, provided |
| 6 | + * that the above copyright notice and this permission notice |
| 7 | + * appear in all copies. |
| 8 | + * |
| 9 | + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| 10 | + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| 11 | + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| 12 | + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR |
| 13 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM |
| 14 | + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
| 15 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
| 16 | + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 17 | + */ |
| 18 | + |
| 19 | +#ifndef DAPBOOT_USB_DESCRIPTOR_H |
| 20 | +#define DAPBOOT_USB_DESCRIPTOR_H |
| 21 | + |
| 22 | +#include "usb_conf.h" |
| 23 | +#include "dfu.h" |
| 24 | + |
| 25 | +// Macro to create a dummy (no-op) USB interface descriptor with the given alternate setting |
| 26 | +#define ALT_DUMMY(N) { \ |
| 27 | + .bLength = USB_DT_INTERFACE_SIZE, \ |
| 28 | + .bDescriptorType = USB_DT_INTERFACE, \ |
| 29 | + .bInterfaceNumber = INTF_DFU, \ |
| 30 | + .bAlternateSetting = (N), \ |
| 31 | + .bNumEndpoints = 0, \ |
| 32 | + .bInterfaceClass = 0, \ |
| 33 | + .bInterfaceSubClass = 0, \ |
| 34 | + .bInterfaceProtocol = 0, \ |
| 35 | + .iInterface = 0, \ |
| 36 | + .endpoint = NULL, \ |
| 37 | + .extra = NULL, \ |
| 38 | + .extralen = 0, \ |
| 39 | +}, |
| 40 | + |
| 41 | +// Functionality for creating repetitive ALT_DUMMY structs with an increasing count during compile time. |
| 42 | +// It doesn't look very nice, but C doesn't allow loops in preprocessor macros, so this needs to be hard-coded. |
| 43 | +#define ALT0 |
| 44 | +#define ALT1 ALT_DUMMY(0) |
| 45 | +#define ALT2 ALT1 ALT_DUMMY(1) |
| 46 | +#define ALT3 ALT2 ALT_DUMMY(2) |
| 47 | +#define ALT4 ALT3 ALT_DUMMY(3) |
| 48 | +#define ALT5 ALT4 ALT_DUMMY(4) |
| 49 | +#define ALTC(n) ALT##n |
| 50 | +#define ALTN(n) ALTC(n) |
| 51 | + |
| 52 | +// The DFU interface doesn't have any special alternate setting by default |
| 53 | +#ifndef USB_ALT |
| 54 | +#define USB_ALT 0 |
| 55 | +#endif |
| 56 | + |
| 57 | +static const struct usb_interface_descriptor altsettings[] = { |
| 58 | + ALTN(USB_ALT) // Prepend USB_ALT dummy USB interface descriptors to "pad" the real one |
| 59 | + { |
| 60 | + .bLength = USB_DT_INTERFACE_SIZE, |
| 61 | + .bDescriptorType = USB_DT_INTERFACE, |
| 62 | + .bInterfaceNumber = INTF_DFU, |
| 63 | + .bAlternateSetting = USB_ALT, |
| 64 | + .bNumEndpoints = 0, |
| 65 | + .bInterfaceClass = 0xFE, |
| 66 | + .bInterfaceSubClass = 1, |
| 67 | + .bInterfaceProtocol = 2, |
| 68 | + .iInterface = 0, |
| 69 | + |
| 70 | + .endpoint = NULL, |
| 71 | + |
| 72 | + .extra = &dfu_function, |
| 73 | + .extralen = sizeof(dfu_function), |
| 74 | + } |
| 75 | +}; |
| 76 | + |
| 77 | +// Tracking this is mandatory if exposing multiple altsettings |
| 78 | +static uint8_t cur_altsetting = 0; |
| 79 | + |
| 80 | +static const struct usb_interface interfaces[] = { |
| 81 | + /* DFU interface */ |
| 82 | + { |
| 83 | + .cur_altsetting = &cur_altsetting, |
| 84 | + .num_altsetting = USB_ALT + 1, |
| 85 | + .altsetting = (const struct usb_interface_descriptor*)&altsettings, |
| 86 | + }, |
| 87 | +}; |
| 88 | + |
| 89 | +static const struct usb_config_descriptor usb_config = { |
| 90 | + .bLength = USB_DT_CONFIGURATION_SIZE, |
| 91 | + .bDescriptorType = USB_DT_CONFIGURATION, |
| 92 | + .wTotalLength = 0, |
| 93 | + .bNumInterfaces = sizeof(interfaces)/sizeof(struct usb_interface), |
| 94 | + .bConfigurationValue = 1, |
| 95 | + .iConfiguration = 0, |
| 96 | + .bmAttributes = 0xC0, |
| 97 | + .bMaxPower = 0x32, |
| 98 | + |
| 99 | + .interface = interfaces, |
| 100 | +}; |
| 101 | + |
| 102 | +#endif //DAPBOOT_USB_DESCRIPTOR_H |
0 commit comments