Embedded SDK
Embedded SDK
usbd_impl.c
Go to the documentation of this file.
1 
48 #include "os.h"
49 #include "os_io_usb.h"
50 
51 /* Includes ------------------------------------------------------------------*/
52 
53 #include "usbd_hid.h"
54 #include "usbd_hid_impl.h"
55 
56 #include "usbd_ctlreq.h"
57 
58 #include "usbd_core.h"
59 #include "usbd_conf.h"
60 
61 #include "usbd_def.h"
62 #include "os_io_seproxyhal.h"
63 
64 #pragma GCC diagnostic push
65 #pragma GCC diagnostic ignored "-Wcast-qual"
66 
67 #ifdef HAVE_IO_U2F
68 #include "u2f_transport.h"
69 #include "u2f_impl.h"
70 #endif // HAVE_IO_U2F
71 
72 #ifdef HAVE_USB_CLASS_CCID
73 #include "usbd_ccid_core.h"
74 #endif // HAVE_USB_CLASS_CCID
75 
118 #define USBD_LANGID_STRING 0x409
119 
120 // clang-format off
121 #ifdef HAVE_VID_PID_PROBER
122 #define USBD_VID 0x2581
123 #define USBD_PID 0xf1d1
124 static uint8_t const USBD_PRODUCT_FS_STRING[] = {
125  10*2+2,
126  USB_DESC_TYPE_STRING,
127  'N', 0,
128  'a', 0,
129  'n', 0,
130  'o', 0,
131  '-', 0,
132  'U', 0,
133  '2', 0,
134  'F', 0,
135  '-', 0,
136  'P', 0,
137 };
138 #else
139 #define USBD_VID 0x2C97
140 
141 #if defined(TARGET_NANOS)
142 #ifndef HAVE_LEGACY_PID
143 #define USBD_PID 0x1000
144 #else // HAVE_LEGACY_PID
145 #define USBD_PID 0x0001
146 #endif // HAVE_LEGACY_PID
147 static uint8_t const USBD_PRODUCT_FS_STRING[] = {
148  6*2+2,
149  USB_DESC_TYPE_STRING,
150  'N', 0,
151  'a', 0,
152  'n', 0,
153  'o', 0,
154  ' ', 0,
155  'S', 0,
156 };
157 #elif defined(TARGET_HW2)
158 #ifndef HAVE_LEGACY_PID
159 #define USBD_PID 0x3000
160 #else // HAVE_LEGACY_PID
161 #define USBD_PID 0x0003
162 #endif // HAVE_LEGACY_PID
163 static uint8_t const USBD_PRODUCT_FS_STRING[] = {
164  3*2+2,
165  USB_DESC_TYPE_STRING,
166  'H', 0,
167  'W', 0,
168  '2', 0,
169 };
170 #elif defined(TARGET_NANOX)
171 #ifndef HAVE_LEGACY_PID
172 #define USBD_PID 0x4000
173 #else // HAVE_LEGACY_PID
174 #define USBD_PID 0x0004
175 #endif // HAVE_LEGACY_PID
176 static uint8_t const USBD_PRODUCT_FS_STRING[] = {
177  6*2+2,
178  USB_DESC_TYPE_STRING,
179  'N', 0,
180  'a', 0,
181  'n', 0,
182  'o', 0,
183  ' ', 0,
184  'X', 0,
185 };
186 #elif defined(TARGET_NANOS2)
187 #ifndef HAVE_LEGACY_PID
188 #define USBD_PID 0x5000
189 #else // HAVE_LEGACY_PID
190 #define USBD_PID 0x0005
191 #endif // HAVE_LEGACY_PID
192 static uint8_t const USBD_PRODUCT_FS_STRING[] = {
193  11*2+2,
194  USB_DESC_TYPE_STRING,
195  'N', 0,
196  'a', 0,
197  'n', 0,
198  'o', 0,
199  ' ', 0,
200  'S', 0,
201  ' ', 0,
202  'P', 0,
203  'l', 0,
204  'u', 0,
205  's', 0,
206 };
207 #elif defined(TARGET_STAX)
208 #ifndef HAVE_LEGACY_PID
209 #define USBD_PID 0x6000
210 #else // HAVE_LEGACY_PID
211 #define USBD_PID 0x0006
212 #endif // HAVE_LEGACY_PID
213 static uint8_t const USBD_PRODUCT_FS_STRING[] = {
214  11*2+2,
215  USB_DESC_TYPE_STRING,
216  'L', 0,
217  'e', 0,
218  'd', 0,
219  'g', 0,
220  'e', 0,
221  'r', 0,
222  ' ', 0,
223  'S', 0,
224  't', 0,
225  'a', 0,
226  'x', 0,
227 };
228 #elif defined(TARGET_FLEX)
229 #ifndef HAVE_LEGACY_PID
230 #define USBD_PID 0x7000
231 #else // HAVE_LEGACY_PID
232 #define USBD_PID 0x0007
233 #endif // HAVE_LEGACY_PID
234 static uint8_t const USBD_PRODUCT_FS_STRING[] = {
235  11*2+2,
236  USB_DESC_TYPE_STRING,
237  'L', 0,
238  'e', 0,
239  'd', 0,
240  'g', 0,
241  'e', 0,
242  'r', 0,
243  ' ', 0,
244  'F', 0,
245  'l', 0,
246  'e', 0,
247  'x', 0,
248 };
249 #else
250 #error unknown TARGET_NAME
251 #endif
252 #endif
253 
254 /* USB Standard Device Descriptor */
255 static uint8_t const USBD_LangIDDesc[]=
256 {
257  USB_LEN_LANGID_STR_DESC,
258  USB_DESC_TYPE_STRING,
259  LOBYTE(USBD_LANGID_STRING),
260  HIBYTE(USBD_LANGID_STRING),
261 };
262 
263 static uint8_t const USB_SERIAL_STRING[] =
264 {
265  4*2+2,
266  USB_DESC_TYPE_STRING,
267  '0', 0,
268  '0', 0,
269  '0', 0,
270  '1', 0,
271 };
272 
273 static uint8_t const USBD_MANUFACTURER_STRING[] = {
274  6*2+2,
275  USB_DESC_TYPE_STRING,
276  'L', 0,
277  'e', 0,
278  'd', 0,
279  'g', 0,
280  'e', 0,
281  'r', 0,
282 };
283 
284 #define USBD_INTERFACE_FS_STRING USBD_PRODUCT_FS_STRING
285 #define USBD_CONFIGURATION_FS_STRING USBD_PRODUCT_FS_STRING
286 
287 #ifndef HAVE_USB_HIDKBD
288 
289 static uint8_t const HID_ReportDesc[] = {
290  0x06, 0xA0, 0xFF, // Usage page (vendor defined)
291  0x09, 0x01, // Usage ID (vendor defined)
292  0xA1, 0x01, // Collection (application)
293 
294  // The Input report
295  0x09, 0x03, // Usage ID - vendor defined
296  0x15, 0x00, // Logical Minimum (0)
297  0x26, 0xFF, 0x00, // Logical Maximum (255)
298  0x75, 0x08, // Report Size (8 bits)
299  0x95, HID_EPIN_SIZE, // Report Count (64 fields)
300  0x81, 0x08, // Input (Data, Variable, Absolute)
301 
302  // The Output report
303  0x09, 0x04, // Usage ID - vendor defined
304  0x15, 0x00, // Logical Minimum (0)
305  0x26, 0xFF, 0x00, // Logical Maximum (255)
306  0x75, 0x08, // Report Size (8 bits)
307  0x95, HID_EPOUT_SIZE, // Report Count (64 fields)
308  0x91, 0x08, // Output (Data, Variable, Absolute)
309  0xC0
310 };
311 
312 #else
313 
314 static uint8_t const HID_ReportDesc_kbd[] = {
315  0x05, 0x01,
316  0x09, 0x06,
317  0xA1, 0x01,
318  0x05, 0x07,
319  0x19, 0xE0,
320  0x29, 0xE7,
321  0x15, 0x00,
322  0x25, 0x01,
323  0x75, 0x01,
324  0x95, 0x08,
325  0x81, 0x02,
326  0x95, 0x01,
327  0x75, 0x08,
328  0x81, 0x01,
329  0x95, 0x05,
330  0x75, 0x01,
331  0x05, 0x08,
332  0x19, 0x01,
333  0x29, 0x05,
334  0x91, 0x02,
335  0x95, 0x01,
336  0x75, 0x03,
337  0x91, 0x01,
338  0x95, 0x06,
339  0x75, 0x08,
340  0x15, 0x00,
341  0x25, 0x65,
342  0x05, 0x07,
343  0x19, 0x00,
344  0x29, 0x65,
345  0x81, 0x00,
346  0xC0
347 };
348 #endif // HAVE_USB_HIDKBD
349 
350 #ifdef HAVE_IO_U2F
351 static uint8_t const HID_ReportDesc_fido[] = {
352  0x06, 0xD0, 0xF1, // Usage page (vendor defined)
353  0x09, 0x01, // Usage ID (vendor defined)
354  0xA1, 0x01, // Collection (application)
355 
356  // The Input report
357  0x09, 0x03, // Usage ID - vendor defined
358  0x15, 0x00, // Logical Minimum (0)
359  0x26, 0xFF, 0x00, // Logical Maximum (255)
360  0x75, 0x08, // Report Size (8 bits)
361  0x95, U2F_EPIN_SIZE, // Report Count (64 fields)
362  0x81, 0x08, // Input (Data, Variable, Absolute)
363 
364  // The Output report
365  0x09, 0x04, // Usage ID - vendor defined
366  0x15, 0x00, // Logical Minimum (0)
367  0x26, 0xFF, 0x00, // Logical Maximum (255)
368  0x75, 0x08, // Report Size (8 bits)
369  0x95, U2F_EPOUT_SIZE, // Report Count (64 fields)
370  0x91, 0x08, // Output (Data, Variable, Absolute)
371  0xC0
372 };
373 #endif // HAVE_IO_U2F
374 
375 #define ARRAY_U2LE(l) (l)&0xFF, (l)>>8
376 
377 #define CFG_HDR_LEN (0x9)
378 #define CFG_HIDGEN_LEN (0x9+0x9+0x7+0x7)
379 #define CFG_IO_U2F_LEN (0x9+0x9+0x7+0x7)
380 #define CFG_USB_CCID_LEN (0x9+0x36+0x7+0x7)
381 #define CFG_WEBUSB_LEN (0x9+0x7+0x7)
382 
383 /* USB HID device Configuration Descriptor */
384 #ifdef HAVE_USB_CLASS_CCID
385 // Note: keeping const qualifier to ensure the good section is used by the linker.
386 // This table is mapped in NVRAM section and therefore it is correctly initialized,
387 // normal Read is possible and Write can be done through nvm_write() calls.
388 static __ALIGN_BEGIN uint8_t const N_USBD_CfgDesc[] __ALIGN_END =
389 #else
390 static __ALIGN_BEGIN uint8_t const USBD_CfgDesc[] __ALIGN_END =
391 #endif // HAVE_USB_CLASS_CCID
392 {
393  0x09, /* bLength: Configuration Descriptor size */
394  USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
395  ARRAY_U2LE(CFG_HDR_LEN /* wTotalLength: Bytes returned */
397 #ifdef HAVE_IO_U2F
399 #endif // HAVE_IO_U2F
400 #ifdef HAVE_USB_CLASS_CCID
402 #endif // HAVE_USB_CLASS_CCID
403 #ifdef HAVE_WEBUSB
405 #endif // HAVE_WEBUSB
406  ),
407  1
408 #ifdef HAVE_IO_U2F
409  +1
410 #endif // HAVE_IO_U2F
411 #ifdef HAVE_USB_CLASS_CCID
412  +1
413 #endif // HAVE_USB_CLASS_CCID
414 #ifdef HAVE_WEBUSB
415  +1
416 #endif // HAVE_WEBUSB
417  , /*bNumInterfaces */
418  0x01, /*bConfigurationValue: Configuration value*/
419  USBD_IDX_PRODUCT_STR, /*iConfiguration: Index of string descriptor describing the configuration*/
420  0xC0, /*bmAttributes: bus powered */
421  0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/
422 
423 #ifndef HAVE_USB_HIDKBD
424  /* HIDGEN ################################################################################################ */
425 
426  /************** Descriptor of KBD HID interface ****************/
427  0x09, /*bLength: Interface Descriptor size*/
428  USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
429  HID_INTF, /*bInterfaceNumber: Number of Interface*/
430  0x00, /*bAlternateSetting: Alternate setting*/
431  0x02, /*bNumEndpoints*/
432  0x03, /*bInterfaceClass: HID*/
433  0x00, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
434  0x00, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
435  USBD_IDX_PRODUCT_STR, /*iInterface: Index of string descriptor*/
436 
437  /******************** Descriptor of HID *************************/
438  0x09, /*bLength: HID Descriptor size*/
439  HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
440  0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
441  0x01,
442  0x00, /*bCountryCode: Hardware target country*/
443  0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
444  0x22, /*bDescriptorType*/
445  sizeof(HID_ReportDesc),/*wItemLength: Total length of Report descriptor*/
446  0x00,
447 
448  /******************** Descriptor of Custom HID endpoints ********************/
449  0x07, /*bLength: Endpoint Descriptor size*/
450  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
451  HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
452  0x03, /*bmAttributes: Interrupt endpoint*/
453  HID_EPIN_SIZE, /*wMaxPacketSize: 2 Byte max */
454  0x00,
455  0x01, /*bInterval: Polling Interval (20 ms)*/
456 
457  0x07, /* bLength: Endpoint Descriptor size */
458  USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
459  HID_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (OUT)*/
460  0x03, /* bmAttributes: Interrupt endpoint */
461  HID_EPOUT_SIZE, /* wMaxPacketSize: 2 Bytes max */
462  0x00,
463  0x01, /* bInterval: Polling Interval (20 ms) */
464 
465 #else
466  /* HIDKBD ################################################################################################ */
467 
468  /************** Descriptor of KBD HID interface ****************/
469  0x09, /*bLength: Interface Descriptor size*/
470  USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
471  0x00, /*bInterfaceNumber: Number of Interface*/
472  0x00, /*bAlternateSetting: Alternate setting*/
473  0x02, /*bNumEndpoints*/
474  0x03, /*bInterfaceClass: HID*/
475  0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
476  0x01, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
477  USBD_IDX_PRODUCT_STR, /*iInterface: Index of string descriptor*/
478 
479  /******************** Descriptor of HID *************************/
480  0x09, /*bLength: HID Descriptor size*/
481  HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
482  0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
483  0x01,
484  0x21, /*bCountryCode: Hardware target country*/ // 0x21: US, 0x08: FR, 0x0D: ISO Intl
485  0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
486  0x22, /*bDescriptorType*/
487  sizeof(HID_ReportDesc_kbd),/*wItemLength: Total length of Report descriptor*/
488  0x00,
489  /******************** Descriptor of Custom HID endpoints ********************/
490  0x07, /*bLength: Endpoint Descriptor size*/
491  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
492  HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
493  0x03, /*bmAttributes: Interrupt endpoint*/
494  8, /*wMaxPacketSize: */
495  0x00,
496  0x01, /*bInterval: Polling Interval */
497 
498  0x07, /* bLength: Endpoint Descriptor size */
499  USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
500  HID_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (OUT)*/
501  0x03, /* bmAttributes: Interrupt endpoint */
502  8, /* wMaxPacketSize: */
503  0x00,
504  0x01, /* bInterval: Polling Interval */
505 #endif // HAVE_USB_HIDKBD
506 
507 #ifdef HAVE_IO_U2F
508  /* HID FIDO ################################################################################################ */
509 
510  /************** Descriptor of HID FIDO interface ****************/
511  0x09, /*bLength: Interface Descriptor size*/
512  USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
513  U2F_INTF, /*bInterfaceNumber: Number of Interface*/
514  0x00, /*bAlternateSetting: Alternate setting*/
515  0x02, /*bNumEndpoints*/
516  0x03, /*bInterfaceClass: HID*/
517  0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
518  0x01, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
519  USBD_IDX_PRODUCT_STR, /*iInterface: Index of string descriptor*/
520 
521  /******************** Descriptor of HID *************************/
522  0x09, /*bLength: HID Descriptor size*/
523  HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
524  0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
525  0x01,
526  0x21, /*bCountryCode: Hardware target country*/ // 0x21: US, 0x08: FR, 0x0D: ISO Intl
527  0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
528  0x22, /*bDescriptorType*/
529  sizeof(HID_ReportDesc_fido),/*wItemLength: Total length of Report descriptor*/
530  0x00,
531  /******************** Descriptor of Custom HID endpoints ********************/
532  0x07, /*bLength: Endpoint Descriptor size*/
533  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
534  U2F_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
535  0x03, /*bmAttributes: Interrupt endpoint*/
536  U2F_EPIN_SIZE, /*wMaxPacketSize: */
537  0x00,
538  0x01, /*bInterval: Polling Interval */
539 
540  0x07, /* bLength: Endpoint Descriptor size */
541  USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
542  U2F_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (OUT)*/
543  0x03, /* bmAttributes: Interrupt endpoint */
544  U2F_EPOUT_SIZE, /* wMaxPacketSize: */
545  0x00,
546  0x01,/* bInterval: Polling Interval */
547 #endif // HAVE_IO_U2F
548 
549 #ifdef HAVE_USB_CLASS_CCID
550  /* CCID ################################################################################################ */
551 
552  /******************** CCID **** interface ********************/
553  0x09, /* bLength: Interface Descriptor size */
554  0x04, /* bDescriptorType: */
555  CCID_INTF, /* bInterfaceNumber: Number of Interface */
556  0x00, /* bAlternateSetting: Alternate setting */
557  0x02, /* bNumEndpoints: endpoints used */
558  0x0B, /* bInterfaceClass: user's interface for CCID */
559  0x00, /* bInterfaceSubClass : */
560  0x00, /* nInterfaceProtocol : None */
561  0x05, /* iInterface: */
562 
563  /******************* CCID class descriptor ********************/
564  0x36, /* bLength: CCID Descriptor size */
565  0x21, /* bDescriptorType: Functional Descriptor type. */
566  0x10, /* bcdCCID(LSB): CCID Class Spec release number (1.00) */
567  0x01, /* bcdCCID(MSB) */
568 
569  0x00, /* bMaxSlotIndex :highest available slot on this device */
570  0x03, /* bVoltageSupport: bit Wise OR for 01h-5.0V 02h-3.0V
571  04h 1.8V*/
572 
573  0x01,0x00,0x00,0x00, /* dwProtocols: 0001h = Protocol T=0 */
574  0x10,0x0E,0x00,0x00, /* dwDefaultClock: 3.6Mhz = 3600kHz = 0x0E10,
575  for 4 Mhz the value is (0x00000FA0) :
576  This is used in ETU and waiting time calculations*/
577  0x10,0x0E,0x00,0x00, /* dwMaximumClock: Maximum supported ICC clock frequency
578  in KHz. So, 3.6Mhz = 3600kHz = 0x0E10,
579  4 Mhz (0x00000FA0) : */
580  0x00, /* bNumClockSupported : no setting from PC
581  If the value is 00h, the
582  supported clock frequencies are assumed to be the
583  default clock frequency defined by dwDefaultClock
584  and the maximum clock frequency defined by
585  dwMaximumClock */
586 
587  0xCD,0x25,0x00,0x00, /* dwDataRate: Default ICC I/O data rate in bps
588  9677 bps = 0x25CD
589  for example 10752 bps (0x00002A00) */
590 
591  0xCD,0x25,0x00,0x00, /* dwMaxDataRate: Maximum supported ICC I/O data
592  rate in bps */
593  0x00, /* bNumDataRatesSupported :
594  The number of data rates that are supported by the CCID
595  If the value is 00h, all data rates between the default
596  data rate dwDataRate and the maximum data rate
597  dwMaxDataRate are supported.
598  Dont support GET_CLOCK_FREQUENCIES
599  */
600  //46
601  0x00,0x00,0x00,0x00, /* dwMaxIFSD: 0 (T=0 only) */
602  0x00,0x00,0x00,0x00, /* dwSynchProtocols */
603  0x00,0x00,0x00,0x00, /* dwMechanical: no special characteristics */
604 
605  0xBA, 0x06, 0x02, 0x00,
606  //0x38,0x00,EXCHANGE_LEVEL_FEATURE,0x00,
607  /* dwFeatures: clk, baud rate, voltage : automatic */
608  /* 00000008h Automatic ICC voltage selection
609  00000010h Automatic ICC clock frequency change
610  00000020h Automatic baud rate change according to
611  active parameters provided by the Host or self
612  determined 00000100h CCID can set
613  ICC in clock stop mode
614 
615  Only one of the following values may be present to
616  select a level of exchange:
617  00010000h TPDU level exchanges with CCID
618  00020000h Short APDU level exchange with CCID
619  00040000h Short and Extended APDU level exchange
620  If none of those values : character level of exchange*/
621  0x0F,0x01,0x00,0x00, /* dwMaxCCIDMessageLength: Maximum block size + header*/
622  /* 261 + 10 */
623 
624  0x00, /* bClassGetResponse*/
625  0x00, /* bClassEnvelope */
626  0x00,0x00, /* wLcdLayout : 0000h no LCD. */
627  0x00, /* bPINSupport : no PIN verif and modif */
628  0x01, /* bMaxCCIDBusySlots */
629 
630  /******************** CCID Endpoints ********************/
631  0x07, /*Endpoint descriptor length = 7*/
632  0x05, /*Endpoint descriptor type */
633  CCID_BULK_IN_EP, /*Endpoint address (IN, address 1) */
634  0x02, /*Bulk endpoint type */
635  LOBYTE(CCID_BULK_EPIN_SIZE),
636  HIBYTE(CCID_BULK_EPIN_SIZE),
637  0x00, /*Polling interval in milliseconds */
638 
639  0x07, /*Endpoint descriptor length = 7 */
640  0x05, /*Endpoint descriptor type */
641  CCID_BULK_OUT_EP, /*Endpoint address (OUT, address 1) */
642  0x02, /*Bulk endpoint type */
643  LOBYTE(CCID_BULK_EPOUT_SIZE),
644  HIBYTE(CCID_BULK_EPOUT_SIZE),
645  0x00, /*Polling interval in milliseconds*/
646 #endif // HAVE_USB_CLASS_CCID
647 
648 #ifdef HAVE_WEBUSB
649  /* WEBUSB ################################################################################################ */
650 
651  /************** Descriptor of WEBUSB interface ****************/
652  0x09, /*bLength: Interface Descriptor size*/
653  USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
654  WEBUSB_INTF, /*bInterfaceNumber: Number of Interface*/
655  0x00, /*bAlternateSetting: Alternate setting*/
656  0x02, /*bNumEndpoints*/
657  0xFF, /*bInterfaceClass: WINUSB*/
658  0xFF, /*bInterfaceSubClass : WINUSB*/
659  0xFF, /*nInterfaceProtocol : WINUSB*/
660  USBD_IDX_PRODUCT_STR, /*iInterface: Index of string descriptor*/
661 
662  /******************** Descriptor of endpoints ********************/
663  0x07, /*bLength: Endpoint Descriptor size*/
664  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
665  WEBUSB_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
666  0x03, /*bmAttributes: Interrupt endpoint*/
667  WEBUSB_EPIN_SIZE, /*wMaxPacketSize: */
668  0x00,
669  0x01, /*bInterval: Polling Interval */
670 
671  0x07, /* bLength: Endpoint Descriptor size */
672  USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
673  WEBUSB_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (OUT)*/
674  0x03, /* bmAttributes: Interrupt endpoint */
675  WEBUSB_EPOUT_SIZE, /* wMaxPacketSize: */
676  0x00,
677  0x01,/* bInterval: Polling Interval */
678 #endif // HAVE_WEBUSB
679 } ;
680 
681 #ifdef HAVE_IO_U2F
682 /* USB HID device Configuration Descriptor */
683 __ALIGN_BEGIN uint8_t const USBD_HID_Desc_fido[] __ALIGN_END =
684 {
685  /******************** Descriptor of HID *************************/
686  0x09, /*bLength: HID Descriptor size*/
687  HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
688  0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
689  0x01,
690  0x21, /*bCountryCode: Hardware target country*/ // 0x21: US, 0x08: FR, 0x0D: ISO Intl
691  0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
692  0x22, /*bDescriptorType*/
693  sizeof(HID_ReportDesc_fido),/*wItemLength: Total length of Report descriptor*/
694  0x00,
695 };
696 #endif // HAVE_IO_U2F
697 
698 #ifndef HAVE_USB_HIDKBD
699 /* USB HID device Configuration Descriptor */
700 __ALIGN_BEGIN uint8_t const USBD_HID_Desc[] __ALIGN_END =
701 {
702  /* 18 */
703  0x09, /*bLength: HID Descriptor size*/
704  HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
705  0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
706  0x01,
707  0x00, /*bCountryCode: Hardware target country*/
708  0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
709  0x22, /*bDescriptorType*/
710  sizeof(HID_ReportDesc),/*wItemLength: Total length of Report descriptor*/
711  0x00,
712 };
713 #else
714 /* USB HID device Configuration Descriptor */
715 __ALIGN_BEGIN uint8_t const USBD_HID_Desc_kbd[] __ALIGN_END =
716 {
717  /******************** Descriptor of HID *************************/
718  0x09, /*bLength: HID Descriptor size*/
719  HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
720  0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
721  0x01,
722  0x21, /*bCountryCode: Hardware target country*/ // 0x21: US, 0x08: FR, 0x0D: ISO Intl
723  0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
724  0x22, /*bDescriptorType*/
725  sizeof(HID_ReportDesc_kbd),/*wItemLength: Total length of Report descriptor*/
726  0x00,
727 };
728 #endif // HAVE_USB_HIDKBD
729 
730 /* USB Standard Device Descriptor */
731 static __ALIGN_BEGIN uint8_t const USBD_DeviceQualifierDesc[] __ALIGN_END =
732 {
733  USB_LEN_DEV_QUALIFIER_DESC,
734  USB_DESC_TYPE_DEVICE_QUALIFIER,
735  0x00,
736  0x02,
737  0x00,
738  0x00,
739  0x00,
740  0x40,
741  0x01,
742  0x00,
743 };
744 
745 /* USB Standard Device Descriptor */
746 static uint8_t const USBD_DeviceDesc[]= {
747  0x12, /* bLength */
748  USB_DESC_TYPE_DEVICE, /* bDescriptorType */
749 #ifdef HAVE_WEBUSB
750  0x10, /* bcdUSB */
751 #else // HAVE_WEBUSB
752  0x00, /* bcdUSB */
753 #endif // HAVE_WEBUSB
754  0x02,
755  0x00, /* bDeviceClass */
756  0x00, /* bDeviceSubClass */
757  0x00, /* bDeviceProtocol */
758  USB_MAX_EP0_SIZE, /* bMaxPacketSize */
759  LOBYTE(USBD_VID), /* idVendor */
760  HIBYTE(USBD_VID), /* idVendor */
761  LOBYTE(USBD_PID), /* idProduct */
762  HIBYTE(USBD_PID), /* idProduct */
763 
764  // Change this ID to make windows WINUSB/WEBUSB reenumerate when the
765  // descriptor changes and the PID/VID are not changed.
766  0x01, /* bcdDevice rel. 2.01 */
767  0x02,
768  USBD_IDX_MFC_STR, /* Index of manufacturer string */
769  USBD_IDX_PRODUCT_STR, /* Index of product string */
770  USBD_IDX_SERIAL_STR, /* Index of serial number string */
771  1 /* bNumConfigurations */
772 }; /* USB_DeviceDescriptor */
773 // clang-format on
774 
781 static uint8_t *USBD_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
782 {
783  UNUSED(speed);
784  *length = sizeof(USBD_DeviceDesc);
785  return (uint8_t *) USBD_DeviceDesc;
786 }
787 
794 static uint8_t *USBD_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
795 {
796  UNUSED(speed);
797  *length = sizeof(USBD_LangIDDesc);
798  return (uint8_t *) USBD_LangIDDesc;
799 }
800 
807 static uint8_t *USBD_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
808 {
809  UNUSED(speed);
810  *length = sizeof(USBD_PRODUCT_FS_STRING);
811  return (uint8_t *) USBD_PRODUCT_FS_STRING;
812 }
813 
820 static uint8_t *USBD_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
821 {
822  UNUSED(speed);
823  *length = sizeof(USBD_MANUFACTURER_STRING);
824  return (uint8_t *) USBD_MANUFACTURER_STRING;
825 }
826 
833 static uint8_t *USBD_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
834 {
835  UNUSED(speed);
836  *length = sizeof(USB_SERIAL_STRING);
837  return (uint8_t *) USB_SERIAL_STRING;
838 }
839 
846 static uint8_t *USBD_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
847 {
848  UNUSED(speed);
849  *length = sizeof(USBD_CONFIGURATION_FS_STRING);
851 }
852 
859 static uint8_t *USBD_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
860 {
861  UNUSED(speed);
862  *length = sizeof(USBD_INTERFACE_FS_STRING);
864 }
865 
872 static uint8_t *USBD_GetDeviceQualifierDesc_impl(uint16_t *length)
873 {
874  *length = sizeof(USBD_DeviceQualifierDesc);
875  return (uint8_t *) USBD_DeviceQualifierDesc;
876 }
877 
885 static uint8_t *USBD_GetCfgDesc_impl(uint16_t *length)
886 {
887 #ifdef HAVE_USB_CLASS_CCID
888  *length = sizeof(N_USBD_CfgDesc);
889  return (uint8_t *) N_USBD_CfgDesc;
890 #else
891  *length = sizeof(USBD_CfgDesc);
892  return (uint8_t *) USBD_CfgDesc;
893 #endif
894 }
895 
897 {
898  switch (USBD_Device.request.wIndex & 0xFF) {
899 #ifdef HAVE_IO_U2F
900  case U2F_INTF:
901  *len = sizeof(USBD_HID_Desc_fido);
902  return (uint8_t *) USBD_HID_Desc_fido;
903 #endif // HAVE_IO_U2F
904 #ifndef HAVE_USB_HIDKBD
905  case HID_INTF:
906  *len = sizeof(USBD_HID_Desc);
907  return (uint8_t *) USBD_HID_Desc;
908 #else
909  case HID_INTF:
910  *len = sizeof(USBD_HID_Desc_kbd);
911  return (uint8_t *) USBD_HID_Desc_kbd;
912 #endif // HAVE_USB_HIDKBD
913  }
914  *len = 0;
915  return 0;
916 }
917 
919 {
920  switch (USBD_Device.request.wIndex & 0xFF) {
921 #ifdef HAVE_IO_U2F
922  case U2F_INTF:
923  *len = sizeof(HID_ReportDesc_fido);
924  return (uint8_t *) HID_ReportDesc_fido;
925 #endif // HAVE_IO_U2F
926 #ifndef HAVE_USB_HIDKBD
927  case HID_INTF:
928  *len = sizeof(HID_ReportDesc);
929  return (uint8_t *) HID_ReportDesc;
930 #else
931  case HID_INTF:
932  *len = sizeof(HID_ReportDesc_kbd);
933  return (uint8_t *) HID_ReportDesc_kbd;
934 #endif // HAVE_USB_HIDKBD
935  }
936  *len = 0;
937  return 0;
938 }
939 
940 #ifdef HAVE_USB_CLASS_CCID
945 const volatile uint8_t *USBD_GetPinPadOffset(void)
946 {
947  unsigned short length = 0;
948  uint8_t *cfgDesc = NULL;
949  unsigned short offset = 0;
950 
951  cfgDesc = USBD_GetCfgDesc_impl(&length);
952 
953  offset = CFG_HDR_LEN + CFG_HIDGEN_LEN;
954 #ifdef HAVE_IO_U2F
955  offset += CFG_IO_U2F_LEN;
956 #endif // HAVE_IO_U2F
957  // Offset of the parameter 'bPINSupport' inside the CCID interface structure in N_USBD_CfgDesc
958  offset += 61;
959 
960  // Returns a const volatile pointer allowing callers to do
961  // - write operations through nvram_write
962  // - read operation without potential compilation optimization issue thanks to the volatile
963  // qualifier.
964  return (const volatile uint8_t *) (cfgDesc + offset);
965 }
966 #endif // HAVE_USB_CLASS_CCID
967 
983 #ifdef HAVE_IO_U2F
984 
992 uint8_t USBD_U2F_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
993 {
994  UNUSED(cfgidx);
995 
996  /* Open EP IN */
997  USBD_LL_OpenEP(pdev, U2F_EPIN_ADDR, USBD_EP_TYPE_INTR, U2F_EPIN_SIZE);
998 
999  /* Open EP OUT */
1000  USBD_LL_OpenEP(pdev, U2F_EPOUT_ADDR, USBD_EP_TYPE_INTR, U2F_EPOUT_SIZE);
1001 
1002  /* Prepare Out endpoint to receive 1st packet */
1003  USBD_LL_PrepareReceive(pdev, U2F_EPOUT_ADDR, U2F_EPOUT_SIZE);
1004 
1005  return USBD_OK;
1006 }
1007 
1008 uint8_t USBD_U2F_DataIn_impl(USBD_HandleTypeDef *pdev, uint8_t epnum)
1009 {
1010  UNUSED(pdev);
1011  // only the data hid endpoint will receive data
1012  switch (epnum) {
1013  // FIDO endpoint
1014  case (U2F_EPIN_ADDR & 0x7F):
1015  // advance the u2f sending machine state
1016  u2f_transport_sent(&G_io_u2f, U2F_MEDIA_USB);
1017  break;
1018  }
1019  return USBD_OK;
1020 }
1021 
1022 uint8_t USBD_U2F_DataOut_impl(USBD_HandleTypeDef *pdev,
1023  uint8_t epnum,
1024  uint8_t *buffer,
1025  __attribute__((unused)) apdu_buffer_t *apdu_buf)
1026 {
1027 #ifdef HAVE_LOCAL_APDU_BUFFER
1028 #error "Feature not implemented"
1029 #endif
1030 
1031  switch (epnum) {
1032  // FIDO endpoint
1033  case (U2F_EPOUT_ADDR & 0x7F):
1034  USBD_LL_PrepareReceive(pdev, U2F_EPOUT_ADDR, U2F_EPOUT_SIZE);
1036  &G_io_u2f, buffer, io_seproxyhal_get_ep_rx_size(U2F_EPOUT_ADDR), U2F_MEDIA_USB);
1037  break;
1038  }
1039 
1040  return USBD_OK;
1041 }
1042 #endif // HAVE_IO_U2F
1043 
1044 uint8_t USBD_HID_DataIn_impl(USBD_HandleTypeDef *pdev, uint8_t epnum)
1045 {
1046  UNUSED(pdev);
1047  switch (epnum) {
1048  // HID gen endpoint
1049  case (HID_EPIN_ADDR & 0x7F):
1050  io_usb_hid_sent(io_usb_send_apdu_data);
1051  break;
1052  }
1053 
1054  return USBD_OK;
1055 }
1056 
1057 uint8_t USBD_HID_DataOut_impl(USBD_HandleTypeDef *pdev,
1058  uint8_t epnum,
1059 #ifndef HAVE_USB_HIDKBD
1060  uint8_t *buffer,
1061  apdu_buffer_t *apdu_buf
1062 #else
1063  __attribute__((unused)) uint8_t *buffer,
1064  __attribute__((unused)) apdu_buffer_t *apdu_buf
1065 #endif // HAVE_USB_HIDKBD
1066 )
1067 {
1068  // only the data hid endpoint will receive data
1069  switch (epnum) {
1070  // HID gen endpoint
1071  case (HID_EPOUT_ADDR & 0x7F):
1072  // prepare receiving the next chunk (masked time)
1074 
1075 #ifndef HAVE_USB_HIDKBD
1076  // avoid troubles when an apdu has not been replied yet
1077  if (G_io_app.apdu_media == IO_APDU_MEDIA_NONE) {
1078  // add to the hid transport
1079  switch (io_usb_hid_receive(io_usb_send_apdu_data,
1080  buffer,
1081  io_seproxyhal_get_ep_rx_size(HID_EPOUT_ADDR),
1082  apdu_buf)) {
1083  default:
1084  break;
1085 
1086  case IO_USB_APDU_RECEIVED:
1087  G_io_app.apdu_media = IO_APDU_MEDIA_USB_HID; // for application code
1088  G_io_app.apdu_state = APDU_USB_HID; // for next call to io_exchange
1089  G_io_app.apdu_length = G_io_usb_hid_total_length;
1090  break;
1091  }
1092  }
1093 #endif // HAVE_USB_HIDKBD
1094  break;
1095  }
1096 
1097  return USBD_OK;
1098 }
1099 
1100 #ifdef HAVE_WEBUSB
1101 
1102 uint8_t USBD_WEBUSB_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
1103 {
1104  UNUSED(cfgidx);
1105 
1106  /* Open EP IN */
1107  USBD_LL_OpenEP(pdev, WEBUSB_EPIN_ADDR, USBD_EP_TYPE_INTR, WEBUSB_EPIN_SIZE);
1108 
1109  /* Open EP OUT */
1110  USBD_LL_OpenEP(pdev, WEBUSB_EPOUT_ADDR, USBD_EP_TYPE_INTR, WEBUSB_EPOUT_SIZE);
1111 
1112  /* Prepare Out endpoint to receive 1st packet */
1113  USBD_LL_PrepareReceive(pdev, WEBUSB_EPOUT_ADDR, WEBUSB_EPOUT_SIZE);
1114 
1115  return USBD_OK;
1116 }
1117 
1118 uint8_t USBD_WEBUSB_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
1119 {
1120  UNUSED(pdev);
1121  UNUSED(cfgidx);
1122  return USBD_OK;
1123 }
1124 
1125 uint8_t USBD_WEBUSB_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
1126 {
1127  UNUSED(pdev);
1128  UNUSED(req);
1129  return USBD_OK;
1130 }
1131 
1132 uint8_t USBD_WEBUSB_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
1133 {
1134  UNUSED(pdev);
1135  switch (epnum) {
1136  // HID gen endpoint
1137  case (WEBUSB_EPIN_ADDR & 0x7F):
1138  io_usb_hid_sent(io_usb_send_apdu_data_ep0x83);
1139  break;
1140  }
1141  return USBD_OK;
1142 }
1143 
1144 uint8_t USBD_WEBUSB_DataOut(USBD_HandleTypeDef *pdev,
1145  uint8_t epnum,
1146  uint8_t *buffer,
1147  apdu_buffer_t *apdu_buf)
1148 {
1149  // only the data hid endpoint will receive data
1150  switch (epnum) {
1151  // HID gen endpoint
1152  case (WEBUSB_EPOUT_ADDR & 0x7F):
1153  // prepare receiving the next chunk (masked time)
1154  USBD_LL_PrepareReceive(pdev, WEBUSB_EPOUT_ADDR, WEBUSB_EPOUT_SIZE);
1155 
1156  // avoid troubles when an apdu has not been replied yet
1157  if (G_io_app.apdu_media == IO_APDU_MEDIA_NONE) {
1158  // add to the hid transport
1159  switch (io_usb_hid_receive(io_usb_send_apdu_data_ep0x83,
1160  buffer,
1161  io_seproxyhal_get_ep_rx_size(WEBUSB_EPOUT_ADDR),
1162  apdu_buf)) {
1163  default:
1164  break;
1165 
1166  case IO_USB_APDU_RECEIVED:
1167  G_io_app.apdu_media = IO_APDU_MEDIA_USB_WEBUSB; // for application code
1168  G_io_app.apdu_state = APDU_USB_WEBUSB; // for next call to io_exchange
1169  G_io_app.apdu_length = G_io_usb_hid_total_length;
1170  break;
1171  }
1172  }
1173  break;
1174  }
1175 
1176  return USBD_OK;
1177 }
1178 
1179 // arbitrary vendor chosen
1180 #define WEBUSB_VENDOR_CODE 0x1E
1181 
1182 // from https://wicg.github.io/webusb/#webusb-platform-capability-descriptor
1183 // see also this (for endianness explanation)
1184 // https://github.com/WICG/webusb/issues/115#issuecomment-352206549
1185 #define WEBUSB_UUID \
1186  0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65
1187 
1188 #define WEBUSB_REQ_GET_URL 0x02
1189 
1190 #define WEBUSB_DT_DESCRIPTOR_SET_HEADER 0
1191 #define WEBUSB_DT_CONFIGURATION_SUBSET_HEADER 1
1192 #define WEBUSB_DT_FUNCTION_SUBSET_HEADER 2
1193 #define WEBUSB_DT_URL 3
1194 
1195 #define WEBUSB_URL_SCHEME_HTTP 0
1196 #define WEBUSB_URL_SCHEME_HTTPS 1
1197 #define WEBUSB_URL_SCHEME_CUSTOM 255
1198 
1199 unsigned char const C_webusb_url_descriptor[] = {
1200  // bLength
1201  3 + WEBUSB_URL_SIZE_B,
1202  // bDescriptorType
1203  WEBUSB_DT_URL,
1204  // bScheme
1205  WEBUSB_URL_SCHEME_HTTPS,
1206  // URL
1207  WEBUSB_URL};
1208 
1209 /* USB 3.1 Descriptor Types - Table 9-6 */
1210 #define USB_DT_BOS 15
1211 #define USB_DT_DEVICE_CAPABILITY 16
1212 
1213 #define USB_DT_BOS_SIZE 5
1214 
1215 /* USB Device Capability Types - USB 3.1 Table 9-14 */
1216 #define USB_DC_PLATFORM 5
1217 
1218 #define MS_OS_20_DESCRIPTOR_LENGTH (0xb2)
1219 
1220 #define WINUSB_VENDOR_CODE 0x77
1221 
1222 // clang-format off
1223 unsigned char const C_usb_bos[] = {
1224  USB_DT_BOS_SIZE, // bLength (5)
1225  USB_DT_BOS, // bDescriptorType
1226  0x39, 0x00, // wTotalLength
1227  2, //bNumberDeviceCapabilities
1228 
1229  // capability descriptor
1230  8+16, // bLength
1231  USB_DT_DEVICE_CAPABILITY, // bDescriptorType
1232  USB_DC_PLATFORM, // bDevCapability
1233  0, // bReserved
1234  WEBUSB_UUID, // UUID[16]
1235  0x00, // bcdVersion
1236  0x01,
1237  WEBUSB_VENDOR_CODE, // bVencordCode
1238 #if WEBUSB_URL_SIZE_B > 0
1239  1, // iLandingPage
1240 #else // WEBUSB_URL_SIZE_B
1241  0, // iLandingPage, no url to retrieve
1242 #endif // WEBUSB_URL_SIZE_B
1243 
1244  // Microsoft OS 2.0 Platform Capability Descriptor
1245  0x1C, // Descriptor size (28 bytes)
1246  0x10, // Descriptor type (Device Capability)
1247  0x05, // Capability type (Platform)
1248  0x00, // Reserved
1249 
1250  // MS OS 2.0 Platform Capability ID (D8DD60DF-4589-4CC7-9CD2-659D9E648A9F)
1251  0xDF, 0x60, 0xDD, 0xD8,
1252  0x89, 0x45,
1253  0xC7, 0x4C,
1254  0x9C, 0xD2,
1255  0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F,
1256 
1257  0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000)
1258  MS_OS_20_DESCRIPTOR_LENGTH, 0x00,
1259  WINUSB_VENDOR_CODE, // Vendor-assigned bMS_VendorCode
1260  0x00 // Doesn’t support alternate enumeration
1261 };
1262 // clang-format on
1263 
1264 #endif // HAVE_WEBUSB
1265 
1266 static uint8_t *USBD_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
1267 {
1268  UNUSED(speed);
1269 #ifdef HAVE_WEBUSB
1270  *length = sizeof(C_usb_bos);
1271  return (uint8_t *) C_usb_bos;
1272 #else
1273  *length = 0;
1274  return NULL;
1275 #endif
1276 }
1277 
1282 // note: how core lib usb calls the hid class
1283 USBD_DescriptorsTypeDef const HID_Desc = {
1284  USBD_DeviceDescriptor,
1285  USBD_LangIDStrDescriptor,
1286  USBD_ManufacturerStrDescriptor,
1287  USBD_ProductStrDescriptor,
1288  USBD_SerialStrDescriptor,
1289  USBD_ConfigStrDescriptor,
1290  USBD_InterfaceStrDescriptor,
1291  USBD_BOSDescriptor,
1292 };
1293 
1294 #ifdef HAVE_IO_U2F
1295 static USBD_ClassTypeDef const USBD_U2F = {
1296  USBD_U2F_Init,
1297  USBD_HID_DeInit,
1298  USBD_HID_Setup,
1299  NULL, /*EP0_TxSent*/
1300  NULL,
1301  /*EP0_RxReady*/ /* STATUS STAGE IN */
1302  USBD_U2F_DataIn_impl, /*DataIn*/
1303  USBD_U2F_DataOut_impl, /*DataOut*/
1304  NULL, /*SOF */
1305  NULL,
1306  NULL,
1307  USBD_GetCfgDesc_impl,
1308  USBD_GetCfgDesc_impl,
1309  USBD_GetCfgDesc_impl,
1310  USBD_GetDeviceQualifierDesc_impl,
1311 };
1312 #endif // HAVE_IO_U2F
1313 
1314 static USBD_ClassTypeDef const USBD_HID = {
1315  USBD_HID_Init,
1316  USBD_HID_DeInit,
1317  USBD_HID_Setup,
1318  NULL, /*EP0_TxSent*/
1319  NULL,
1320  /*EP0_RxReady*/ /* STATUS STAGE IN */
1321  USBD_HID_DataIn_impl, /*DataIn*/
1322  USBD_HID_DataOut_impl, /*DataOut*/
1323  NULL, /*SOF */
1324  NULL,
1325  NULL,
1326  USBD_GetCfgDesc_impl,
1327  USBD_GetCfgDesc_impl,
1328  USBD_GetCfgDesc_impl,
1329  USBD_GetDeviceQualifierDesc_impl,
1330 };
1331 
1332 #ifdef HAVE_WEBUSB
1333 
1334 // clang-format off
1335 static const unsigned char C_winusb_string_descriptor[] = {
1336  // bLength
1337  0x12,
1338  // bDescriptorType
1339  USB_DESC_TYPE_STRING,
1340  // wData
1341  'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, '1', 0x00, '0', 0x00, '0', 0x00, WINUSB_VENDOR_CODE, 0x00, // MSFT100<VCODE>
1342 };
1343 // clang-format on
1344 
1345 // Microsoft OS 2.0 descriptor wIndex values
1346 #define MS_OS_20_DESCRIPTOR_INDEX 0x07
1347 
1348 // Microsoft OS 2.0 descriptor types
1349 #define MS_OS_20_SUBSET_HEADER_CONFIGURATION 0x01
1350 #define MS_OS_20_SUBSET_HEADER_FUNCTION 0x02
1351 #define MS_OS_20_FEATURE_COMPATIBLE_ID 0x03
1352 #define MS_OS_20_FEATURE_REG_PROPERTY 0x04
1353 
1354 // clang-format off
1355 static const unsigned char C_winusb_request_descriptor[] = {
1356  // Microsoft OS 2.0 descriptor set header (table 10)
1357  0x0A,
1358  0x00, // Descriptor size (10 bytes)
1359  0x00,
1360  0x00, // MS OS 2.0 descriptor set header
1361  0x00,
1362  0x00,
1363  0x03,
1364  0x06, // Windows version (8.1) (0x06030000)
1365  MS_OS_20_DESCRIPTOR_LENGTH,
1366  0x00, // Size, MS OS 2.0 descriptor set
1367 
1368  // Microsoft OS 2.0 configuration subset header
1369  0x08, 0x00, // Descriptor size (8 bytes)
1370  MS_OS_20_SUBSET_HEADER_CONFIGURATION, 0x00, // MS OS 2.0 configuration subset header
1371  0x00, // bConfigurationValue
1372  0x00, // Reserved
1373  0xA8, 0x00, // Size, MS OS 2.0 configuration subset
1374 
1375  // Microsoft OS 2.0 function subset header
1376  0x08, 0x00, // Descriptor size (8 bytes)
1377  MS_OS_20_SUBSET_HEADER_FUNCTION, 0x00, // MS OS 2.0 function subset header
1378  WEBUSB_INTF, // first Interface impacted by this function
1379 
1380  0x00, // Reserved
1381  0xA0, 0x00, // Size, MS OS 2.0 function subset
1382 
1383  // Microsoft OS 2.0 compatible ID descriptor (table 13)
1384  0x14, 0x00, // wLength
1385  MS_OS_20_FEATURE_COMPATIBLE_ID, 0x00, // MS_OS_20_FEATURE_COMPATIBLE_ID
1386  'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,
1387  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1388 
1389  0x84, 0x00, //wLength:
1390  MS_OS_20_FEATURE_REG_PROPERTY, 0x00, // wDescriptorType: MS_OS_20_FEATURE_REG_PROPERTY: 0x04 (Table 9)
1391  0x07, 0x00, //wPropertyDataType: REG_MULTI_SZ (Table 15)
1392  0x2a, 0x00, //wPropertyNameLength:
1393  //bPropertyName: “DeviceInterfaceGUID”
1394  'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00,
1395  'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00,
1396  0x00, 0x00,
1397  0x50, 0x00, // wPropertyDataLength
1398  //bPropertyData: “{CE809264-4B24-4E81-A8B2-57ED01D580E1}”.
1399  '{', 0x00, 'C', 0x00, 'E', 0x00, '8', 0x00, '0', 0x00, '9', 0x00, '2', 0x00, '6', 0x00, '4', 0x00, '-', 0x00,
1400  '4', 0x00, 'B', 0x00, '2', 0x00, '4', 0x00, '-', 0x00, '4', 0x00, 'E', 0x00, '8', 0x00, '1', 0x00, '-', 0x00,
1401  'A', 0x00, '8', 0x00, 'B', 0x00, '2', 0x00, '-', 0x00, '5', 0x00, '7', 0x00, 'E', 0x00, 'D', 0x00, '0', 0x00,
1402  '1', 0x00, 'D', 0x00, '5', 0x00, '8', 0x00, '0', 0x00, 'E', 0x00, '1', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00
1403 };
1404 
1405 #define WINUSB_GET_COMPATIBLE_ID_FEATURE 0x04
1406 static const unsigned char C_winusb_wcid[] = {
1407  // header
1408  0x28, 0x00, 0x00, 0x00, // dwLength
1409  0x00, 0x01, // bcdVersion
1410  0x04, 0x00, // wIndex
1411  0x01, // bNumSections
1412  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved
1413  // functions
1414  WEBUSB_INTF, // bInterfaceNumber
1415  0x01, // reserved
1416  'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatibleId
1417  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1418  0x00, // subCompatibleId
1419  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved
1420 };
1421 
1422 #define WINUSB_GET_EXTENDED_PROPERTIES_OS_FEATURE 0x05
1423 static const unsigned char C_winusb_guid[] = {
1424  // header
1425  0x92, 0x00, 0x00, 0x00, // dwLength
1426  0x00, 0x01, // bcdVersion
1427  0x05, 0x00, // wIndex
1428  0x01, 0x00, // wNumFeatures
1429  // features
1430  0x88, 0x00, 0x00, 0x00, // dwLength
1431  0x07, 0x00, 0x00, 0x00, // dwPropertyDataType
1432  0x2A, 0x00, // wNameLength
1433  'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00,
1434  'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00,
1435  'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00,
1436  'D', 0x00, 's', 0x00, 0x00, 0x00, // .name, unicode nul terminated
1437  0x50, 0x00, 0x00, 0x00, // dwPropertyDataLength
1438  // Same as BLE char: 13d63400-2C97-0004-0000-4c6564676572
1439  '{', 0x00, '1', 0x00, '3', 0x00, 'd', 0x00, '6', 0x00, '3', 0x00,
1440  '4', 0x00, '0', 0x00, '0', 0x00, '-', 0x00, '2', 0x00, 'C', 0x00,
1441  '9', 0x00, '7', 0x00, '-', 0x00, '0', 0x00, '0', 0x00, '0', 0x00,
1442  '4', 0x00, '-', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00,
1443  '-', 0x00, '4', 0x00, 'c', 0x00, '6', 0x00, '5', 0x00, '6', 0x00,
1444  '4', 0x00, '6', 0x00, '7', 0x00, '6', 0x00, '5', 0x00, '7', 0x00,
1445  '2', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 // propertyData, double unicode nul terminated
1446 };
1447 // clang-format on
1448 
1449 // upon unsupported request, check for webusb request
1450 void USBD_CtlError(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
1451 {
1452 #if WEBUSB_URL_SIZE_B > 0
1453  if ((req->bmRequest & 0x80) && req->bRequest == WEBUSB_VENDOR_CODE
1454  && req->wIndex == WEBUSB_REQ_GET_URL
1455  // HTTPS url
1456  && req->wValue == 1) {
1457  // return the URL descriptor
1458  USBD_CtlSendData(pdev,
1459  (unsigned char *) C_webusb_url_descriptor,
1460  MIN(req->wLength, sizeof(C_webusb_url_descriptor)));
1461  }
1462  else
1463 #endif // WEBUSB_URL_SIZE_B
1464  // SETUP (LE): 0x80 0x06 0x03 0x77 0x00 0x00 0xXX 0xXX
1465  if ((req->bmRequest & 0x80) && req->bRequest == USB_REQ_GET_DESCRIPTOR
1466  && (req->wValue >> 8) == USB_DESC_TYPE_STRING && (req->wValue & 0xFF) == 0xEE) {
1467  USBD_CtlSendData(pdev,
1468  (unsigned char *) C_winusb_string_descriptor,
1469  MIN(req->wLength, sizeof(C_winusb_string_descriptor)));
1470  }
1471  // SETUP (LE): 0x80 0x77 0x04 0x00 0x00 0x00 0xXX 0xXX
1472  else if ((req->bmRequest & 0x80) && req->bRequest == WINUSB_VENDOR_CODE
1473  && req->wIndex == WINUSB_GET_COMPATIBLE_ID_FEATURE) {
1474  USBD_CtlSendData(
1475  pdev, (unsigned char *) C_winusb_wcid, MIN(req->wLength, sizeof(C_winusb_wcid)));
1476  }
1477  // SETUP (LE): 0x80 0x77 0x05 0x00 0x00 0x00 0xXX 0xXX
1478  else if ((req->bmRequest & 0x80) && req->bRequest == WINUSB_VENDOR_CODE
1479  && req->wIndex == WINUSB_GET_EXTENDED_PROPERTIES_OS_FEATURE) {
1480  USBD_CtlSendData(
1481  pdev, (unsigned char *) C_winusb_guid, MIN(req->wLength, sizeof(C_winusb_guid)));
1482  }
1483  // Microsoft OS 2.0 Descriptors for Windows 8.1 and Windows 10
1484  else if ((req->bmRequest & 0x80) && req->bRequest == WINUSB_VENDOR_CODE
1485  && req->wIndex == MS_OS_20_DESCRIPTOR_INDEX) {
1486  USBD_CtlSendData(pdev,
1487  (unsigned char *) C_winusb_request_descriptor,
1488  MIN(req->wLength, sizeof(C_winusb_request_descriptor)));
1489  }
1490  else {
1491  USBD_CtlStall(pdev);
1492  }
1493 }
1494 
1495 static const USBD_ClassTypeDef USBD_WEBUSB = {
1496  USBD_WEBUSB_Init,
1497  USBD_WEBUSB_DeInit,
1498  USBD_WEBUSB_Setup,
1499  NULL, /*EP0_TxSent*/
1500  NULL, /*EP0_RxReady*/
1501  USBD_WEBUSB_DataIn,
1502  USBD_WEBUSB_DataOut,
1503  NULL, /*SOF */
1504  NULL, /*ISOIn*/
1505  NULL, /*ISOOut*/
1506  USBD_GetCfgDesc_impl,
1507  USBD_GetCfgDesc_impl,
1508  USBD_GetCfgDesc_impl,
1509  USBD_GetDeviceQualifierDesc_impl,
1510 };
1511 
1512 #endif // HAVE_WEBUSB
1513 
1514 #ifdef HAVE_USB_CLASS_CCID
1515 static const USBD_ClassTypeDef USBD_CCID = {
1516  USBD_CCID_Init,
1517  USBD_CCID_DeInit,
1518  USBD_CCID_Setup,
1519  NULL, /*EP0_TxSent*/
1520  NULL, /*EP0_RxReady*/
1521  USBD_CCID_DataIn,
1522  USBD_CCID_DataOut,
1523  NULL, /*SOF */
1524  NULL, /*ISOIn*/
1525  NULL, /*ISOOut*/
1526  USBD_GetCfgDesc_impl,
1527  USBD_GetCfgDesc_impl,
1528  USBD_GetCfgDesc_impl,
1529  USBD_GetDeviceQualifierDesc_impl,
1530 };
1531 
1532 uint8_t SC_AnswerToReset(uint8_t voltage, uint8_t *atr_buffer)
1533 {
1534  UNUSED(voltage);
1535  // return the atr length
1536  atr_buffer[0] = 0x3B;
1537  atr_buffer[1] = 0;
1538  return 2;
1539 }
1540 
1541 void SC_Poweroff(void)
1542 {
1543  // nothing to do ?
1544 }
1545 
1546 uint8_t SC_ExecuteEscape(uint8_t *escapePtr,
1547  uint32_t escapeLen,
1548  uint8_t *responseBuff,
1549  uint16_t *responseLen)
1550 {
1551  UNUSED(escapePtr);
1552  UNUSED(escapeLen);
1553  UNUSED(responseBuff);
1554  UNUSED(responseLen);
1555  // nothing to do ?
1556  return 0;
1557 }
1558 #endif // HAVE_USB_CLASS_CCID
1559 
1560 void USB_power(unsigned char enabled)
1561 {
1562  memset(&USBD_Device, 0, sizeof(USBD_Device));
1563 
1564  // init timeouts and other global fields
1565  memset(G_io_app.usb_ep_xfer_len, 0, sizeof(G_io_app.usb_ep_xfer_len));
1566  memset(G_io_app.usb_ep_timeouts, 0, sizeof(G_io_app.usb_ep_timeouts));
1567 
1568  if (enabled) {
1569  memset(&USBD_Device, 0, sizeof(USBD_Device));
1570  /* Init Device Library */
1571  USBD_Init(&USBD_Device, (USBD_DescriptorsTypeDef *) &HID_Desc, 0);
1572 
1573  /* Register the HID class */
1574  USBD_RegisterClassForInterface(HID_INTF, &USBD_Device, (USBD_ClassTypeDef *) &USBD_HID);
1575 #ifdef HAVE_IO_U2F
1576  USBD_RegisterClassForInterface(U2F_INTF, &USBD_Device, (USBD_ClassTypeDef *) &USBD_U2F);
1577  // initialize the U2F tunnel transport
1578  u2f_transport_init(&G_io_u2f, G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
1579 #endif // HAVE_IO_U2F
1580 #ifdef HAVE_USB_CLASS_CCID
1581  USBD_RegisterClassForInterface(CCID_INTF, &USBD_Device, (USBD_ClassTypeDef *) &USBD_CCID);
1582 #endif // HAVE_USB_CLASS_CCID
1583 
1584 #ifdef HAVE_WEBUSB
1585  USBD_RegisterClassForInterface(
1586  WEBUSB_INTF, &USBD_Device, (USBD_ClassTypeDef *) &USBD_WEBUSB);
1587 #endif // HAVE_WEBUSB
1588 
1589  /* Start Device Process */
1590  USBD_Start(&USBD_Device);
1591  }
1592  else {
1593  USBD_DeInit(&USBD_Device);
1594  }
1595 }
1596 
1597 #pragma GCC diagnostic pop
1610 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
const volatile uint8_t * USBD_GetPinPadOffset(void)
USBD_DescriptorsTypeDef const HID_Desc
Definition: usbd_impl.c:1283
void USB_power(unsigned char enabled)
Definition: usbd_impl.c:1560
#define USBD_LANGID_STRING
Definition: usbd_impl.c:118
uint8_t * USBD_HID_GetReportDescriptor_impl(uint16_t *len)
Definition: usbd_impl.c:918
#define USBD_CONFIGURATION_FS_STRING
Definition: usbd_impl.c:285
#define CFG_USB_CCID_LEN
Definition: usbd_impl.c:380
#define ARRAY_U2LE(l)
Definition: usbd_impl.c:375
uint8_t * USBD_HID_GetHidDescriptor_impl(uint16_t *len)
Definition: usbd_impl.c:896
#define CFG_IO_U2F_LEN
Definition: usbd_impl.c:379
#define CFG_HIDGEN_LEN
Definition: usbd_impl.c:378
#define CFG_WEBUSB_LEN
Definition: usbd_impl.c:381
#define CFG_HDR_LEN
Definition: usbd_impl.c:377
#define USBD_VID
Definition: usbd_impl.c:139
#define USBD_INTERFACE_FS_STRING
Definition: usbd_impl.c:284
uint8_t USBD_HID_DataOut_impl(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *buffer, apdu_buffer_t *apdu_buf)
Definition: usbd_impl.c:1057
uint8_t USBD_HID_DataIn_impl(USBD_HandleTypeDef *pdev, uint8_t epnum)
USBD_HID_DataOut handle data OUT Stage.
Definition: usbd_impl.c:1044
#define MIN(x, y)
Definition: nbgl_types.h:79
struct __attribute__((packed)) ndef_struct_s
Structure to store an NDEF message.
Definition: nfc_ndef.h:102
@ U2F_MEDIA_USB
Definition: u2f_service.h:49
void u2f_transport_sent(u2f_service_t *service, u2f_transport_media_t media)
void u2f_transport_init(u2f_service_t *service, uint8_t *message_buffer, uint16_t message_buffer_length)
void u2f_transport_received(u2f_service_t *service, uint8_t *buffer, uint16_t size, u2f_transport_media_t media)
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps)
Opens an endpoint of the Low Level Driver.
Definition: usbd_conf.c:130
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint16_t size)
Prepares an endpoint for reception.
Definition: usbd_conf.c:326
: Header for usbd_conf file.
unsigned short uint16_t
Definition: usbd_conf.h:54
unsigned char uint8_t
Definition: usbd_conf.h:53
#define HID_EPOUT_ADDR
Definition: usbd_hid_impl.h:30
#define HID_EPOUT_SIZE
Definition: usbd_hid_impl.h:31
#define HID_EPIN_SIZE
Definition: usbd_hid_impl.h:28
#define HID_EPIN_ADDR
Definition: usbd_hid_impl.h:27
#define HID_INTF
Definition: usbd_hid_impl.h:25