Harald Welte | 34a8706 | 2019-04-19 22:33:36 +0200 | [diff] [blame] | 1 | #include "usbd_config.h" |
| 2 | #include "usbdc.h" |
| 3 | #include "usb_protocol.h" |
| 4 | #include "usb_protocol_cdc.h" |
| 5 | #include "ccid_proto.h" |
| 6 | #include "cdcdf_acm_desc.h" |
| 7 | |
| 8 | /* aggregate descriptors for the combined CDC-ACM + CCID device that we expose |
| 9 | * from sysmoQMOD */ |
| 10 | |
| 11 | enum str_desc_num { |
| 12 | STR_DESC_MANUF = 1, |
| 13 | STR_DESC_PRODUCT, |
| 14 | STR_DESC_CONFIG, |
| 15 | STR_DESC_INTF_ACM_COMM, |
| 16 | STR_DESC_INTF_ACM_DATA, |
| 17 | STR_DESC_INTF_CCID, |
| 18 | STR_DESC_SERIAL, |
| 19 | }; |
| 20 | |
| 21 | /* a struct of structs representing the concatenated collection of USB descriptors */ |
| 22 | struct usb_desc_collection { |
| 23 | struct usb_dev_desc dev; |
| 24 | struct usb_config_desc cfg; |
| 25 | |
| 26 | /* CDC-ACM: Two interfaces, one with IRQ EP and one with BULK IN + OUT */ |
| 27 | struct { |
| 28 | struct { |
| 29 | struct usb_iface_desc iface; |
| 30 | struct usb_cdc_hdr_desc cdc_hdr; |
| 31 | struct usb_cdc_call_mgmt_desc cdc_call_mgmt; |
| 32 | struct usb_cdc_acm_desc cdc_acm; |
| 33 | struct usb_cdc_union_desc cdc_union; |
| 34 | struct usb_ep_desc ep[1]; |
| 35 | } comm; |
| 36 | struct { |
| 37 | struct usb_iface_desc iface; |
| 38 | struct usb_ep_desc ep[2]; |
| 39 | } data; |
| 40 | } cdc; |
| 41 | |
| 42 | /* CCID: One interface with CCID class descriptor and three endpoints */ |
| 43 | struct { |
| 44 | struct usb_iface_desc iface; |
| 45 | struct usb_ccid_class_descriptor class; |
| 46 | struct usb_ep_desc ep[3]; |
| 47 | } ccid; |
| 48 | uint8_t str[116]; |
| 49 | } __attribute__((packed)); |
| 50 | |
| 51 | static const struct usb_desc_collection usb_fs_descs = { |
| 52 | .dev = { |
| 53 | .bLength = sizeof(struct usb_dev_desc), |
| 54 | .bDescriptorType = USB_DT_DEVICE, |
| 55 | .bcdUSB = USB_V2_0, |
| 56 | .bDeviceClass = 0x02, |
| 57 | .bDeviceSubClass = 0, |
| 58 | .bDeviceProtocol = 0, |
| 59 | .bMaxPacketSize0 = CONF_USB_CDCD_ACM_BMAXPKSZ0, |
| 60 | .idVendor = CONF_USB_CDCD_ACM_IDVENDER, |
| 61 | .idProduct = CONF_USB_CDCD_ACM_IDPRODUCT, |
| 62 | .iManufacturer = STR_DESC_MANUF, |
| 63 | .iProduct = STR_DESC_PRODUCT, |
| 64 | .iSerialNumber = STR_DESC_SERIAL, |
| 65 | .bNumConfigurations = 1, |
| 66 | }, |
| 67 | .cfg = { |
| 68 | .bLength = sizeof(struct usb_config_desc), |
| 69 | .bDescriptorType = USB_DT_CONFIG, |
| 70 | .wTotalLength = sizeof(usb_fs_descs.cfg) + |
| 71 | sizeof(usb_fs_descs.cdc) + |
| 72 | sizeof(usb_fs_descs.ccid), |
| 73 | .bNumInterfaces = 3, |
| 74 | .bConfigurationValue = CONF_USB_CDCD_ACM_BCONFIGVAL, |
| 75 | .iConfiguration = STR_DESC_CONFIG, |
| 76 | .bmAttributes = CONF_USB_CDCD_ACM_BMATTRI, |
| 77 | .bMaxPower = CONF_USB_CDCD_ACM_BMAXPOWER, |
| 78 | }, |
| 79 | .cdc = { |
| 80 | .comm = { |
| 81 | .iface = { |
| 82 | .bLength = sizeof(struct usb_iface_desc), |
| 83 | .bDescriptorType = USB_DT_INTERFACE, |
| 84 | .bInterfaceNumber = CONF_USB_CDCD_ACM_COMM_BIFCNUM, |
| 85 | .bAlternateSetting = CONF_USB_CDCD_ACM_COMM_BALTSET, |
| 86 | .bNumEndpoints = 1, |
| 87 | .bInterfaceClass = CDC_CLASS_COMM, |
| 88 | .bInterfaceSubClass = CDC_SUBCLASS_ACM, |
| 89 | .bInterfaceProtocol = 0x00, |
| 90 | .iInterface = STR_DESC_INTF_ACM_COMM, |
| 91 | }, |
| 92 | .cdc_hdr = { |
| 93 | .bFunctionLength = sizeof(struct usb_cdc_hdr_desc), |
| 94 | .bDescriptorType = CDC_CS_INTERFACE, |
| 95 | .bDescriptorSubtype = CDC_SCS_HEADER, |
| 96 | .bcdCDC = LE16(0x1001), |
| 97 | }, |
| 98 | .cdc_call_mgmt = { |
| 99 | .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc), |
| 100 | .bDescriptorType = CDC_CS_INTERFACE, |
| 101 | .bDescriptorSubtype = CDC_SCS_CALL_MGMT, |
| 102 | .bmCapabilities = 0x01, |
| 103 | .bDataInterface = 0x00, |
| 104 | }, |
| 105 | .cdc_acm = { |
| 106 | .bFunctionLength = sizeof(struct usb_cdc_acm_desc), |
| 107 | .bDescriptorType = CDC_CS_INTERFACE, |
| 108 | .bDescriptorSubtype = CDC_SCS_ACM, |
| 109 | .bmCapabilities = 0x02, |
| 110 | }, |
| 111 | .cdc_union = { |
| 112 | .bFunctionLength = sizeof(struct usb_cdc_union_desc), |
| 113 | .bDescriptorType = CDC_CS_INTERFACE, |
| 114 | .bDescriptorSubtype = CDC_SCS_UNION, |
| 115 | .bMasterInterface = CONF_USB_CDCD_ACM_COMM_BIFCNUM, |
| 116 | .bSlaveInterface0 = 0x01, |
| 117 | }, |
| 118 | .ep = { |
| 119 | { |
| 120 | .bLength = sizeof(struct usb_ep_desc), |
| 121 | .bDescriptorType = USB_DT_ENDPOINT, |
| 122 | .bEndpointAddress = CONF_USB_CDCD_ACM_COMM_INT_EPADDR, |
| 123 | .bmAttributes = USB_EP_TYPE_INTERRUPT, |
| 124 | .wMaxPacketSize = CONF_USB_CDCD_ACM_COMM_INT_MAXPKSZ, |
| 125 | .bInterval = CONF_USB_CDCD_ACM_COMM_INT_INTERVAL, |
| 126 | }, |
| 127 | }, |
| 128 | }, |
| 129 | .data = { |
| 130 | .iface = { |
| 131 | .bLength = sizeof(struct usb_iface_desc), |
| 132 | .bDescriptorType = USB_DT_INTERFACE, |
| 133 | .bInterfaceNumber = CONF_USB_CDCD_ACM_DATA_BIFCNUM, |
| 134 | .bAlternateSetting = CONF_USB_CDCD_ACM_DATA_BALTSET, |
| 135 | .bNumEndpoints = 2, |
| 136 | .bInterfaceClass = CDC_CLASS_DATA, |
| 137 | .bInterfaceSubClass = 0x00, |
| 138 | .bInterfaceProtocol = 0x00, |
| 139 | .iInterface = STR_DESC_INTF_ACM_DATA, |
| 140 | }, |
| 141 | .ep = { |
| 142 | { |
| 143 | .bLength = sizeof(struct usb_ep_desc), |
| 144 | .bDescriptorType = USB_DT_ENDPOINT, |
| 145 | .bEndpointAddress = CONF_USB_CDCD_ACM_DATA_BULKOUT_EPADDR, |
| 146 | .bmAttributes = USB_EP_TYPE_BULK, |
| 147 | .wMaxPacketSize = CONF_USB_CDCD_ACM_DATA_BULKOUT_MAXPKSZ, |
| 148 | .bInterval = 0, |
| 149 | }, |
| 150 | { |
| 151 | .bLength = sizeof(struct usb_ep_desc), |
| 152 | .bDescriptorType = USB_DT_ENDPOINT, |
| 153 | .bEndpointAddress = CONF_USB_CDCD_ACM_DATA_BULKIN_EPADDR, |
| 154 | .bmAttributes = USB_EP_TYPE_BULK, |
| 155 | .wMaxPacketSize = CONF_USB_CDCD_ACM_DATA_BULKIN_MAXPKSZ, |
| 156 | .bInterval = 0, |
| 157 | }, |
| 158 | }, |
| 159 | }, |
| 160 | }, |
| 161 | .ccid = { |
| 162 | .iface = { |
| 163 | .bLength = sizeof(struct usb_iface_desc), |
| 164 | .bDescriptorType = USB_DT_INTERFACE, |
Eric Wild | 7603390 | 2019-10-01 15:04:01 +0200 | [diff] [blame] | 165 | .bInterfaceNumber = 0, |
Harald Welte | 34a8706 | 2019-04-19 22:33:36 +0200 | [diff] [blame] | 166 | .bAlternateSetting = 0, |
| 167 | .bNumEndpoints = 3, |
| 168 | .bInterfaceClass = 11, |
| 169 | .bInterfaceSubClass = 0, |
| 170 | .bInterfaceProtocol = 0, |
| 171 | .iInterface = STR_DESC_INTF_CCID, |
| 172 | }, |
| 173 | .class = { |
| 174 | .bLength = sizeof(struct usb_ccid_class_descriptor), |
| 175 | .bDescriptorType = 33, |
| 176 | .bcdCCID = LE16(0x0110), |
| 177 | .bMaxSlotIndex = 7, |
Eric Wild | 7603390 | 2019-10-01 15:04:01 +0200 | [diff] [blame] | 178 | .bVoltageSupport = 0x07, /* 5/3/1.8V */ |
| 179 | .dwProtocols = 0x03, |
Harald Welte | 34a8706 | 2019-04-19 22:33:36 +0200 | [diff] [blame] | 180 | .dwDefaultClock = LE32(2500), |
| 181 | .dwMaximumClock = LE32(20000), |
| 182 | .bNumClockSupported = 4, |
| 183 | .dwDataRate = LE32(9600), |
| 184 | .dwMaxDataRate = LE32(921600), |
| 185 | .bNumDataRatesSupported = 0, |
| 186 | .dwMaxIFSD = LE32(0), |
| 187 | .dwSynchProtocols = LE32(0), |
| 188 | .dwMechanical = LE32(0), |
Eric Wild | 7603390 | 2019-10-01 15:04:01 +0200 | [diff] [blame] | 189 | .dwFeatures = LE32(0x10 | 0x00010000), |
Harald Welte | 34a8706 | 2019-04-19 22:33:36 +0200 | [diff] [blame] | 190 | .dwMaxCCIDMessageLength = 272, |
| 191 | .bClassGetResponse = 0xff, |
| 192 | .bClassEnvelope = 0xff, |
| 193 | .wLcdLayout = LE16(0), |
| 194 | .bPINSupport = 0, |
| 195 | .bMaxCCIDBusySlots = 8, |
| 196 | }, |
| 197 | .ep = { |
| 198 | { /* Bulk-OUT descriptor */ |
| 199 | .bLength = sizeof(struct usb_ep_desc), |
| 200 | .bDescriptorType = USB_DT_ENDPOINT, |
| 201 | .bEndpointAddress = 0x02, |
| 202 | .bmAttributes = USB_EP_TYPE_BULK, |
| 203 | .wMaxPacketSize = 64, |
| 204 | .bInterval = 0, |
| 205 | }, |
| 206 | { /* Bulk-IN descriptor */ |
| 207 | .bLength = sizeof(struct usb_ep_desc), |
| 208 | .bDescriptorType = USB_DT_ENDPOINT, |
| 209 | .bEndpointAddress = 0x83, |
| 210 | .bmAttributes = USB_EP_TYPE_BULK, |
| 211 | .wMaxPacketSize = 64, |
| 212 | .bInterval = 0, |
| 213 | }, |
| 214 | { /* Interrupt dscriptor */ |
| 215 | .bLength = sizeof(struct usb_ep_desc), |
| 216 | .bDescriptorType = USB_DT_ENDPOINT, |
| 217 | .bEndpointAddress = 0x84, |
| 218 | .bmAttributes = USB_EP_TYPE_INTERRUPT, |
| 219 | .wMaxPacketSize = 64, |
| 220 | .bInterval = 0x10, |
| 221 | }, |
| 222 | }, |
| 223 | }, |
| 224 | //DFURT_IF_DESCRIPTOR, |
| 225 | .str = { |
| 226 | #if 0 |
| 227 | CDCD_ACM_STR_DESCES |
| 228 | #else |
| 229 | 4, 3, 0x09, 0x04, |
| 230 | 18, 3, 's',0, 'y',0, 's',0, 'm',0, 'o',0, 'c',0, 'o',0, 'm',0, |
| 231 | 24, 3, 's',0, 'y',0, 's',0, 'm',0, 'o',0, 'O',0, 'C',0, 'T',0, 'S',0, 'I',0, 'M',0, |
| 232 | 4, 3, 'A', 0, |
| 233 | 22, 3, 'd',0, 'e',0, 'b',0, 'u',0, 'g',0, ' ',0, 'U',0, 'A',0, 'R',0, 'T',0, |
| 234 | 22, 3, 'd',0, 'e',0, 'b',0, 'u',0, 'g',0, ' ',0, 'U',0, 'A',0, 'R',0, 'T',0, |
| 235 | 10, 3, 'C',0, 'C',0, 'I',0, 'D',0, |
| 236 | 12, 3, 'F',0, 'I',0, 'X',0, 'M',0, 'E',0, |
| 237 | #endif |
| 238 | } |
| 239 | }; |
| 240 | |
| 241 | const struct usbd_descriptors usb_descs[] |
| 242 | = {{ (uint8_t *)&usb_fs_descs, (uint8_t *)&usb_fs_descs + sizeof(usb_fs_descs) }}; |