More USB driver change
[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 device_desc[] = {
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 config_desc[] = {
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: 5V-only */
129   0x02, 0, 0, 0,          /* dwProtocols: T=1 */
130   0xa0, 0x0f, 0, 0,       /* dwDefaultClock: 4000 */
131   0xa0, 0x0f, 0, 0,       /* dwMaximumClock: 4000 */
132   0,                      /* bNumClockSupported: 0x00 */
133   0x80, 0x25, 0, 0,       /* dwDataRate: 9600 */
134   0x80, 0x25, 0, 0,       /* dwMaxDataRate: 9600 */
135   0,                      /* bNumDataRateSupported: 0x00 */
136   0xfe, 0, 0, 0,          /* dwMaxIFSD: 254 */
137   0, 0, 0, 0,             /* dwSynchProtocols: 0 */
138   0, 0, 0, 0,             /* dwMechanical: 0 */
139   0x7a, 0x04, 0x02, 0x00, /* dwFeatures:
140                            *  Short and extended APDU level: 0x40000 ----
141                            *  Short APDU level             : 0x20000  *
142                            *  (ICCD?)                      : 0x00800 ----
143                            *  Automatic IFSD               : 0x00400   *
144                            *  NAD value other than 0x00    : 0x00200
145                            *  Can set ICC in clock stop    : 0x00100
146                            *  Automatic PPS CUR            : 0x00080
147                            *  Automatic PPS PROP           : 0x00040 *
148                            *  Auto baud rate change        : 0x00020   *
149                            *  Auto clock change            : 0x00010   *
150                            *  Auto voltage selection       : 0x00008   *
151                            *  Auto activaction of ICC      : 0x00004
152                            *  Automatic conf. based on ATR : 0x00002  *
153                            */
154   0x0f, 0x01, 0, 0,       /* dwMaxCCIDMessageLength: 271 */
155   0xff,                   /* bClassGetResponse: 0xff */
156   0x00,                   /* bClassEnvelope: 0 */
157   0, 0,                   /* wLCDLayout: 0 */
158 #if defined(PINPAD_SUPPORT)
159 #if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DND_SUPPORT)
160   1,                      /* bPinSupport: with PIN pad (verify) */
161 #elif defined(PINPAD_DIAL_SUPPORT)
162   3,                      /* bPinSupport: with PIN pad (verify, modify) */
163 #endif
164 #else
165   0,                      /* bPinSupport: No PIN pad */
166 #endif
167   1,                      /* bMaxCCIDBusySlots: 1 */
168   /*Endpoint IN1 Descriptor*/
169   7,                           /* bLength: Endpoint Descriptor size */
170   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
171   0x81,                         /* bEndpointAddress: (IN1) */
172   0x02,                         /* bmAttributes: Bulk */
173   USB_ICC_DATA_SIZE, 0x00,      /* wMaxPacketSize: */
174   0x00,                         /* bInterval */
175   /*Endpoint OUT1 Descriptor*/
176   7,                           /* bLength: Endpoint Descriptor size */
177   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
178   0x01,                         /* bEndpointAddress: (OUT1) */
179   0x02,                         /* bmAttributes: Bulk */
180   USB_ICC_DATA_SIZE, 0x00,      /* wMaxPacketSize: */
181   0x00,                         /* bInterval */
182   /*Endpoint IN2 Descriptor*/
183   7,                           /* bLength: Endpoint Descriptor size */
184   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
185   0x82,                         /* bEndpointAddress: (IN2) */
186   0x03,                         /* bmAttributes: Interrupt */
187   0x04, 0x00,                   /* wMaxPacketSize: 4 */
188   0xFF,                         /* bInterval (255ms) */
189
190 #ifdef HID_CARD_CHANGE_SUPPORT
191   /* Interface Descriptor */
192   9,                             /* bLength: Interface Descriptor size */
193   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
194   HID_INTERFACE,  /* bInterfaceNumber: Number of Interface */
195   0x00,           /* bAlternateSetting: Alternate setting */
196   0x01,           /* bNumEndpoints: One endpoint used */
197   0x03,           /* bInterfaceClass: HID */
198   0x00,           /* bInterfaceSubClass: no boot */
199   0x00,           /* bInterfaceProtocol: 0=none */
200   0x00,           /* iInterface: no string for this interface */
201
202   9,            /* bLength: HID Descriptor size */
203   0x21,         /* bDescriptorType: HID */
204   0x10, 0x01,   /* bcdHID: HID Class Spec release number */
205   0x00,         /* bCountryCode: Hardware target country */
206   0x01,         /* bNumDescriptors: Number of HID class descriptors to follow */
207   0x22,         /* bDescriptorType */
208   HID_REPORT_DESC_SIZE, 0, /* wItemLength: Total length of Report descriptor */
209
210   /*Endpoint IN7 Descriptor*/
211   7,                            /* bLength: Endpoint Descriptor size */
212   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
213   0x87,                         /* bEndpointAddress: (IN7) */
214   0x03,                         /* bmAttributes: Interrupt */
215   0x02, 0x00,                   /* wMaxPacketSize: 2 */
216   0x20,                         /* bInterval (32ms) */
217 #endif
218
219 #ifdef ENABLE_VIRTUAL_COM_PORT
220   /* Interface Descriptor */
221   9,                          /* bLength: Interface Descriptor size */
222   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
223   VCOM_INTERFACE_0,      /* bInterfaceNumber: Index of Interface */
224   0x00,           /* bAlternateSetting: Alternate setting */
225   0x01,           /* bNumEndpoints: One endpoints used */
226   0x02,           /* bInterfaceClass: Communication Interface Class */
227   0x02,           /* bInterfaceSubClass: Abstract Control Model */
228   0x01,           /* bInterfaceProtocol: Common AT commands */
229   0x00,           /* iInterface: */
230   /*Header Functional Descriptor*/
231   5,                        /* bLength: Endpoint Descriptor size */
232   0x24,                     /* bDescriptorType: CS_INTERFACE */
233   0x00,                     /* bDescriptorSubtype: Header Func Desc */
234   0x10, 0x01,               /* bcdCDC: spec release number */
235   /*Call Managment Functional Descriptor*/
236   5,        /* bFunctionLength */
237   0x24,     /* bDescriptorType: CS_INTERFACE */
238   0x01,     /* bDescriptorSubtype: Call Management Func Desc */
239   0x03,     /* bmCapabilities: D0+D1 */
240   VCOM_INTERFACE_1,         /* bDataInterface */
241   /*ACM Functional Descriptor*/
242   4,        /* bFunctionLength */
243   0x24,     /* bDescriptorType: CS_INTERFACE */
244   0x02,     /* bDescriptorSubtype: Abstract Control Management desc */
245   0x02,     /* bmCapabilities */
246   /*Union Functional Descriptor*/
247   5,             /* bFunctionLength */
248   0x24,          /* bDescriptorType: CS_INTERFACE */
249   0x06,          /* bDescriptorSubtype: Union func desc */
250   VCOM_INTERFACE_0,      /* bMasterInterface: Communication class interface */
251   VCOM_INTERFACE_1,      /* bSlaveInterface0: Data Class Interface */
252   /*Endpoint 4 Descriptor*/
253   7,                           /* bLength: Endpoint Descriptor size */
254   USB_ENDPOINT_DESCRIPTOR_TYPE,    /* bDescriptorType: Endpoint */
255   0x84,                            /* bEndpointAddress: (IN4) */
256   0x03,                            /* bmAttributes: Interrupt */
257   VIRTUAL_COM_PORT_INT_SIZE, 0x00, /* wMaxPacketSize: */
258   0xFF,                            /* bInterval: */
259
260   /*Data class interface descriptor*/
261   9,                           /* bLength: Endpoint Descriptor size */
262   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
263   VCOM_INTERFACE_1,      /* bInterfaceNumber: Index of Interface */
264   0x00,                    /* bAlternateSetting: Alternate setting */
265   0x02,                    /* bNumEndpoints: Two endpoints used */
266   0x0A,                    /* bInterfaceClass: CDC */
267   0x00,                    /* bInterfaceSubClass: */
268   0x00,                    /* bInterfaceProtocol: */
269   0x00,                    /* iInterface: */
270   /*Endpoint 5 Descriptor*/
271   7,                           /* bLength: Endpoint Descriptor size */
272   USB_ENDPOINT_DESCRIPTOR_TYPE,     /* bDescriptorType: Endpoint */
273   0x05,                             /* bEndpointAddress: (OUT5) */
274   0x02,                             /* bmAttributes: Bulk */
275   VIRTUAL_COM_PORT_DATA_SIZE, 0x00, /* wMaxPacketSize: */
276   0x00,                      /* bInterval: ignore for Bulk transfer */
277   /*Endpoint 3 Descriptor*/
278   7,                           /* bLength: Endpoint Descriptor size */
279   USB_ENDPOINT_DESCRIPTOR_TYPE,     /* bDescriptorType: Endpoint */
280   0x83,                             /* bEndpointAddress: (IN3) */
281   0x02,                             /* bmAttributes: Bulk */
282   VIRTUAL_COM_PORT_DATA_SIZE, 0x00, /* wMaxPacketSize: */
283   0x00,                             /* bInterval */
284 #endif
285 #ifdef PINPAD_DND_SUPPORT
286   /* Interface Descriptor.*/
287   9,                          /* bLength: Interface Descriptor size */
288   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
289   MSC_INTERFACE,                /* bInterfaceNumber. */
290   0x00,                         /* bAlternateSetting.               */
291   0x02,                         /* bNumEndpoints.                   */
292   0x08,                         /* bInterfaceClass (Mass Stprage).  */
293   0x06,                         /* bInterfaceSubClass (SCSI
294                                    transparent command set, MSCO
295                                    chapter 2).                      */
296   0x50,                         /* bInterfaceProtocol (Bulk-Only
297                                    Mass Storage, MSCO chapter 3).  */
298   0x00,                         /* iInterface.                      */
299   /* Endpoint Descriptor.*/
300   7,                            /* bLength: Endpoint Descriptor size */
301   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
302   0x86,                         /* bEndpointAddress: (IN6)   */
303   0x02,                         /* bmAttributes (Bulk).             */
304   0x40, 0x00,                   /* wMaxPacketSize.                  */
305   0x00,                         /* bInterval (ignored for bulk).    */
306   /* Endpoint Descriptor.*/
307   7,                            /* bLength: Endpoint Descriptor size */
308   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
309   0x06,                         /* bEndpointAddress: (OUT6)    */
310   0x02,                         /* bmAttributes (Bulk).             */
311   0x40, 0x00,                   /* wMaxPacketSize.                  */
312   0x00,                         /* bInterval (ignored for bulk).    */
313 #endif
314 };
315
316
317 /* USB String Descriptors */
318 static const uint8_t gnuk_string_lang_id[] = {
319   4,                            /* bLength */
320   USB_STRING_DESCRIPTOR_TYPE,
321   0x09, 0x04                    /* LangID = 0x0409: US-English */
322 };
323
324 #define USB_STRINGS_FOR_GNUK 1
325 #include "usb-strings.c.inc"
326
327 struct desc
328 {
329   const uint8_t *desc;
330   uint16_t size;
331 };
332
333 static const struct desc string_descriptors[] = {
334   {gnuk_string_lang_id, sizeof (gnuk_string_lang_id)},
335   {gnuk_string_vendor, sizeof (gnuk_string_vendor)},
336   {gnuk_string_product, sizeof (gnuk_string_product)},
337   {gnuk_string_serial, sizeof (gnuk_string_serial)},
338   {gnuk_revision_detail, sizeof (gnuk_revision_detail)},
339   {gnuk_config_options, sizeof (gnuk_config_options)},
340   {sys_version, sizeof (sys_version)},
341 };
342 #define NUM_STRING_DESC (sizeof (string_descriptors) / sizeof (struct desc))
343
344 #define USB_DT_HID                      0x21
345 #define USB_DT_REPORT                   0x22
346
347 int
348 usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
349                        struct control_info *detail)
350 {
351   if (rcp == DEVICE_RECIPIENT)
352     {
353       if (desc_type == DEVICE_DESCRIPTOR)
354         return usb_lld_reply_request (device_desc, sizeof (device_desc), detail);
355       else if (desc_type == CONFIG_DESCRIPTOR)
356         return usb_lld_reply_request (config_desc, sizeof (config_desc), detail);
357       else if (desc_type == STRING_DESCRIPTOR)
358         {
359           if (desc_index < NUM_STRING_DESC)
360             return usb_lld_reply_request (string_descriptors[desc_index].desc,
361                                           string_descriptors[desc_index].size,
362                                           detail);
363           else if (desc_index == NUM_STRING_DESC)
364             {
365               uint8_t usbbuf[64];
366               int i;
367               size_t len;
368
369               for (i = 0; i < (int)sizeof (usbbuf)/2 - 2; i++)
370                 {
371                   if (sys_board_name[i] == 0)
372                     break;
373
374                   usbbuf[i*2+2] = sys_board_name[i];
375                   usbbuf[i*2+3] = 0;
376                 }
377               usbbuf[0] = len = i*2 + 2;
378               usbbuf[1] = USB_STRING_DESCRIPTOR_TYPE;
379               return usb_lld_reply_request (usbbuf, len, detail);
380             }
381         }
382     }
383 #ifdef HID_CARD_CHANGE_SUPPORT
384   else if (rcp == INTERFACE_RECIPIENT)
385     {
386       if (detail->index == 1)
387         {
388           if (desc_type == USB_DT_HID)
389             return usb_lld_reply_request (config_desc+ICC_TOTAL_LENGTH+9, 9,
390                                           detail);
391           else if (desc_type == USB_DT_REPORT)
392             return usb_lld_reply_request (hid_report_desc, HID_REPORT_DESC_SIZE,
393                                           detail);
394         }
395     }
396 #endif
397
398   return USB_UNSUPPORT;
399 }