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.
 
 
 
 
 
 

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