Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
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
124static 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
147static 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
163static 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
176static 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
192static 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
213static 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
234static 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 */
255static 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
263static 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
273static 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
289static 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
314static 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
351static 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.
388static __ALIGN_BEGIN uint8_t const N_USBD_CfgDesc[] __ALIGN_END =
389#else
390static __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 */
731static __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 */
746static 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
781static 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
794static 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
807static 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
820static 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
833static 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
846static uint8_t *USBD_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
847{
848 UNUSED(speed);
849 *length = sizeof(USBD_CONFIGURATION_FS_STRING);
851}
852
859static uint8_t *USBD_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
860{
861 UNUSED(speed);
862 *length = sizeof(USBD_INTERFACE_FS_STRING);
864}
865
872static uint8_t *USBD_GetDeviceQualifierDesc_impl(uint16_t *length)
873{
874 *length = sizeof(USBD_DeviceQualifierDesc);
875 return (uint8_t *) USBD_DeviceQualifierDesc;
876}
877
885static 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
945const 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
992uint8_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
1008uint8_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
1017 break;
1018 }
1019 return USBD_OK;
1020}
1021
1022uint8_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
1044uint8_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
1057uint8_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
1102uint8_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
1118uint8_t USBD_WEBUSB_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
1119{
1120 UNUSED(pdev);
1121 UNUSED(cfgidx);
1122 return USBD_OK;
1123}
1124
1125uint8_t USBD_WEBUSB_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
1126{
1127 UNUSED(pdev);
1128 UNUSED(req);
1129 return USBD_OK;
1130}
1131
1132uint8_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
1144uint8_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
1199unsigned 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
1223unsigned 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
1266static 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
1283USBD_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
1295static 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
1314static 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
1335static 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
1355static 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
1406static 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
1423static 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
1450void 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
1495static 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
1515static 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
1532uint8_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
1541void SC_Poweroff(void)
1542{
1543 // nothing to do ?
1544}
1545
1546uint8_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
1560void 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
#define USBD_CONFIGURATION_FS_STRING
Definition usbd_impl.c:285
#define CFG_USB_CCID_LEN
Definition usbd_impl.c:380
uint8_t * USBD_HID_GetReportDescriptor_impl(uint16_t *len)
Definition usbd_impl.c:918
#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
__attribute__((section("._nbgl_fonts_"))) const
return the non-unicode font corresponding to the given font ID
Definition nbgl_fonts.c:67
#define MIN(x, y)
Definition nbgl_types.h:98
@ 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
#define HID_EPOUT_SIZE
#define HID_EPIN_SIZE
#define HID_EPIN_ADDR
#define HID_INTF