96d000767e3cc84bf913d65aba12f63441aaaf5c
[gnuk/gnuk.git] / src / usb_desc.c
1 /*
2  * usb_desc.c - USB Descriptor
3  */
4
5 #include <stdint.h>
6 #include <string.h>
7
8 #include "config.h"
9
10 #include "sys.h"
11 #include "usb_lld.h"
12 #include "usb_conf.h"
13 #include "usb-cdc.h"
14
15 \f
16 #ifdef HID_CARD_CHANGE_SUPPORT
17 /* HID report descriptor.  */
18 #define HID_REPORT_DESC_SIZE (sizeof (hid_report_desc))
19
20 static const uint8_t hid_report_desc[] = {
21   0x05, 0x01,       /* USAGE_PAGE (Generic Desktop) */
22   0x09, 0x07,       /* USAGE (Keypad) */
23   0xa1, 0x01,       /* COLLECTION (Application) */
24   0x05, 0x07,       /*   USAGE_PAGE (Key Codes) */
25   0x19, 0xe0,       /*   USAGE_MINIMUM (Keyboard LeftControl) */
26   0x29, 0xe7,       /*   USAGE_MAXIMUM (Keyboard Right GUI) */
27   0x15, 0x00,       /*   LOGICAL_MINIMUM (0) */
28   0x25, 0x01,       /*   LOGICAL_MAXIMUM (1) */
29   0x75, 0x01,       /*   REPORT_SIZE (1) */
30   0x95, 0x08,       /*   REPORT_COUNT (8) */
31   0x81, 0x02,       /*   INPUT (Data,Var,Abs); Modifier byte */
32
33   /*
34    * NumLock, CapsLock, ScrollLock, Compose, Kana, Power, Shift,
35    * Do Not Disturb
36    */
37   0x05, 0x08,       /*   USAGE_PAGE (LEDs) */
38   0x19, 0x01,       /*   USAGE_MINIMUM (1) */
39   0x29, 0x08,       /*   USAGE_MAXIMUM (8) */
40   0x95, 0x08,       /*   REPORT_COUNT (8) */
41   0x75, 0x01,       /*   REPORT_SIZE (1) */
42   0x91, 0x02,       /*   OUTPUT (Data,Var,Abs); LED report */
43
44   0x05, 0x07,       /*   USAGE_PAGE (Key Codes) */
45   0x19, 0x00,       /*   USAGE_MINIMUM (Reserved (no event indicated)) */
46   0x29, 0x65,       /*   USAGE_MAXIMUM (Keyboard Application) */
47   0x15, 0x00,       /*   LOGICAL_MINIMUM (0) */
48   0x25, 0x65,       /*   LOGICAL_MAXIMUM (101) */
49   0x95, 0x06,       /*   REPORT_COUNT (1) */
50   0x75, 0x08,       /*   REPORT_SIZE (8) */
51   0x81, 0x00,       /*   INPUT (Data,Ary,Abs); Key arrays (1 bytes) */
52   0xc0              /* END_COLLECTION */
53 };
54 #endif
55 \f
56 #define USB_ICC_INTERFACE_CLASS 0x0B
57 #define USB_ICC_INTERFACE_SUBCLASS 0x00
58 #define USB_ICC_INTERFACE_BULK_PROTOCOL 0x00
59 #define USB_ICC_DATA_SIZE 64
60
61 /* USB Standard Device Descriptor */
62 static const uint8_t gnukDeviceDescriptor[] = {
63   18,   /* bLength */
64   USB_DEVICE_DESCRIPTOR_TYPE,     /* bDescriptorType */
65   0x10, 0x01,   /* bcdUSB = 1.1 */
66   0x00,   /* bDeviceClass: 0 means deferred to interface */
67   0x00,   /* bDeviceSubClass */
68   0x00,   /* bDeviceProtocol */
69   0x40,   /* bMaxPacketSize0 */
70 #include "usb-vid-pid-ver.c.inc"
71   1, /* Index of string descriptor describing manufacturer */
72   2, /* Index of string descriptor describing product */
73   3, /* Index of string descriptor describing the device's serial number */
74   0x01    /* bNumConfigurations */
75 };
76
77 #define ICC_TOTAL_LENGTH (9+9+54+7+7+7)
78
79 #ifdef HID_CARD_CHANGE_SUPPORT
80 #define HID_TOTAL_LENGTH (9+9+7)
81 #else
82 #define HID_TOTAL_LENGTH   0
83 #endif
84
85 #ifdef ENABLE_VIRTUAL_COM_PORT
86 #define VCOM_TOTAL_LENGTH (9+5+5+4+5+7+9+7+7)
87 #else
88 #define VCOM_TOTAL_LENGTH   0
89 #endif
90
91 #ifdef PINPAD_DND_SUPPORT
92 #define MSC_TOTAL_LENGTH (9+7+7)
93 #else
94 #define MSC_TOTAL_LENGTH   0
95 #endif
96
97 #define W_TOTAL_LENGTH (ICC_TOTAL_LENGTH + HID_TOTAL_LENGTH     \
98                         + VCOM_TOTAL_LENGTH + MSC_TOTAL_LENGTH)
99
100
101 /* Configuation Descriptor */
102 static const uint8_t gnukConfigDescriptor[] = {
103   9,                       /* bLength: Configuation Descriptor size */
104   USB_CONFIGURATION_DESCRIPTOR_TYPE,      /* bDescriptorType: Configuration */
105   W_TOTAL_LENGTH, 0x00,   /* wTotalLength:no of returned bytes */
106   NUM_INTERFACES,   /* bNumInterfaces: */
107   0x01,   /* bConfigurationValue: Configuration value */
108   0x00,   /* iConfiguration: Index of string descriptor describing the configuration */
109   USB_INITIAL_FEATURE,  /* bmAttributes*/
110   50,     /* MaxPower 100 mA */
111
112   /* Interface Descriptor */
113   9,                             /* bLength: Interface Descriptor size */
114   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
115   ICC_INTERFACE,                 /* bInterfaceNumber: Index of this interface */
116   0,                             /* Alternate setting for this interface */
117   3,                             /* bNumEndpoints: Bulk-IN, Bulk-OUT, Intr-IN */
118   USB_ICC_INTERFACE_CLASS,
119   USB_ICC_INTERFACE_SUBCLASS,
120   USB_ICC_INTERFACE_BULK_PROTOCOL,
121   0,                             /* string index for interface */
122
123   /* ICC Descriptor */
124   54,                     /* bLength: */
125   0x21,                   /* bDescriptorType: USBDESCR_ICC */
126   0x10, 0x01,             /* bcdCCID: revision 1.1 (of CCID) */
127   0,                      /* bMaxSlotIndex: */
128   1,                      /* bVoltageSupport: FIXED VALUE */
129   0x02, 0, 0, 0,          /* dwProtocols: T=1 */
130   0xf3, 0x0d, 0, 0,       /* dwDefaultClock: 3571 (non-ICCD): 3580 (ICCD) */
131   0xf3, 0x0d, 0, 0,       /* dwMaximumClock: 3571 (non-ICCD): 3580 (ICCD) */
132   1,                      /* bNumClockSupported: FIXED VALUE */
133   0x80, 0x25, 0, 0,       /* dwDataRate: 9600: FIXED VALUE */
134   0x80, 0x25, 0, 0,       /* dwMaxDataRate: 9600: FIXED VALUE */
135   1,                      /* bNumDataRateSupported: FIXED VALUE */
136   0xfe, 0, 0, 0,          /* dwMaxIFSD: 254 */
137   0, 0, 0, 0,             /* dwSynchProtocols: FIXED VALUE */
138   0, 0, 0, 0,             /* dwMechanical: FIXED VALUE */
139   /*
140    * According to Specification for USB ICCD (revision 1.0),
141    * dwFeatures should be 0x00040840.
142    *
143    * It is different now for better interaction to GPG's in-stock
144    * ccid-driver.
145    */
146   0x42, 0x08, 0x02, 0x00, /* dwFeatures (not ICCD):
147                            *  Short APDU level             : 0x20000 *
148                            *  (what? means ICCD?)          : 0x00800 *
149                            *  Automatic IFSD               : 0x00400
150                            *  NAD value other than 0x00    : 0x00200
151                            *  Can set ICC in clock stop    : 0x00100
152                            *  Automatic PPS CUR            : 0x00080
153                            *  Automatic PPS PROP           : 0x00040 *
154                            *  Auto baud rate change        : 0x00020
155                            *  Auto clock change            : 0x00010
156                            *  Auto voltage selection       : 0x00008
157                            *  Auto activaction of ICC      : 0x00004
158                            *  Automatic conf. based on ATR : 0x00002  g
159                            */
160   0x0f, 0x01, 0, 0,       /* dwMaxCCIDMessageLength: 271 */
161   0xff,                   /* bClassGetResponse: */
162   0xff,                   /* bClassEnvelope: */
163   0, 0,                   /* wLCDLayout: FIXED VALUE */
164 #if defined(PINPAD_SUPPORT)
165 #if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DND_SUPPORT)
166   1,                      /* bPinSupport: with PIN pad (verify) */
167 #elif defined(PINPAD_DIAL_SUPPORT)
168   3,                      /* bPinSupport: with PIN pad (verify, modify) */
169 #endif
170 #else
171   0,                      /* bPinSupport: No PIN pad */
172 #endif
173   1,                      /* bMaxCCIDBusySlots: 1 */
174   /*Endpoint IN1 Descriptor*/
175   7,                           /* bLength: Endpoint Descriptor size */
176   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
177   0x81,                         /* bEndpointAddress: (IN1) */
178   0x02,                         /* bmAttributes: Bulk */
179   USB_ICC_DATA_SIZE, 0x00,      /* wMaxPacketSize: */
180   0x00,                         /* bInterval */
181   /*Endpoint OUT1 Descriptor*/
182   7,                           /* bLength: Endpoint Descriptor size */
183   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
184   0x01,                         /* bEndpointAddress: (OUT1) */
185   0x02,                         /* bmAttributes: Bulk */
186   USB_ICC_DATA_SIZE, 0x00,      /* wMaxPacketSize: */
187   0x00,                         /* bInterval */
188   /*Endpoint IN2 Descriptor*/
189   7,                           /* bLength: Endpoint Descriptor size */
190   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
191   0x82,                         /* bEndpointAddress: (IN2) */
192   0x03,                         /* bmAttributes: Interrupt */
193   4, 0x00,                      /* wMaxPacketSize: */
194   0xFF,                         /* bInterval (255ms) */
195
196 #ifdef HID_CARD_CHANGE_SUPPORT
197   /* Interface Descriptor */
198   9,                             /* bLength: Interface Descriptor size */
199   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
200   HID_INTERFACE,  /* bInterfaceNumber: Number of Interface */
201   0x00,           /* bAlternateSetting: Alternate setting */
202   0x01,           /* bNumEndpoints: One endpoint used */
203   0x03,           /* bInterfaceClass: HID */
204   0x00,           /* bInterfaceSubClass: no boot */
205   0x00,           /* bInterfaceProtocol: 0=none */
206   0x00,           /* iInterface: no string for this interface */
207
208   9,            /* bLength: HID Descriptor size */
209   0x21,         /* bDescriptorType: HID */
210   0x10, 0x01,   /* bcdHID: HID Class Spec release number */
211   0x00,         /* bCountryCode: Hardware target country */
212   0x01,         /* bNumDescriptors: Number of HID class descriptors to follow */
213   0x22,         /* bDescriptorType */
214   HID_REPORT_DESC_SIZE, 0, /* wItemLength: Total length of Report descriptor */
215
216   /*Endpoint IN7 Descriptor*/
217   7,                            /* bLength: Endpoint Descriptor size */
218   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
219   0x87,                         /* bEndpointAddress: (IN7) */
220   0x03,                         /* bmAttributes: Interrupt */
221   0x02, 0x00,                   /* wMaxPacketSize: 2 */
222   0x20,                         /* bInterval (32ms) */
223 #endif
224
225 #ifdef ENABLE_VIRTUAL_COM_PORT
226   /* Interface Descriptor */
227   9,                          /* bLength: Interface Descriptor size */
228   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
229   VCOM_INTERFACE_0,      /* bInterfaceNumber: Index of Interface */
230   0x00,           /* bAlternateSetting: Alternate setting */
231   0x01,           /* bNumEndpoints: One endpoints used */
232   0x02,           /* bInterfaceClass: Communication Interface Class */
233   0x02,           /* bInterfaceSubClass: Abstract Control Model */
234   0x01,           /* bInterfaceProtocol: Common AT commands */
235   0x00,           /* iInterface: */
236   /*Header Functional Descriptor*/
237   5,                        /* bLength: Endpoint Descriptor size */
238   0x24,                     /* bDescriptorType: CS_INTERFACE */
239   0x00,                     /* bDescriptorSubtype: Header Func Desc */
240   0x10, 0x01,               /* bcdCDC: spec release number */
241   /*Call Managment Functional Descriptor*/
242   5,        /* bFunctionLength */
243   0x24,     /* bDescriptorType: CS_INTERFACE */
244   0x01,     /* bDescriptorSubtype: Call Management Func Desc */
245   0x03,     /* bmCapabilities: D0+D1 */
246   VCOM_INTERFACE_1,         /* bDataInterface */
247   /*ACM Functional Descriptor*/
248   4,        /* bFunctionLength */
249   0x24,     /* bDescriptorType: CS_INTERFACE */
250   0x02,     /* bDescriptorSubtype: Abstract Control Management desc */
251   0x02,     /* bmCapabilities */
252   /*Union Functional Descriptor*/
253   5,             /* bFunctionLength */
254   0x24,          /* bDescriptorType: CS_INTERFACE */
255   0x06,          /* bDescriptorSubtype: Union func desc */
256   VCOM_INTERFACE_0,      /* bMasterInterface: Communication class interface */
257   VCOM_INTERFACE_1,      /* bSlaveInterface0: Data Class Interface */
258   /*Endpoint 4 Descriptor*/
259   7,                           /* bLength: Endpoint Descriptor size */
260   USB_ENDPOINT_DESCRIPTOR_TYPE,    /* bDescriptorType: Endpoint */
261   0x84,                            /* bEndpointAddress: (IN4) */
262   0x03,                            /* bmAttributes: Interrupt */
263   VIRTUAL_COM_PORT_INT_SIZE, 0x00, /* wMaxPacketSize: */
264   0xFF,                            /* bInterval: */
265
266   /*Data class interface descriptor*/
267   9,                           /* bLength: Endpoint Descriptor size */
268   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
269   VCOM_INTERFACE_1,      /* bInterfaceNumber: Index of Interface */
270   0x00,                    /* bAlternateSetting: Alternate setting */
271   0x02,                    /* bNumEndpoints: Two endpoints used */
272   0x0A,                    /* bInterfaceClass: CDC */
273   0x00,                    /* bInterfaceSubClass: */
274   0x00,                    /* bInterfaceProtocol: */
275   0x00,                    /* iInterface: */
276   /*Endpoint 5 Descriptor*/
277   7,                           /* bLength: Endpoint Descriptor size */
278   USB_ENDPOINT_DESCRIPTOR_TYPE,     /* bDescriptorType: Endpoint */
279   0x05,                             /* bEndpointAddress: (OUT5) */
280   0x02,                             /* bmAttributes: Bulk */
281   VIRTUAL_COM_PORT_DATA_SIZE, 0x00, /* wMaxPacketSize: */
282   0x00,                      /* bInterval: ignore for Bulk transfer */
283   /*Endpoint 3 Descriptor*/
284   7,                           /* bLength: Endpoint Descriptor size */
285   USB_ENDPOINT_DESCRIPTOR_TYPE,     /* bDescriptorType: Endpoint */
286   0x83,                             /* bEndpointAddress: (IN3) */
287   0x02,                             /* bmAttributes: Bulk */
288   VIRTUAL_COM_PORT_DATA_SIZE, 0x00, /* wMaxPacketSize: */
289   0x00,                             /* bInterval */
290 #endif
291 #ifdef PINPAD_DND_SUPPORT
292   /* Interface Descriptor.*/
293   9,                          /* bLength: Interface Descriptor size */
294   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
295   MSC_INTERFACE,                /* bInterfaceNumber. */
296   0x00,                         /* bAlternateSetting.               */
297   0x02,                         /* bNumEndpoints.                   */
298   0x08,                         /* bInterfaceClass (Mass Stprage).  */
299   0x06,                         /* bInterfaceSubClass (SCSI
300                                    transparent command set, MSCO
301                                    chapter 2).                      */
302   0x50,                         /* bInterfaceProtocol (Bulk-Only
303                                    Mass Storage, MSCO chapter 3).  */
304   0x00,                         /* iInterface.                      */
305   /* Endpoint Descriptor.*/
306   7,                            /* bLength: Endpoint Descriptor size */
307   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
308   0x86,                         /* bEndpointAddress: (IN6)   */
309   0x02,                         /* bmAttributes (Bulk).             */
310   0x40, 0x00,                   /* wMaxPacketSize.                  */
311   0x00,                         /* bInterval (ignored for bulk).    */
312   /* Endpoint Descriptor.*/
313   7,                            /* bLength: Endpoint Descriptor size */
314   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
315   0x06,                         /* bEndpointAddress: (OUT6)    */
316   0x02,                         /* bmAttributes (Bulk).             */
317   0x40, 0x00,                   /* wMaxPacketSize.                  */
318   0x00,                         /* bInterval (ignored for bulk).    */
319 #endif
320 };
321
322
323 /* USB String Descriptors */
324 static const uint8_t gnukStringLangID[] = {
325   4,                            /* bLength */
326   USB_STRING_DESCRIPTOR_TYPE,
327   0x09, 0x04                    /* LangID = 0x0409: US-English */
328 };
329
330 #define USB_STRINGS_FOR_GNUK 1
331 #include "usb-strings.c.inc"
332
333 struct desc
334 {
335   const uint8_t *desc;
336   uint16_t size;
337 };
338
339 static const struct desc String_Descriptors[NUM_STRING_DESC] = {
340   {gnukStringLangID, sizeof (gnukStringLangID)},
341   {gnukStringVendor, sizeof (gnukStringVendor)},
342   {gnukStringProduct, sizeof (gnukStringProduct)},
343   {gnukStringSerial, sizeof (gnukStringSerial)},
344   {gnuk_revision_detail, sizeof (gnuk_revision_detail)},
345   {gnuk_config_options, sizeof (gnuk_config_options)},
346   {sys_version, sizeof (sys_version)},
347 };
348
349 #define USB_DT_HID                      0x21
350 #define USB_DT_REPORT                   0x22
351
352 int
353 usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
354                        uint16_t index)
355 {
356   if (rcp == DEVICE_RECIPIENT)
357     {
358       if (desc_type == DEVICE_DESCRIPTOR)
359         {
360           usb_lld_set_data_to_send (gnukDeviceDescriptor,
361                                     sizeof (gnukDeviceDescriptor));
362           return USB_SUCCESS;
363         }
364       else if (desc_type == CONFIG_DESCRIPTOR)
365         {
366           usb_lld_set_data_to_send (gnukConfigDescriptor,
367                                     sizeof (gnukConfigDescriptor));
368           return USB_SUCCESS;
369         }
370       else if (desc_type == STRING_DESCRIPTOR)
371         {
372           if (desc_index < NUM_STRING_DESC)
373             {
374               usb_lld_set_data_to_send (String_Descriptors[desc_index].desc,
375                                         String_Descriptors[desc_index].size);
376               return USB_SUCCESS;
377             }
378         }
379     }
380   else if (rcp == INTERFACE_RECIPIENT)
381     {
382 #ifdef HID_CARD_CHANGE_SUPPORT
383       if (index == 1)
384         {
385           if (desc_type == USB_DT_HID)
386             {
387               usb_lld_set_data_to_send (gnukConfigDescriptor+ICC_TOTAL_LENGTH+9,
388                                         9);
389               return USB_SUCCESS;
390             }
391           else if (desc_type == USB_DT_REPORT)
392             {
393               usb_lld_set_data_to_send (hid_report_desc, HID_REPORT_DESC_SIZE);
394               return USB_SUCCESS;
395             }
396         }
397       else
398 #else
399       (void)index;
400 #endif
401       if (desc_type == STRING_DESCRIPTOR)
402         {
403           if (desc_index < NUM_STRING_DESC)
404             {
405               usb_lld_set_data_to_send (String_Descriptors[desc_index].desc,
406                                         String_Descriptors[desc_index].size);
407               return USB_SUCCESS;
408             }
409         }
410     }
411
412   return USB_UNSUPPORT;
413 }