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