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