a8299103bb34dc6e53d4f4c98c17cc234fcbaa4e
[openocd.git] / src / jtag / drivers / OpenULINK / src / usb.c
bloba8299103bb34dc6e53d4f4c98c17cc234fcbaa4e
1 /***************************************************************************
2 * Copyright (C) 2011 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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
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
28 * Therefore, we do not have to support the Set Configuration USB request.
31 #include "usb.h"
32 #include "delay.h"
33 #include "io.h"
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;
40 volatile __xdata __at 0x7FE8 struct setup_data setup_data;
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
47 * Normally, we would initialize the descriptor structures in C99 style:
49 * __code usb_device_descriptor_t device_descriptor = {
50 * .bLength = foo,
51 * .bDescriptorType = bar,
52 * .bcdUSB = 0xABCD,
53 * ...
54 * };
56 * But SDCC currently does not support this, so we have to do it the
57 * old-fashioned way...
60 __code struct usb_device_descriptor device_descriptor = {
61 /* .bLength = */ sizeof(struct usb_device_descriptor),
62 /* .bDescriptorType = */ DESCRIPTOR_TYPE_DEVICE,
63 /* .bcdUSB = */ 0x0110, /* BCD: 01.00 (Version 1.0 USB spec) */
64 /* .bDeviceClass = */ 0xFF, /* 0xFF = vendor-specific */
65 /* .bDeviceSubClass = */ 0xFF,
66 /* .bDeviceProtocol = */ 0xFF,
67 /* .bMaxPacketSize0 = */ 64,
68 /* .idVendor = */ 0xC251,
69 /* .idProduct = */ 0x2710,
70 /* .bcdDevice = */ 0x0100,
71 /* .iManufacturer = */ 1,
72 /* .iProduct = */ 2,
73 /* .iSerialNumber = */ 3,
74 /* .bNumConfigurations = */ 1
77 /* WARNING: ALL config, interface and endpoint descriptors MUST be adjacent! */
79 __code struct usb_config_descriptor config_descriptor = {
80 /* .bLength = */ sizeof(struct usb_config_descriptor),
81 /* .bDescriptorType = */ DESCRIPTOR_TYPE_CONFIGURATION,
82 /* .wTotalLength = */ sizeof(struct usb_config_descriptor) +
83 sizeof(struct usb_interface_descriptor) +
84 (NUM_ENDPOINTS *
85 sizeof(struct usb_endpoint_descriptor)),
86 /* .bNumInterfaces = */ 1,
87 /* .bConfigurationValue = */ 1,
88 /* .iConfiguration = */ 4, /* String describing this configuration */
89 /* .bmAttributes = */ 0x80, /* Only MSB set according to USB spec */
90 /* .MaxPower = */ 50 /* 100 mA */
93 __code struct usb_interface_descriptor interface_descriptor00 = {
94 /* .bLength = */ sizeof(struct usb_interface_descriptor),
95 /* .bDescriptorType = */ DESCRIPTOR_TYPE_INTERFACE,
96 /* .bInterfaceNumber = */ 0,
97 /* .bAlternateSetting = */ 0,
98 /* .bNumEndpoints = */ NUM_ENDPOINTS,
99 /* .bInterfaceClass = */ 0xFF,
100 /* .bInterfaceSubclass = */ 0xFF,
101 /* .bInterfaceProtocol = */ 0xFF,
102 /* .iInterface = */ 0
105 __code struct usb_endpoint_descriptor Bulk_EP2_IN_Endpoint_Descriptor = {
106 /* .bLength = */ sizeof(struct usb_endpoint_descriptor),
107 /* .bDescriptorType = */ 0x05,
108 /* .bEndpointAddress = */ 2 | USB_DIR_IN,
109 /* .bmAttributes = */ 0x02,
110 /* .wMaxPacketSize = */ 64,
111 /* .bInterval = */ 0
114 __code struct usb_endpoint_descriptor Bulk_EP2_OUT_Endpoint_Descriptor = {
115 /* .bLength = */ sizeof(struct usb_endpoint_descriptor),
116 /* .bDescriptorType = */ 0x05,
117 /* .bEndpointAddress = */ 2 | USB_DIR_OUT,
118 /* .bmAttributes = */ 0x02,
119 /* .wMaxPacketSize = */ 64,
120 /* .bInterval = */ 0
123 __code struct usb_language_descriptor language_descriptor = {
124 /* .bLength = */ 4,
125 /* .bDescriptorType = */ DESCRIPTOR_TYPE_STRING,
126 /* .wLANGID = */ {0x0409 /* US English */}
129 __code struct usb_string_descriptor strManufacturer =
130 STR_DESCR(9, 'O', 'p', 'e', 'n', 'U', 'L', 'I', 'N', 'K');
132 __code struct usb_string_descriptor strProduct =
133 STR_DESCR(9, 'O', 'p', 'e', 'n', 'U', 'L', 'I', 'N', 'K');
135 __code struct usb_string_descriptor strSerialNumber =
136 STR_DESCR(6, '0', '0', '0', '0', '0', '1');
138 __code struct usb_string_descriptor strConfigDescr =
139 STR_DESCR(12, 'J', 'T', 'A', 'G', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r');
141 /* Table containing pointers to string descriptors */
142 __code struct usb_string_descriptor *__code en_string_descriptors[4] = {
143 &strManufacturer,
144 &strProduct,
145 &strSerialNumber,
146 &strConfigDescr
149 void sudav_isr(void) __interrupt SUDAV_ISR
151 CLEAR_IRQ();
153 usb_handle_setup_data();
155 USBIRQ = SUDAVIR;
156 EP0CS |= HSNAK;
159 void sof_isr(void) __interrupt SOF_ISR
162 void sutok_isr(void) __interrupt SUTOK_ISR
165 void suspend_isr(void) __interrupt SUSPEND_ISR
168 void usbreset_isr(void) __interrupt USBRESET_ISR
171 void ibn_isr(void) __interrupt IBN_ISR
175 void ep0in_isr(void) __interrupt EP0IN_ISR
178 void ep0out_isr(void) __interrupt EP0OUT_ISR
181 void ep1in_isr(void) __interrupt EP1IN_ISR
184 void ep1out_isr(void) __interrupt EP1OUT_ISR
189 * EP2 IN: called after the transfer from uC->Host has finished: we sent data
191 void ep2in_isr(void) __interrupt EP2IN_ISR
193 EP2_in = 1;
195 CLEAR_IRQ();
196 IN07IRQ = IN2IR;/* Clear OUT2 IRQ */
200 * EP2 OUT: called after the transfer from Host->uC has finished: we got data
202 void ep2out_isr(void) __interrupt EP2OUT_ISR
204 EP2_out = 1;
206 CLEAR_IRQ();
207 OUT07IRQ = OUT2IR; /* Clear OUT2 IRQ */
210 void ep3in_isr(void) __interrupt EP3IN_ISR
213 void ep3out_isr(void) __interrupt EP3OUT_ISR
216 void ep4in_isr(void) __interrupt EP4IN_ISR
219 void ep4out_isr(void) __interrupt EP4OUT_ISR
222 void ep5in_isr(void) __interrupt EP5IN_ISR
225 void ep5out_isr(void) __interrupt EP5OUT_ISR
228 void ep6in_isr(void) __interrupt EP6IN_ISR
231 void ep6out_isr(void) __interrupt EP6OUT_ISR
234 void ep7in_isr(void) __interrupt EP7IN_ISR
237 void ep7out_isr(void) __interrupt EP7OUT_ISR
242 * Return the control/status register for an endpoint
244 * @param ep endpoint address
245 * @return on success: pointer to Control & Status register for endpoint
246 * specified in \a ep
247 * @return on failure: NULL
249 __xdata uint8_t *usb_get_endpoint_cs_reg(uint8_t ep)
251 /* Mask direction bit */
252 uint8_t ep_num = ep & 0x7F;
254 switch (ep_num) {
255 case 0:
256 return &EP0CS;
257 break;
258 case 1:
259 return ep & 0x80 ? &IN1CS : &OUT1CS;
260 break;
261 case 2:
262 return ep & 0x80 ? &IN2CS : &OUT2CS;
263 break;
264 case 3:
265 return ep & 0x80 ? &IN3CS : &OUT3CS;
266 break;
267 case 4:
268 return ep & 0x80 ? &IN4CS : &OUT4CS;
269 break;
270 case 5:
271 return ep & 0x80 ? &IN5CS : &OUT5CS;
272 break;
273 case 6:
274 return ep & 0x80 ? &IN6CS : &OUT6CS;
275 break;
276 case 7:
277 return ep & 0x80 ? &IN7CS : &OUT7CS;
278 break;
281 return NULL;
284 void usb_reset_data_toggle(uint8_t ep)
286 /* TOGCTL register:
287 +----+-----+-----+------+-----+-------+-------+-------+
288 | Q | S | R | IO | 0 | EP2 | EP1 | EP0 |
289 +----+-----+-----+------+-----+-------+-------+-------+
291 To reset data toggle bits, we have to write the endpoint direction (IN/OUT)
292 to the IO bit and the endpoint number to the EP2..EP0 bits. Then, in a
293 separate write cycle, the R bit needs to be set.
295 uint8_t togctl_value = (ep & 0x80 >> 3) | (ep & 0x7);
297 /* First step: Write EP number and direction bit */
298 TOGCTL = togctl_value;
300 /* Second step: Set R bit */
301 togctl_value |= TOG_R;
302 TOGCTL = togctl_value;
306 * Handle GET_STATUS request.
308 * @return on success: true
309 * @return on failure: false
311 bool usb_handle_get_status(void)
313 uint8_t *ep_cs;
315 switch (setup_data.bmRequestType) {
316 case GS_DEVICE:
317 /* Two byte response: Byte 0, Bit 0 = self-powered, Bit 1 = remote wakeup.
318 * Byte 1: reserved, reset to zero */
319 IN0BUF[0] = 0;
320 IN0BUF[1] = 0;
322 /* Send response */
323 IN0BC = 2;
324 break;
325 case GS_INTERFACE:
326 /* Always return two zero bytes according to USB 1.1 spec, p. 191 */
327 IN0BUF[0] = 0;
328 IN0BUF[1] = 0;
330 /* Send response */
331 IN0BC = 2;
332 break;
333 case GS_ENDPOINT:
334 /* Get stall bit for endpoint specified in low byte of wIndex */
335 ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex & 0xff);
337 if (*ep_cs & EPSTALL)
338 IN0BUF[0] = 0x01;
339 else
340 IN0BUF[0] = 0x00;
342 /* Second byte sent has to be always zero */
343 IN0BUF[1] = 0;
345 /* Send response */
346 IN0BC = 2;
347 break;
348 default:
349 return false;
350 break;
353 return true;
357 * Handle CLEAR_FEATURE request.
359 * @return on success: true
360 * @return on failure: false
362 bool usb_handle_clear_feature(void)
364 __xdata uint8_t *ep_cs;
366 switch (setup_data.bmRequestType) {
367 case CF_DEVICE:
368 /* Clear remote wakeup not supported: stall EP0 */
369 STALL_EP0();
370 break;
371 case CF_ENDPOINT:
372 if (setup_data.wValue == 0) {
373 /* Unstall the endpoint specified in wIndex */
374 ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex);
375 if (!ep_cs)
376 return false;
377 *ep_cs &= ~EPSTALL;
378 } else {
379 /* Unsupported feature, stall EP0 */
380 STALL_EP0();
382 break;
383 default:
384 /* Vendor commands... */
387 return true;
391 * Handle SET_FEATURE request.
393 * @return on success: true
394 * @return on failure: false
396 bool usb_handle_set_feature(void)
398 __xdata uint8_t *ep_cs;
400 switch (setup_data.bmRequestType) {
401 case SF_DEVICE:
402 if (setup_data.wValue == 2)
403 return true;
404 break;
405 case SF_ENDPOINT:
406 if (setup_data.wValue == 0) {
407 /* Stall the endpoint specified in wIndex */
408 ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex);
409 if (!ep_cs)
410 return false;
411 *ep_cs |= EPSTALL;
412 } else {
413 /* Unsupported endpoint feature */
414 return false;
416 break;
417 default:
418 /* Vendor commands... */
419 break;
422 return true;
426 * Handle GET_DESCRIPTOR request.
428 * @return on success: true
429 * @return on failure: false
431 bool usb_handle_get_descriptor(void)
433 __xdata uint8_t descriptor_type;
434 __xdata uint8_t descriptor_index;
436 descriptor_type = (setup_data.wValue & 0xff00) >> 8;
437 descriptor_index = setup_data.wValue & 0x00ff;
439 switch (descriptor_type) {
440 case DESCRIPTOR_TYPE_DEVICE:
441 SUDPTRH = HI8(&device_descriptor);
442 SUDPTRL = LO8(&device_descriptor);
443 break;
444 case DESCRIPTOR_TYPE_CONFIGURATION:
445 SUDPTRH = HI8(&config_descriptor);
446 SUDPTRL = LO8(&config_descriptor);
447 break;
448 case DESCRIPTOR_TYPE_STRING:
449 if (setup_data.wIndex == 0) {
450 /* Supply language descriptor */
451 SUDPTRH = HI8(&language_descriptor);
452 SUDPTRL = LO8(&language_descriptor);
453 } else if (setup_data.wIndex == 0x0409 /* US English */) {
454 /* Supply string descriptor */
455 SUDPTRH = HI8(en_string_descriptors[descriptor_index - 1]);
456 SUDPTRL = LO8(en_string_descriptors[descriptor_index - 1]);
457 } else
458 return false;
459 break;
460 default:
461 /* Unsupported descriptor type */
462 return false;
463 break;
466 return true;
470 * Handle SET_INTERFACE request.
472 void usb_handle_set_interface(void)
474 /* Reset Data Toggle */
475 usb_reset_data_toggle(USB_DIR_IN | 2);
476 usb_reset_data_toggle(USB_DIR_OUT | 2);
478 /* Unstall & clear busy flag of all valid IN endpoints */
479 IN2CS = 0 | EPBSY;
481 /* Unstall all valid OUT endpoints, reset bytecounts */
482 OUT2CS = 0;
483 OUT2BC = 0;
487 * Handle the arrival of a USB Control Setup Packet.
489 void usb_handle_setup_data(void)
491 switch (setup_data.bRequest) {
492 case GET_STATUS:
493 if (!usb_handle_get_status())
494 STALL_EP0();
495 break;
496 case CLEAR_FEATURE:
497 if (!usb_handle_clear_feature())
498 STALL_EP0();
499 break;
500 case 2: case 4:
501 /* Reserved values */
502 STALL_EP0();
503 break;
504 case SET_FEATURE:
505 if (!usb_handle_set_feature())
506 STALL_EP0();
507 break;
508 case SET_ADDRESS:
509 /* Handled by USB core */
510 break;
511 case SET_DESCRIPTOR:
512 /* Set Descriptor not supported. */
513 STALL_EP0();
514 break;
515 case GET_DESCRIPTOR:
516 if (!usb_handle_get_descriptor())
517 STALL_EP0();
518 break;
519 case GET_CONFIGURATION:
520 /* OpenULINK has only one configuration, return its index */
521 IN0BUF[0] = config_descriptor.bConfigurationValue;
522 IN0BC = 1;
523 break;
524 case SET_CONFIGURATION:
525 /* OpenULINK has only one configuration -> nothing to do */
526 break;
527 case GET_INTERFACE:
528 /* OpenULINK only has one interface, return its number */
529 IN0BUF[0] = interface_descriptor00.bInterfaceNumber;
530 IN0BC = 1;
531 break;
532 case SET_INTERFACE:
533 usb_handle_set_interface();
534 break;
535 case SYNCH_FRAME:
536 /* Isochronous endpoints not used -> nothing to do */
537 break;
538 default:
539 /* Any other requests: do nothing */
540 break;
545 * USB initialization. Configures USB interrupts, endpoints and performs
546 * ReNumeration.
548 void usb_init(void)
550 /* Mark endpoint 2 IN & OUT as valid */
551 IN07VAL = IN2VAL;
552 OUT07VAL = OUT2VAL;
554 /* Make sure no isochronous endpoints are marked valid */
555 INISOVAL = 0;
556 OUTISOVAL = 0;
558 /* Disable isochronous endpoints. This makes the isochronous data buffers
559 * available as 8051 XDATA memory at address 0x2000 - 0x27FF */
560 ISOCTL = ISODISAB;
562 /* Enable USB Autovectoring */
563 USBBAV |= AVEN;
565 /* Enable SUDAV interrupt */
566 USBIEN |= SUDAVIE;
568 /* Enable EP2 OUT & IN interrupts */
569 OUT07IEN = OUT2IEN;
570 IN07IEN = IN2IEN;
572 /* Enable USB interrupt (EIE register) */
573 EUSB = 1;
575 /* Perform ReNumeration */
576 USBCS = DISCON | RENUM;
577 delay_ms(200);
578 USBCS = DISCOE | RENUM;