5b3eac8ba263ae3454464e4c750c89ce4b74aca2
[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 #define ICC_NUM_INTERFACES 1
79
80 #ifdef HID_CARD_CHANGE_SUPPORT
81 #define HID_TOTAL_LENGTH (9+9+7)
82 #define HID_NUM_INTERFACES 1
83 #else
84 #define HID_TOTAL_LENGTH   0
85 #define HID_NUM_INTERFACES 0
86 #endif
87
88 #ifdef ENABLE_VIRTUAL_COM_PORT
89 #define VCOM_TOTAL_LENGTH (9+5+5+4+5+7+9+7+7)
90 #define VCOM_NUM_INTERFACES 2
91 #else
92 #define VCOM_TOTAL_LENGTH   0
93 #define VCOM_NUM_INTERFACES 0
94 #endif
95
96 #ifdef PINPAD_DND_SUPPORT
97 #define MSC_TOTAL_LENGTH (9+7+7)
98 #define MSC_NUM_INTERFACES 1
99 #else
100 #define MSC_TOTAL_LENGTH   0
101 #define MSC_NUM_INTERFACES 0
102 #endif
103
104 #define W_TOTAL_LENGTH (ICC_TOTAL_LENGTH + HID_TOTAL_LENGTH     \
105                         + VCOM_TOTAL_LENGTH + MSC_TOTAL_LENGTH)
106 #define NUM_INTERFACES (ICC_NUM_INTERFACES + HID_NUM_INTERFACES \
107                         + VCOM_NUM_INTERFACES + MSC_NUM_INTERFACES)
108
109
110
111 /* Configuation Descriptor */
112 static const uint8_t gnukConfigDescriptor[] = {
113   9,                       /* bLength: Configuation Descriptor size */
114   USB_CONFIGURATION_DESCRIPTOR_TYPE,      /* bDescriptorType: Configuration */
115   W_TOTAL_LENGTH, 0x00,   /* wTotalLength:no of returned bytes */
116   NUM_INTERFACES,   /* bNumInterfaces: */
117   0x01,   /* bConfigurationValue: Configuration value */
118   0x00,   /* iConfiguration: Index of string descriptor describing the configuration */
119   USB_INITIAL_FEATURE,  /* bmAttributes*/
120   50,     /* MaxPower 100 mA */
121
122   /* Interface Descriptor */
123   9,                             /* bLength: Interface Descriptor size */
124   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
125   0,                             /* bInterfaceNumber: Index of this interface */
126   0,                             /* Alternate setting for this interface */
127   3,                             /* bNumEndpoints: Bulk-IN, Bulk-OUT, Intr-IN */
128   USB_ICC_INTERFACE_CLASS,
129   USB_ICC_INTERFACE_SUBCLASS,
130   USB_ICC_INTERFACE_BULK_PROTOCOL,
131   0,                             /* string index for interface */
132
133   /* ICC Descriptor */
134   54,                     /* bLength: */
135   0x21,                   /* bDescriptorType: USBDESCR_ICC */
136   0x10, 0x01,             /* bcdCCID: revision 1.1 (of CCID) */
137   0,                      /* bMaxSlotIndex: */
138   1,                      /* bVoltageSupport: FIXED VALUE */
139   0x02, 0, 0, 0,          /* dwProtocols: T=1 */
140   0xf3, 0x0d, 0, 0,       /* dwDefaultClock: 3571 (non-ICCD): 3580 (ICCD) */
141   0xf3, 0x0d, 0, 0,       /* dwMaximumClock: 3571 (non-ICCD): 3580 (ICCD) */
142   1,                      /* bNumClockSupported: FIXED VALUE */
143   0x80, 0x25, 0, 0,       /* dwDataRate: 9600: FIXED VALUE */
144   0x80, 0x25, 0, 0,       /* dwMaxDataRate: 9600: FIXED VALUE */
145   1,                      /* bNumDataRateSupported: FIXED VALUE */
146   0xfe, 0, 0, 0,          /* dwMaxIFSD: 254 */
147   0, 0, 0, 0,             /* dwSynchProtocols: FIXED VALUE */
148   0, 0, 0, 0,             /* dwMechanical: FIXED VALUE */
149   /*
150    * According to Specification for USB ICCD (revision 1.0),
151    * dwFeatures should be 0x00040840.
152    *
153    * It is different now for better interaction to GPG's in-stock
154    * ccid-driver.
155    */
156   0x42, 0x08, 0x02, 0x00, /* dwFeatures (not ICCD):
157                            *  Short APDU level             : 0x20000 *
158                            *  (what? means ICCD?)          : 0x00800 *
159                            *  Automatic IFSD               : 0x00400
160                            *  NAD value other than 0x00    : 0x00200
161                            *  Can set ICC in clock stop    : 0x00100
162                            *  Automatic PPS CUR            : 0x00080
163                            *  Automatic PPS PROP           : 0x00040 *
164                            *  Auto baud rate change        : 0x00020
165                            *  Auto clock change            : 0x00010
166                            *  Auto voltage selection       : 0x00008
167                            *  Auto activaction of ICC      : 0x00004
168                            *  Automatic conf. based on ATR : 0x00002  g
169                            */
170   0x0f, 0x01, 0, 0,       /* dwMaxCCIDMessageLength: 271 */
171   0xff,                   /* bClassGetResponse: */
172   0xff,                   /* bClassEnvelope: */
173   0, 0,                   /* wLCDLayout: FIXED VALUE */
174 #if defined(PINPAD_SUPPORT)
175 #if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DND_SUPPORT)
176   1,                      /* bPinSupport: with PIN pad (verify) */
177 #elif defined(PINPAD_DIAL_SUPPORT)
178   3,                      /* bPinSupport: with PIN pad (verify, modify) */
179 #endif
180 #else
181   0,                      /* bPinSupport: No PIN pad */
182 #endif
183   1,                      /* bMaxCCIDBusySlots: 1 */
184   /*Endpoint IN1 Descriptor*/
185   7,                           /* bLength: Endpoint Descriptor size */
186   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
187   0x81,                         /* bEndpointAddress: (IN1) */
188   0x02,                         /* bmAttributes: Bulk */
189   USB_ICC_DATA_SIZE, 0x00,      /* wMaxPacketSize: */
190   0x00,                         /* bInterval */
191   /*Endpoint OUT1 Descriptor*/
192   7,                           /* bLength: Endpoint Descriptor size */
193   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
194   0x01,                         /* bEndpointAddress: (OUT1) */
195   0x02,                         /* bmAttributes: Bulk */
196   USB_ICC_DATA_SIZE, 0x00,      /* wMaxPacketSize: */
197   0x00,                         /* bInterval */
198   /*Endpoint IN2 Descriptor*/
199   7,                           /* bLength: Endpoint Descriptor size */
200   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
201   0x82,                         /* bEndpointAddress: (IN2) */
202   0x03,                         /* bmAttributes: Interrupt */
203   4, 0x00,                      /* wMaxPacketSize: */
204   0xFF,                         /* bInterval (255ms) */
205
206 #ifdef HID_CARD_CHANGE_SUPPORT
207   /* Interface Descriptor */
208   9,                             /* bLength: Interface Descriptor size */
209   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
210   0x01,           /* bInterfaceNumber: Number of Interface */
211   0x00,           /* bAlternateSetting: Alternate setting */
212   0x01,           /* bNumEndpoints: One endpoint used */
213   0x03,           /* bInterfaceClass: HID */
214   0x00,           /* bInterfaceSubClass: no boot */
215   0x00,           /* bInterfaceProtocol: 0=none */
216   0x00,           /* iInterface: no string for this interface */
217
218   9,            /* bLength: HID Descriptor size */
219   0x21,         /* bDescriptorType: HID */
220   0x10, 0x01,   /* bcdHID: HID Class Spec release number */
221   0x00,         /* bCountryCode: Hardware target country */
222   0x01,         /* bNumDescriptors: Number of HID class descriptors to follow */
223   0x22,         /* bDescriptorType */
224   HID_REPORT_DESC_SIZE, 0, /* wItemLength: Total length of Report descriptor */
225
226   /*Endpoint IN7 Descriptor*/
227   7,                            /* bLength: Endpoint Descriptor size */
228   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
229   0x87,                         /* bEndpointAddress: (IN7) */
230   0x03,                         /* bmAttributes: Interrupt */
231   0x02, 0x00,                   /* wMaxPacketSize: 2 */
232   0x20,                         /* bInterval (32ms) */
233 #endif
234
235 #ifdef ENABLE_VIRTUAL_COM_PORT
236   /* Interface Descriptor */
237   9,                          /* bLength: Interface Descriptor size */
238   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
239   0x02,           /* bInterfaceNumber: Number of Interface */
240   0x00,           /* bAlternateSetting: Alternate setting */
241   0x01,           /* bNumEndpoints: One endpoints used */
242   0x02,           /* bInterfaceClass: Communication Interface Class */
243   0x02,           /* bInterfaceSubClass: Abstract Control Model */
244   0x01,           /* bInterfaceProtocol: Common AT commands */
245   0x00,           /* iInterface: */
246   /*Header Functional Descriptor*/
247   5,                        /* bLength: Endpoint Descriptor size */
248   0x24,                     /* bDescriptorType: CS_INTERFACE */
249   0x00,                     /* bDescriptorSubtype: Header Func Desc */
250   0x10,                     /* bcdCDC: spec release number */
251   0x01,
252   /*Call Managment Functional Descriptor*/
253   5,        /* bFunctionLength */
254   0x24,     /* bDescriptorType: CS_INTERFACE */
255   0x01,     /* bDescriptorSubtype: Call Management Func Desc */
256   0x03,     /* bmCapabilities: D0+D1 */
257   0x02,     /* bDataInterface: 2 */
258   /*ACM Functional Descriptor*/
259   4,        /* bFunctionLength */
260   0x24,     /* bDescriptorType: CS_INTERFACE */
261   0x02,     /* bDescriptorSubtype: Abstract Control Management desc */
262   0x02,     /* bmCapabilities */
263   /*Union Functional Descriptor*/
264   5,             /* bFunctionLength */
265   0x24,          /* bDescriptorType: CS_INTERFACE */
266   0x06,          /* bDescriptorSubtype: Union func desc */
267   0x01,          /* bMasterInterface: Communication class interface */
268   0x02,          /* bSlaveInterface0: Data Class Interface */
269   /*Endpoint 4 Descriptor*/
270   7,                           /* bLength: Endpoint Descriptor size */
271   USB_ENDPOINT_DESCRIPTOR_TYPE,    /* bDescriptorType: Endpoint */
272   0x84,                            /* bEndpointAddress: (IN4) */
273   0x03,                            /* bmAttributes: Interrupt */
274   VIRTUAL_COM_PORT_INT_SIZE, 0x00, /* wMaxPacketSize: */
275   0xFF,                            /* bInterval: */
276
277   /*Data class interface descriptor*/
278   9,                           /* bLength: Endpoint Descriptor size */
279   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
280   0x03,                    /* bInterfaceNumber: Number of Interface */
281   0x00,                    /* bAlternateSetting: Alternate setting */
282   0x02,                    /* bNumEndpoints: Two endpoints used */
283   0x0A,                    /* bInterfaceClass: CDC */
284   0x00,                    /* bInterfaceSubClass: */
285   0x00,                    /* bInterfaceProtocol: */
286   0x00,                    /* iInterface: */
287   /*Endpoint 5 Descriptor*/
288   7,                           /* bLength: Endpoint Descriptor size */
289   USB_ENDPOINT_DESCRIPTOR_TYPE,     /* bDescriptorType: Endpoint */
290   0x05,                             /* bEndpointAddress: (OUT5) */
291   0x02,                             /* bmAttributes: Bulk */
292   VIRTUAL_COM_PORT_DATA_SIZE, 0x00, /* wMaxPacketSize: */
293   0x00,                      /* bInterval: ignore for Bulk transfer */
294   /*Endpoint 3 Descriptor*/
295   7,                           /* bLength: Endpoint Descriptor size */
296   USB_ENDPOINT_DESCRIPTOR_TYPE,     /* bDescriptorType: Endpoint */
297   0x83,                             /* bEndpointAddress: (IN3) */
298   0x02,                             /* bmAttributes: Bulk */
299   VIRTUAL_COM_PORT_DATA_SIZE, 0x00, /* wMaxPacketSize: */
300   0x00,                             /* bInterval */
301 #endif
302 #ifdef PINPAD_DND_SUPPORT
303   /* Interface Descriptor.*/
304   9,                          /* bLength: Interface Descriptor size */
305   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
306 #ifdef ENABLE_VIRTUAL_COM_PORT
307   0x04,                         /* bInterfaceNumber.                */
308 #else
309   0x02,                         /* bInterfaceNumber.                */
310 #endif
311   0x00,                         /* bAlternateSetting.               */
312   0x02,                         /* bNumEndpoints.                   */
313   0x08,                         /* bInterfaceClass (Mass Stprage).  */
314   0x06,                         /* bInterfaceSubClass (SCSI
315                                    transparent command set, MSCO
316                                    chapter 2).                      */
317   0x50,                         /* bInterfaceProtocol (Bulk-Only
318                                    Mass Storage, MSCO chapter 3).  */
319   0x00,                         /* iInterface.                      */
320   /* Endpoint Descriptor.*/
321   7,                            /* bLength: Endpoint Descriptor size */
322   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
323   0x86,                         /* bEndpointAddress: (IN6)   */
324   0x02,                         /* bmAttributes (Bulk).             */
325   0x40, 0x00,                   /* wMaxPacketSize.                  */
326   0x00,                         /* bInterval (ignored for bulk).    */
327   /* Endpoint Descriptor.*/
328   7,                            /* bLength: Endpoint Descriptor size */
329   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
330   0x06,                         /* bEndpointAddress: (OUT6)    */
331   0x02,                         /* bmAttributes (Bulk).             */
332   0x40, 0x00,                   /* wMaxPacketSize.                  */
333   0x00,                         /* bInterval (ignored for bulk).    */
334 #endif
335 };
336
337
338 /* USB String Descriptors */
339 static const uint8_t gnukStringLangID[] = {
340   4,                            /* bLength */
341   USB_STRING_DESCRIPTOR_TYPE,
342   0x09, 0x04                    /* LangID = 0x0409: US-English */
343 };
344
345 #define USB_STRINGS_FOR_GNUK 1
346 #include "usb-strings.c.inc"
347
348 struct desc
349 {
350   const uint8_t *desc;
351   uint16_t size;
352 };
353
354 static const struct desc String_Descriptors[NUM_STRING_DESC] = {
355   {gnukStringLangID, sizeof (gnukStringLangID)},
356   {gnukStringVendor, sizeof (gnukStringVendor)},
357   {gnukStringProduct, sizeof (gnukStringProduct)},
358   {gnukStringSerial, sizeof (gnukStringSerial)},
359   {gnuk_revision_detail, sizeof (gnuk_revision_detail)},
360   {gnuk_config_options, sizeof (gnuk_config_options)},
361   {sys_version, sizeof (sys_version)},
362 };
363
364 #define USB_DT_HID                      0x21
365 #define USB_DT_REPORT                   0x22
366
367 int
368 usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
369                        uint16_t index)
370 {
371   if (rcp == DEVICE_RECIPIENT)
372     {
373       if (desc_type == DEVICE_DESCRIPTOR)
374         {
375           usb_lld_set_data_to_send (gnukDeviceDescriptor,
376                                     sizeof (gnukDeviceDescriptor));
377           return USB_SUCCESS;
378         }
379       else if (desc_type == CONFIG_DESCRIPTOR)
380         {
381           usb_lld_set_data_to_send (gnukConfigDescriptor,
382                                     sizeof (gnukConfigDescriptor));
383           return USB_SUCCESS;
384         }
385       else if (desc_type == STRING_DESCRIPTOR)
386         {
387           if (desc_index < NUM_STRING_DESC)
388             {
389               usb_lld_set_data_to_send (String_Descriptors[desc_index].desc,
390                                         String_Descriptors[desc_index].size);
391               return USB_SUCCESS;
392             }
393         }
394     }
395   else if (rcp == INTERFACE_RECIPIENT)
396     {
397 #ifdef HID_CARD_CHANGE_SUPPORT
398       if (index == 1)
399         {
400           if (desc_type == USB_DT_HID)
401             {
402               usb_lld_set_data_to_send (gnukConfigDescriptor+ICC_TOTAL_LENGTH+9,
403                                         9);
404               return USB_SUCCESS;
405             }
406           else if (desc_type == USB_DT_REPORT)
407             {
408               usb_lld_set_data_to_send (hid_report_desc, HID_REPORT_DESC_SIZE);
409               return USB_SUCCESS;
410             }
411         }
412       else
413 #else
414       (void)index;
415 #endif
416       if (desc_type == STRING_DESCRIPTOR)
417         {
418           if (desc_index < NUM_STRING_DESC)
419             {
420               usb_lld_set_data_to_send (String_Descriptors[desc_index].desc,
421                                         String_Descriptors[desc_index].size);
422               return USB_SUCCESS;
423             }
424         }
425     }
426
427   return USB_UNSUPPORT;
428 }