OpenULINK firmware: Use C99 designated struct initializers
[fw/openocd] / src / jtag / drivers / OpenULINK / src / usb.c
1 /***************************************************************************
2  *   Copyright (C) 2011-2013 by Martin Schmoelzer                          *
3  *   <martin.schmoelzer@student.tuwien.ac.at>                              *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
19  ***************************************************************************/
20
21 /**
22  * @file
23  * Defines USB descriptors, interrupt routines and helper functions.
24  * To minimize code size, we make the following assumptions:
25  *  - The OpenULINK has exactly one configuration
26  *  - and exactly one alternate setting
27  *
28  * Therefore, we do not have to support the Set Configuration USB request.
29  */
30
31 #include "usb.h"
32 #include "delay.h"
33 #include "io.h"
34
35 /* Also update external declarations in "include/usb.h" if making changes to
36  * these variables! */
37 volatile bool EP2_out;
38 volatile bool EP2_in;
39
40 volatile __xdata __at 0x7FE8 struct setup_data setup_data;
41
42 /* Define number of endpoints (except Control Endpoint 0) in a central place.
43  * Be sure to include the neccessary endpoint descriptors! */
44 #define NUM_ENDPOINTS 2
45
46 __code struct usb_device_descriptor device_descriptor = {
47         .bLength =              sizeof(struct usb_device_descriptor),
48         .bDescriptorType =      DESCRIPTOR_TYPE_DEVICE,
49         .bcdUSB =               0x0110, /* BCD: 01.00 (Version 1.0 USB spec) */
50         .bDeviceClass =         0xFF,   /* 0xFF = vendor-specific */
51         .bDeviceSubClass =      0xFF,
52         .bDeviceProtocol =      0xFF,
53         .bMaxPacketSize0 =      64,
54         .idVendor =             0xC251,
55         .idProduct =            0x2710,
56         .bcdDevice =            0x0100,
57         .iManufacturer =        1,
58         .iProduct =             2,
59         .iSerialNumber =        3,
60         .bNumConfigurations =   1
61 };
62
63 /* WARNING: ALL config, interface and endpoint descriptors MUST be adjacent! */
64
65 __code struct usb_config_descriptor config_descriptor = {
66         .bLength =              sizeof(struct usb_config_descriptor),
67         .bDescriptorType =      DESCRIPTOR_TYPE_CONFIGURATION,
68         .wTotalLength =         sizeof(struct usb_config_descriptor) +
69                 sizeof(struct usb_interface_descriptor) +
70                 (NUM_ENDPOINTS * sizeof(struct usb_endpoint_descriptor)),
71         .bNumInterfaces =       1,
72         .bConfigurationValue =  1,
73         .iConfiguration =       4,      /* String describing this configuration */
74         .bmAttributes =         0x80,   /* Only MSB set according to USB spec */
75         .MaxPower =             50      /* 100 mA */
76 };
77
78 __code struct usb_interface_descriptor interface_descriptor00 = {
79         .bLength = sizeof(struct usb_interface_descriptor),
80         .bDescriptorType =      DESCRIPTOR_TYPE_INTERFACE,
81         .bInterfaceNumber =     0,
82         .bAlternateSetting =    0,
83         .bNumEndpoints =        NUM_ENDPOINTS,
84         .bInterfaceClass =      0xFF,
85         .bInterfaceSubclass =   0xFF,
86         .bInterfaceProtocol =   0xFF,
87         .iInterface =           0
88 };
89
90 __code struct usb_endpoint_descriptor Bulk_EP2_IN_Endpoint_Descriptor = {
91         .bLength =              sizeof(struct usb_endpoint_descriptor),
92         .bDescriptorType =      0x05,
93         .bEndpointAddress =     (2 | USB_DIR_IN),
94         .bmAttributes =         0x02,
95         .wMaxPacketSize =       64,
96         .bInterval =            0
97 };
98
99 __code struct usb_endpoint_descriptor Bulk_EP2_OUT_Endpoint_Descriptor = {
100         .bLength =              sizeof(struct usb_endpoint_descriptor),
101         .bDescriptorType =      0x05,
102         .bEndpointAddress =     (2 | USB_DIR_OUT),
103         .bmAttributes =         0x02,
104         .wMaxPacketSize =       64,
105         .bInterval =            0
106 };
107
108 __code struct usb_language_descriptor language_descriptor = {
109         .bLength =              4,
110         .bDescriptorType =      DESCRIPTOR_TYPE_STRING,
111         .wLANGID =              {0x0409 /* US English */}
112 };
113
114 __code struct usb_string_descriptor strManufacturer =
115         STR_DESCR(9, 'O', 'p', 'e', 'n', 'U', 'L', 'I', 'N', 'K');
116
117 __code struct usb_string_descriptor strProduct =
118         STR_DESCR(9, 'O', 'p', 'e', 'n', 'U', 'L', 'I', 'N', 'K');
119
120 __code struct usb_string_descriptor strSerialNumber =
121         STR_DESCR(6, '0', '0', '0', '0', '0', '1');
122
123 __code struct usb_string_descriptor strConfigDescr  =
124         STR_DESCR(12, 'J', 'T', 'A', 'G', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r');
125
126 /* Table containing pointers to string descriptors */
127 __code struct usb_string_descriptor *__code en_string_descriptors[4] = {
128         &strManufacturer,
129         &strProduct,
130         &strSerialNumber,
131         &strConfigDescr
132 };
133
134 void sudav_isr(void) __interrupt SUDAV_ISR
135 {
136         CLEAR_IRQ();
137
138         usb_handle_setup_data();
139
140         USBIRQ = SUDAVIR;
141         EP0CS |= HSNAK;
142 }
143
144 void sof_isr(void)      __interrupt SOF_ISR
145 {
146 }
147 void sutok_isr(void)    __interrupt SUTOK_ISR
148 {
149 }
150 void suspend_isr(void)  __interrupt SUSPEND_ISR
151 {
152 }
153 void usbreset_isr(void) __interrupt USBRESET_ISR
154 {
155 }
156 void ibn_isr(void)      __interrupt IBN_ISR
157 {
158 }
159
160 void ep0in_isr(void)    __interrupt EP0IN_ISR
161 {
162 }
163 void ep0out_isr(void)   __interrupt EP0OUT_ISR
164 {
165 }
166 void ep1in_isr(void)    __interrupt EP1IN_ISR
167 {
168 }
169 void ep1out_isr(void)   __interrupt EP1OUT_ISR
170 {
171 }
172
173 /**
174  * EP2 IN: called after the transfer from uC->Host has finished: we sent data
175  */
176 void ep2in_isr(void)    __interrupt EP2IN_ISR
177 {
178         EP2_in = 1;
179
180         CLEAR_IRQ();
181         IN07IRQ = IN2IR;/* Clear OUT2 IRQ */
182 }
183
184 /**
185  * EP2 OUT: called after the transfer from Host->uC has finished: we got data
186  */
187 void ep2out_isr(void)   __interrupt EP2OUT_ISR
188 {
189         EP2_out = 1;
190
191         CLEAR_IRQ();
192         OUT07IRQ = OUT2IR;      /* Clear OUT2 IRQ */
193 }
194
195 void ep3in_isr(void)    __interrupt EP3IN_ISR
196 {
197 }
198 void ep3out_isr(void)   __interrupt EP3OUT_ISR
199 {
200 }
201 void ep4in_isr(void)    __interrupt EP4IN_ISR
202 {
203 }
204 void ep4out_isr(void)   __interrupt EP4OUT_ISR
205 {
206 }
207 void ep5in_isr(void)    __interrupt EP5IN_ISR
208 {
209 }
210 void ep5out_isr(void)   __interrupt EP5OUT_ISR
211 {
212 }
213 void ep6in_isr(void)    __interrupt EP6IN_ISR
214 {
215 }
216 void ep6out_isr(void)   __interrupt EP6OUT_ISR
217 {
218 }
219 void ep7in_isr(void)    __interrupt EP7IN_ISR
220 {
221 }
222 void ep7out_isr(void)   __interrupt EP7OUT_ISR
223 {
224 }
225
226 /**
227  * Return the control/status register for an endpoint
228  *
229  * @param ep endpoint address
230  * @return on success: pointer to Control & Status register for endpoint
231  *  specified in \a ep
232  * @return on failure: NULL
233  */
234 __xdata uint8_t *usb_get_endpoint_cs_reg(uint8_t ep)
235 {
236         /* Mask direction bit */
237         uint8_t ep_num = ep & 0x7F;
238
239         switch (ep_num) {
240             case 0:
241                     return &EP0CS;
242                     break;
243             case 1:
244                     return ep & 0x80 ? &IN1CS : &OUT1CS;
245                     break;
246             case 2:
247                     return ep & 0x80 ? &IN2CS : &OUT2CS;
248                     break;
249             case 3:
250                     return ep & 0x80 ? &IN3CS : &OUT3CS;
251                     break;
252             case 4:
253                     return ep & 0x80 ? &IN4CS : &OUT4CS;
254                     break;
255             case 5:
256                     return ep & 0x80 ? &IN5CS : &OUT5CS;
257                     break;
258             case 6:
259                     return ep & 0x80 ? &IN6CS : &OUT6CS;
260                     break;
261             case 7:
262                     return ep & 0x80 ? &IN7CS : &OUT7CS;
263                     break;
264         }
265
266         return NULL;
267 }
268
269 void usb_reset_data_toggle(uint8_t ep)
270 {
271         /* TOGCTL register:
272            +----+-----+-----+------+-----+-------+-------+-------+
273            | Q  |  S  |  R  |  IO  |  0  |  EP2  |  EP1  |  EP0  |
274            +----+-----+-----+------+-----+-------+-------+-------+
275
276            To reset data toggle bits, we have to write the endpoint direction (IN/OUT)
277            to the IO bit and the endpoint number to the EP2..EP0 bits. Then, in a
278            separate write cycle, the R bit needs to be set.
279         */
280         uint8_t togctl_value = (ep & 0x80 >> 3) | (ep & 0x7);
281
282         /* First step: Write EP number and direction bit */
283         TOGCTL = togctl_value;
284
285         /* Second step: Set R bit */
286         togctl_value |= TOG_R;
287         TOGCTL = togctl_value;
288 }
289
290 /**
291  * Handle GET_STATUS request.
292  *
293  * @return on success: true
294  * @return on failure: false
295  */
296 bool usb_handle_get_status(void)
297 {
298         uint8_t *ep_cs;
299
300         switch (setup_data.bmRequestType) {
301             case GS_DEVICE:
302                         /* Two byte response: Byte 0, Bit 0 = self-powered, Bit 1 = remote wakeup.
303                          *                    Byte 1: reserved, reset to zero */
304                     IN0BUF[0] = 0;
305                     IN0BUF[1] = 0;
306
307                         /* Send response */
308                     IN0BC = 2;
309                     break;
310             case GS_INTERFACE:
311                         /* Always return two zero bytes according to USB 1.1 spec, p. 191 */
312                     IN0BUF[0] = 0;
313                     IN0BUF[1] = 0;
314
315                         /* Send response */
316                     IN0BC = 2;
317                     break;
318             case GS_ENDPOINT:
319                         /* Get stall bit for endpoint specified in low byte of wIndex */
320                     ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex & 0xff);
321
322                     if (*ep_cs & EPSTALL)
323                             IN0BUF[0] = 0x01;
324                     else
325                             IN0BUF[0] = 0x00;
326
327                         /* Second byte sent has to be always zero */
328                     IN0BUF[1] = 0;
329
330                         /* Send response */
331                     IN0BC = 2;
332                     break;
333             default:
334                     return false;
335                     break;
336         }
337
338         return true;
339 }
340
341 /**
342  * Handle CLEAR_FEATURE request.
343  *
344  * @return on success: true
345  * @return on failure: false
346  */
347 bool usb_handle_clear_feature(void)
348 {
349         __xdata uint8_t *ep_cs;
350
351         switch (setup_data.bmRequestType) {
352             case CF_DEVICE:
353                         /* Clear remote wakeup not supported: stall EP0 */
354                     STALL_EP0();
355                     break;
356             case CF_ENDPOINT:
357                     if (setup_data.wValue == 0) {
358                                 /* Unstall the endpoint specified in wIndex */
359                             ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex);
360                             if (!ep_cs)
361                                     return false;
362                             *ep_cs &= ~EPSTALL;
363                     } else {
364                                 /* Unsupported feature, stall EP0 */
365                             STALL_EP0();
366                     }
367                     break;
368             default:
369                         /* Vendor commands... */
370         }
371
372         return true;
373 }
374
375 /**
376  * Handle SET_FEATURE request.
377  *
378  * @return on success: true
379  * @return on failure: false
380  */
381 bool usb_handle_set_feature(void)
382 {
383         __xdata uint8_t *ep_cs;
384
385         switch (setup_data.bmRequestType) {
386             case SF_DEVICE:
387                     if (setup_data.wValue == 2)
388                             return true;
389                     break;
390             case SF_ENDPOINT:
391                     if (setup_data.wValue == 0) {
392                                 /* Stall the endpoint specified in wIndex */
393                             ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex);
394                             if (!ep_cs)
395                                     return false;
396                             *ep_cs |= EPSTALL;
397                     } else {
398                                 /* Unsupported endpoint feature */
399                             return false;
400                     }
401                     break;
402             default:
403                         /* Vendor commands... */
404                     break;
405         }
406
407         return true;
408 }
409
410 /**
411  * Handle GET_DESCRIPTOR request.
412  *
413  * @return on success: true
414  * @return on failure: false
415  */
416 bool usb_handle_get_descriptor(void)
417 {
418         __xdata uint8_t descriptor_type;
419         __xdata uint8_t descriptor_index;
420
421         descriptor_type = (setup_data.wValue & 0xff00) >> 8;
422         descriptor_index = setup_data.wValue & 0x00ff;
423
424         switch (descriptor_type) {
425             case DESCRIPTOR_TYPE_DEVICE:
426                     SUDPTRH = HI8(&device_descriptor);
427                     SUDPTRL = LO8(&device_descriptor);
428                     break;
429             case DESCRIPTOR_TYPE_CONFIGURATION:
430                     SUDPTRH = HI8(&config_descriptor);
431                     SUDPTRL = LO8(&config_descriptor);
432                     break;
433             case DESCRIPTOR_TYPE_STRING:
434                     if (setup_data.wIndex == 0) {
435                                 /* Supply language descriptor */
436                             SUDPTRH = HI8(&language_descriptor);
437                             SUDPTRL = LO8(&language_descriptor);
438                     } else if (setup_data.wIndex == 0x0409 /* US English */)   {
439                                 /* Supply string descriptor */
440                             SUDPTRH = HI8(en_string_descriptors[descriptor_index - 1]);
441                             SUDPTRL = LO8(en_string_descriptors[descriptor_index - 1]);
442                     } else
443                             return false;
444                     break;
445             default:
446                         /* Unsupported descriptor type */
447                     return false;
448                     break;
449         }
450
451         return true;
452 }
453
454 /**
455  * Handle SET_INTERFACE request.
456  */
457 void usb_handle_set_interface(void)
458 {
459         /* Reset Data Toggle */
460         usb_reset_data_toggle(USB_DIR_IN  | 2);
461         usb_reset_data_toggle(USB_DIR_OUT | 2);
462
463         /* Unstall & clear busy flag of all valid IN endpoints */
464         IN2CS = 0 | EPBSY;
465
466         /* Unstall all valid OUT endpoints, reset bytecounts */
467         OUT2CS = 0;
468         OUT2BC = 0;
469 }
470
471 /**
472  * Handle the arrival of a USB Control Setup Packet.
473  */
474 void usb_handle_setup_data(void)
475 {
476         switch (setup_data.bRequest) {
477             case GET_STATUS:
478                     if (!usb_handle_get_status())
479                             STALL_EP0();
480                     break;
481             case CLEAR_FEATURE:
482                     if (!usb_handle_clear_feature())
483                             STALL_EP0();
484                     break;
485             case 2: case 4:
486                         /* Reserved values */
487                     STALL_EP0();
488                     break;
489             case SET_FEATURE:
490                     if (!usb_handle_set_feature())
491                             STALL_EP0();
492                     break;
493             case SET_ADDRESS:
494                         /* Handled by USB core */
495                     break;
496             case SET_DESCRIPTOR:
497                         /* Set Descriptor not supported. */
498                     STALL_EP0();
499                     break;
500             case GET_DESCRIPTOR:
501                     if (!usb_handle_get_descriptor())
502                             STALL_EP0();
503                     break;
504             case GET_CONFIGURATION:
505                         /* OpenULINK has only one configuration, return its index */
506                     IN0BUF[0] = config_descriptor.bConfigurationValue;
507                     IN0BC = 1;
508                     break;
509             case SET_CONFIGURATION:
510                         /* OpenULINK has only one configuration -> nothing to do */
511                     break;
512             case GET_INTERFACE:
513                         /* OpenULINK only has one interface, return its number */
514                     IN0BUF[0] = interface_descriptor00.bInterfaceNumber;
515                     IN0BC = 1;
516                     break;
517             case SET_INTERFACE:
518                     usb_handle_set_interface();
519                     break;
520             case SYNCH_FRAME:
521                         /* Isochronous endpoints not used -> nothing to do */
522                     break;
523             default:
524                         /* Any other requests: do nothing */
525                     break;
526         }
527 }
528
529 /**
530  * USB initialization. Configures USB interrupts, endpoints and performs
531  * ReNumeration.
532  */
533 void usb_init(void)
534 {
535         /* Mark endpoint 2 IN & OUT as valid */
536         IN07VAL  = IN2VAL;
537         OUT07VAL = OUT2VAL;
538
539         /* Make sure no isochronous endpoints are marked valid */
540         INISOVAL  = 0;
541         OUTISOVAL = 0;
542
543         /* Disable isochronous endpoints. This makes the isochronous data buffers
544          * available as 8051 XDATA memory at address 0x2000 - 0x27FF */
545         ISOCTL = ISODISAB;
546
547         /* Enable USB Autovectoring */
548         USBBAV |= AVEN;
549
550         /* Enable SUDAV interrupt */
551         USBIEN |= SUDAVIE;
552
553         /* Enable EP2 OUT & IN interrupts */
554         OUT07IEN = OUT2IEN;
555         IN07IEN  = IN2IEN;
556
557         /* Enable USB interrupt (EIE register) */
558         EUSB = 1;
559
560         /* Perform ReNumeration */
561         USBCS = DISCON | RENUM;
562         delay_ms(200);
563         USBCS = DISCOE | RENUM;
564 }