You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

580 lines
15 KiB

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