usb_stack.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*
  2. This work is licensed under the Creative Commons Attribution 3.0 Unported License.
  3. To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/
  4. or send a letter to
  5. Creative Commons,
  6. 171 Second Street,
  7. Suite 300,
  8. San Francisco,
  9. California,
  10. 94105,
  11. USA.
  12. Influence and inspiration taken from http://pe.ece.olin.edu/ece/projects.html
  13. */
  14. // JTR v0.2a Jan 26th 2012
  15. #include "../dp_usb/usb_stack_globals.h" // USB stack only defines Not function related.
  16. #if USB_EP0_BUFFER_SIZE == 8u
  17. #elif USB_EP0_BUFFER_SIZE == 16u
  18. #elif USB_EP0_BUFFER_SIZE == 32u
  19. #elif USB_EP0_BUFFER_SIZE == 64u
  20. #else
  21. #error "USB_EP0_BUFFER_SIZE needs to be 8, 16, 32 or 64 bytes"
  22. #endif
  23. ROMPTR const BYTE *usb_device_descriptor;
  24. ROMPTR const BYTE *usb_config_descriptor;
  25. ROMPTR const BYTE *usb_string_descriptor;
  26. int usb_num_string_descriptors;
  27. usb_handler_t sof_handler;
  28. usb_handler_t class_setup_handler, vendor_setup_handler;
  29. usb_ep_t endpoints[MAX_CHIP_EP]; // JTR change. MAX_CHIP_EP is the number of hardware endpoints on the silicon. See picusb.h
  30. /* Allocate buffers for buffer description table and the actual buffers */
  31. // CvD: linkscript puts it in the right memory location
  32. // JTR comments. This below goes part way to ridding us of the need for a linker script (PIC18).
  33. // It floats the EP0 buffers to occupy space immediately behind the buffer descriptors.
  34. // However there are problems. It only works for the EP0 buffers because they are the only
  35. // buffers defined in this block. It is not possible to do arithmatic within a #pragma
  36. // therefore there seems to be no way to cause EPs in other blocks to float.
  37. // All the buffers would need to be defined here and this would break the universal nature
  38. // of this module. As such efforts to create a custom linker script free stack have been
  39. // put on hold for now but can be revisited at any stage.
  40. // Please see http://dangerousprototypes.com/forum/viewtopic.php?f=39&t=1651&start=120#p17401
  41. #if defined(PIC_18F)
  42. #pragma udata usb_bdt
  43. BDentry usb_bdt[2 + 2 * MAX_EPNUM_USED]; // JTR changed index from 32 to variable
  44. #pragma udata usb_data
  45. //* Only claim buffer for ep 0 */
  46. #if USB_PP_BUF_MODE == 0
  47. BYTE usb_ep0_out_buf[USB_EP0_BUFFER_SIZE];
  48. BYTE usb_ep0_in_buf[USB_EP0_BUFFER_SIZE];
  49. #else
  50. #error "Ping pong buffer not implemented yet!"
  51. #endif
  52. #elif defined(PIC_24F)
  53. #pragma udata usb_bdt
  54. BDentry usb_bdt[2 + 2 * MAX_EPNUM_USED] __attribute__((aligned(512))); // JTR changed index from 32 to variable TODO: Dynamic allocation reflecting number of used endpoints. (How to do counting in preprocessor?)
  55. #if USB_PP_BUF_MODE == 0
  56. BYTE usb_ep0_out_buf[USB_EP0_BUFFER_SIZE];
  57. BYTE usb_ep0_in_buf[USB_EP0_BUFFER_SIZE];
  58. #else
  59. #error "Ping pong buffer not implemented yet!"
  60. #endif
  61. #endif
  62. #pragma udata
  63. unsigned int usb_device_status;
  64. unsigned int usb_current_cfg;
  65. volatile BYTE usb_device_state;
  66. BYTE usb_addr_pending;
  67. BYTE trn_status; // Global since it is needed everywere
  68. BDentry *EP0_Outbdp, *EP0_Inbdp; // Dito
  69. BYTE IsSuspended = 0;
  70. ROMPTR const BYTE *usb_rom_ptr;
  71. size_t usb_rom_len;
  72. volatile BYTE usbrequesterrorflag;
  73. void usb_init(ROMPTR const BYTE *device_descriptor,
  74. ROMPTR const BYTE *config_descriptor,
  75. ROMPTR const BYTE *string_descriptor,
  76. int num_string_descriptors) {
  77. usb_device_descriptor = device_descriptor;
  78. usb_config_descriptor = config_descriptor;
  79. usb_string_descriptor = string_descriptor;
  80. usb_num_string_descriptors = num_string_descriptors;
  81. sof_handler = NULL;
  82. class_setup_handler = NULL;
  83. vendor_setup_handler = NULL;
  84. usb_unset_in_handler(0);
  85. usb_unset_out_handler(0);
  86. ClearUSBtoDefault();
  87. ConfigureUsbHardware();
  88. EnablePacketTransfer();
  89. }
  90. void usb_start(void) {
  91. EnableUsb(); // Enable USB-hardware
  92. usb_device_state = ATTACHED_STATE;
  93. while (SingleEndedZeroIsSet()); // Busywait for initial power-up
  94. usb_device_state = DEFAULT_STATE; //JTR2
  95. }
  96. void usb_handle_error(void) {
  97. /* No errorhandler for now, just clear offending flag*/
  98. ClearAllUsbErrorInterruptFlags();
  99. }
  100. void usb_handle_reset(void) {
  101. do {
  102. ClearUsbInterruptFlag(USB_TRN); // JTR corrected Must poll TRN Flag and clear, then wait 6 cycles. for next flag set.
  103. usb_current_cfg = 0;
  104. usb_device_state = DEFAULT_STATE; // This BLOCK creates the requied 6 cycle delay for TRNF to reassert.
  105. usb_addr_pending = 0x00;
  106. } while (USB_TRANSACTION_FLAG);
  107. ClearUSBtoDefault();
  108. EnablePacketTransfer();
  109. }
  110. void ClearUSBtoDefault(void) {
  111. int i;
  112. sof_handler = NULL;
  113. class_setup_handler = NULL;
  114. vendor_setup_handler = NULL;
  115. SetUsbAddress(0); // After reset we don't have an address
  116. ResetPPbuffers();
  117. ClearAllUsbErrorInterruptFlags();
  118. for (i = 0; i < MAX_CHIP_EP; i++) {
  119. endpoints[i].out_handler = NULL;
  120. endpoints[i].in_handler = NULL;
  121. USB_UEP[i] = 0;
  122. }
  123. for (i = 0; i < (2 + 2 * MAX_EPNUM_USED); i++) {
  124. usb_bdt[i].BDSTAT = 0;
  125. }
  126. USB_UEP0 = USB_EP_CONTROL; // Configure Only ep0 At this point.
  127. //usbrequesterrorflag = 0;
  128. #ifdef USB_SELF_POWERED
  129. // JTR TODO this isn't actually 100% correct. "usb_device_status" is a runtime variable
  130. // In the case of a bus powered device it will always be 0x000 but in the case of
  131. // self powered with bus powered option it becames variable to the current powered
  132. // State. This is a minor thing and for now but it may need to be addressed if there is
  133. // any hardware that is dual powered.
  134. usb_device_status = 0x0001;
  135. #else
  136. usb_device_status = 0x0000;
  137. #endif
  138. usb_device_state = DETACHED_STATE; // JTR added flag byte for enumeration state
  139. usb_current_cfg = 0; // JTR formally usb_configured
  140. usb_addr_pending = 0x00;
  141. #if USB_PP_BUF_MODE == NO_PINGPONG
  142. usb_bdt[USB_CALC_BD(0, USB_DIR_OUT, USB_PP_EVEN)].BDCNT = USB_EP0_BUFFER_SIZE; // JTR endpoints[0].buffer_size; same thing done more obviously
  143. usb_bdt[USB_CALC_BD(0, USB_DIR_OUT, USB_PP_EVEN)].BDADDR = usb_ep0_out_buf; //endpoints[0].out_buffer;
  144. usb_bdt[USB_CALC_BD(0, USB_DIR_OUT, USB_PP_EVEN)].BDSTAT = UOWN + DTSEN;
  145. usb_bdt[USB_CALC_BD(0, USB_DIR_IN, USB_PP_EVEN)].BDCNT = 0;
  146. usb_bdt[USB_CALC_BD(0, USB_DIR_IN, USB_PP_EVEN)].BDADDR = usb_ep0_in_buf; //endpoints[0].in_buffer;
  147. usb_bdt[USB_CALC_BD(0, USB_DIR_IN, USB_PP_EVEN)].BDSTAT = DTS + DTSEN; // Set DTS => First packet inverts, ie. is Data0
  148. #else
  149. #error "Invalid PING_PONG mode"
  150. #endif
  151. }
  152. void usb_handler(void) {
  153. if (USB_IDLE_FLAG) {
  154. /* Idle - suspend */
  155. USBSuspend(); // // Must be defined in user code.
  156. ClearUsbInterruptFlag(USB_IDLE);
  157. }
  158. if (USB_RESET_FLAG) {
  159. usb_handle_reset();
  160. ClearUsbInterruptFlag(USB_URST);
  161. }
  162. if (USB_ERROR_FLAG) {
  163. // usb_handle_error();
  164. ClearAllUsbErrorInterruptFlags();
  165. ClearUsbInterruptFlag(USB_UERR);
  166. }
  167. if (USB_STALL_FLAG) {
  168. ClearUsbInterruptFlag(USB_STALL);
  169. }
  170. if (USB_SOF_FLAG) {
  171. /* Start-of-frame */
  172. if (sof_handler) sof_handler();
  173. ClearUsbInterruptFlag(USB_SOF);
  174. }
  175. if (USB_TRANSACTION_FLAG) {
  176. if (!USB_STAT2EP(GetUsbTransaction()))
  177. usb_handle_transaction(); // Only handle EP0 transactions.
  178. ClearUsbInterruptFlag(USB_TRN); // JTR Missing! This is why Ian was only getting one interrupt??
  179. } // Side effect: advance USTAT Fifo
  180. }
  181. void usb_handle_transaction(void) {
  182. usbrequesterrorflag = 0;
  183. trn_status = GetUsbTransaction();
  184. EP0_Outbdp = &usb_bdt[USB_USTAT2BD(trn_status)];
  185. EP0_Inbdp = &usb_bdt[USB_USTAT2BD(trn_status | DIRBIT)]; // All replies in IN direction
  186. switch (EP0_Outbdp->BDSTAT & USB_TOKEN_Mask) {
  187. case USB_TOKEN_SETUP:
  188. usb_handle_setup();
  189. break;
  190. case USB_TOKEN_OUT:
  191. usb_handle_out();
  192. break;
  193. case USB_TOKEN_IN:
  194. usb_handle_in();
  195. break;
  196. //default:
  197. /* Default case of unknown TOKEN - discard */
  198. }
  199. }
  200. void usb_handle_setup(void) {
  201. EP0_Inbdp->BDSTAT = DTSEN; // Reclaim reply buffer
  202. EnablePacketTransfer(); // JTR this is placed here to overcome a errate issue with early PIC18 USB pics.
  203. switch (EP0_Outbdp->BDADDR[USB_bmRequestType] & USB_bmRequestType_TypeMask) {
  204. case USB_bmRequestType_Standard:
  205. switch (EP0_Outbdp->BDADDR[USB_bmRequestType] & USB_bmRequestType_RecipientMask) {
  206. case USB_bmRequestType_Device:
  207. usb_handle_StandardDeviceRequest(EP0_Outbdp);
  208. break;
  209. case USB_bmRequestType_Interface:
  210. usb_handle_StandardInterfaceRequest(EP0_Outbdp);
  211. break;
  212. case USB_bmRequestType_Endpoint:
  213. usb_handle_StandardEndpointRequest(EP0_Outbdp);
  214. break;
  215. default:
  216. usb_RequestError();
  217. }
  218. break;
  219. case USB_bmRequestType_Class:
  220. if (class_setup_handler) class_setup_handler();
  221. break;
  222. case USB_bmRequestType_Vendor:
  223. //ROBOTS FIX: http://dangerousprototypes.com/forum/viewtopic.php?f=39&t=3849&view=unread#unread
  224. // did call class_setup_handler();
  225. if (vendor_setup_handler) vendor_setup_handler();
  226. break;
  227. default:
  228. usb_RequestError();
  229. }
  230. /* Prepare endpoint for new reception */
  231. EP0_Outbdp->BDCNT = USB_EP0_BUFFER_SIZE; // Size of EP0, should always be ep0?
  232. // JTR, is the next OUT transfer to be a setup packet (DAT0) or a DATA packet (DAT1)?
  233. // note that this is not an entirely robust way of doing things. See the microchip stack for
  234. // further comments and a better system as this does not account for errors and retries
  235. // and it results in the SIE not accepting the final out ZLP status packet for IN transfers
  236. // with a data stage. However it works but it is not anything to be proud of...
  237. EP0_Outbdp->BDSTAT = (!(EP0_Outbdp->BDADDR[USB_bmRequestType] & USB_bmRequestType_PhaseMask) &&
  238. (EP0_Outbdp->BDADDR[USB_wLength] || EP0_Outbdp->BDADDR[USB_wLengthHigh])) ? UOWN + DTS + DTSEN : UOWN + DTSEN;
  239. }
  240. void usb_handle_StandardDeviceRequest(BDentry *bdp) {
  241. BYTE *packet = bdp->BDADDR;
  242. int i;
  243. switch (packet[USB_bRequest]) {
  244. case USB_REQUEST_GET_STATUS:
  245. EP0_Inbdp->BDADDR[0] = usb_device_status & 0xFF;
  246. EP0_Inbdp->BDADDR[1] = usb_device_status >> 8;
  247. usb_ack_dat1(2);
  248. break;
  249. case USB_REQUEST_CLEAR_FEATURE:
  250. if (0x01u == packet[USB_wValue]) { // TODO: Remove magic (REMOTE_WAKEUP_FEATURE)
  251. usb_device_status &= ~0x0002;
  252. usb_ack_dat1(0);
  253. } else
  254. usb_RequestError();
  255. break;
  256. case USB_REQUEST_SET_FEATURE:
  257. if (0x01u == packet[USB_wValue]) { // TODO: Remove magic (REMOTE_WAKEUP_FEATURE)
  258. usb_device_status |= 0x0002;
  259. usb_ack_dat1(0);
  260. } else
  261. usb_RequestError();
  262. break;
  263. case USB_REQUEST_SET_ADDRESS:
  264. if (0x00u == packet[USB_wValueHigh] && 0x7Fu >= packet[USB_wValue]) {
  265. usb_addr_pending = packet[USB_wValue];
  266. usb_set_in_handler(0, usb_set_address);
  267. usb_ack_dat1(0);
  268. } else
  269. usb_RequestError();
  270. break;
  271. case USB_REQUEST_GET_DESCRIPTOR:
  272. switch (packet[USB_bDescriptorType]) {
  273. case USB_DEVICE_DESCRIPTOR_TYPE: // There is only every one in pratice.
  274. usb_rom_ptr = usb_device_descriptor;
  275. usb_rom_len = usb_device_descriptor[0]; // Get BYTE length from descriptor always at byte [0]
  276. if ((0 == packet[USB_wLengthHigh] && packet[USB_wLength] < usb_rom_ptr[0]))
  277. usb_rom_len = packet[USB_wLength]; // If the HOST asked for LESS then must adjust count to the smaller number
  278. break;
  279. case USB_CONFIGURATION_DESCRIPTOR_TYPE:
  280. if (packet[USB_bDescriptorIndex] >= usb_device_descriptor[17]) {
  281. flag_usb_RequestError();
  282. break;
  283. }
  284. usb_rom_ptr = usb_config_descriptor;
  285. usb_rom_len = usb_rom_ptr[2] + usb_rom_ptr[3] * 256; // Get WORD length from descriptor always at bytes 2&3 (Low-High)
  286. for (i = 0; i < packet[USB_bDescriptorIndex]; i++) { // Implicit linked list traversal until requested configuration
  287. usb_rom_ptr += usb_rom_len;
  288. usb_rom_len = usb_rom_ptr[2] + usb_rom_ptr[3] * 256; // Get (next) WORD length from descriptor always at bytes 2&3 (Low-High)
  289. }
  290. if ((packet[USB_wLengthHigh] < usb_rom_ptr[3]) ||
  291. (packet[USB_wLengthHigh] == usb_rom_ptr[3] && packet[USB_wLength] < usb_rom_ptr[2]))
  292. usb_rom_len = packet[USB_wLength] + packet[USB_wLengthHigh] * 256; // If the HOST asked for LESS then must adjust count to the smaller number
  293. break;
  294. case USB_STRING_DESCRIPTOR_TYPE:
  295. // TODO: Handle language request. For now return standard language.
  296. if (packet[USB_bDescriptorIndex] >= usb_num_string_descriptors) {
  297. flag_usb_RequestError();
  298. break;
  299. }
  300. usb_rom_ptr = usb_string_descriptor;
  301. usb_rom_len = usb_rom_ptr[0]; // Get BYTE length from descriptor always at byte [0]
  302. for (i = 0; i < packet[USB_bDescriptorIndex]; i++) { // Implicit linked list traversal until requested configuration
  303. usb_rom_ptr += usb_rom_len;
  304. usb_rom_len = usb_rom_ptr[0];
  305. }
  306. if ((0 == packet[USB_wLengthHigh] && packet[USB_wLength] < usb_rom_ptr[0]))
  307. usb_rom_len = packet[USB_wLength];
  308. break;
  309. case USB_INTERFACE_DESCRIPTOR_TYPE:
  310. case USB_ENDPOINT_DESCRIPTOR_TYPE:
  311. default:
  312. flag_usb_RequestError();
  313. }
  314. if (0 == usbrequesterrorflag) {
  315. usb_send_rom(); // Send first part of packet right away, the rest is handled by the EP0 IN handler.
  316. usb_set_in_handler(0, usb_send_rom);
  317. } else {
  318. usb_RequestError();
  319. }
  320. break;
  321. case USB_REQUEST_GET_CONFIGURATION:
  322. EP0_Inbdp->BDADDR[0] = usb_current_cfg;
  323. usb_ack_dat1(1);
  324. break;
  325. case USB_REQUEST_SET_CONFIGURATION:
  326. if (USB_NUM_CONFIGURATIONS >= packet[USB_wValue]) {
  327. // TODO: Support multiple configurations
  328. /* Configure endpoints (USB_UEPn - registers) */
  329. usb_current_cfg = packet[USB_wValue];
  330. if (usb_current_cfg != 0) {
  331. // JTR user_configured_init major addition. This is a CALLBACK to the USER when the device is enumerated.
  332. // This is when we setup non EP0 endpoints.
  333. // TODO: This really could be a function pointer
  334. usb_device_state = CONFIGURED_STATE;
  335. user_configured_init();
  336. } else {
  337. usb_device_state = ADDRESS_STATE;
  338. }
  339. usb_ack_dat1(0);
  340. } else
  341. usb_RequestError();
  342. break;
  343. case USB_REQUEST_SET_DESCRIPTOR:
  344. default:
  345. usb_RequestError();
  346. }
  347. }
  348. void usb_handle_StandardInterfaceRequest(BDentry *bdp) {
  349. BYTE *packet = bdp->BDADDR;
  350. switch (packet[USB_bRequest]) {
  351. case USB_REQUEST_GET_STATUS:
  352. EP0_Inbdp->BDADDR[0] = 0x00;
  353. EP0_Inbdp->BDADDR[1] = 0x00;
  354. usb_ack_dat1(2);
  355. break;
  356. case USB_REQUEST_GET_INTERFACE:
  357. if (USB_NUM_INTERFACES > packet[USB_bInterface]) {
  358. // TODO: Implement alternative interfaces, or move responsibility to class/vendor functions.
  359. EP0_Inbdp->BDADDR[0] = 0;
  360. usb_ack_dat1(1);
  361. } else
  362. usb_RequestError();
  363. break;
  364. case USB_REQUEST_SET_INTERFACE:
  365. if (USB_NUM_INTERFACES > packet[USB_bInterface] && 0u == packet[USB_wValue]) {
  366. // TODO: Implement alternative interfaces...
  367. usb_ack_dat1(0);
  368. } else
  369. usb_RequestError();
  370. break;
  371. case USB_REQUEST_CLEAR_FEATURE: // JTR N/A for interface
  372. case USB_REQUEST_SET_FEATURE: // This is correct and finished code.
  373. default:
  374. usb_RequestError();
  375. }
  376. }
  377. void usb_handle_StandardEndpointRequest(BDentry *bdp) {
  378. BYTE *packet;
  379. BYTE epnum;
  380. BYTE dir;
  381. BDentry *epbd;
  382. usb_uep_t *pUEP;
  383. packet = bdp->BDADDR;
  384. switch (packet[USB_bRequest]) {
  385. case USB_REQUEST_GET_STATUS:
  386. EP0_Inbdp->BDADDR[0] = 0x00; // Assume no stall
  387. EP0_Inbdp->BDADDR[1] = 0x00; // Same for stall or not
  388. epnum = packet[USB_wIndex] & 0x0F;
  389. dir = packet[USB_wIndex] >> 7;
  390. epbd = &usb_bdt[USB_CALC_BD(epnum, dir, USB_PP_EVEN)];
  391. if (epbd->BDSTAT &= ~BSTALL)
  392. EP0_Inbdp->BDADDR[0] = 0x01; // EVEN BD is stall flag set?
  393. //epbd = &usb_bdt[USB_CALC_BD(epnum, dir, USB_PP_ODD)];
  394. //if (epbd->BDSTAT &= ~BSTALL)
  395. // rbdp->BDADDR[0] = 0x01; // ODD BD is stall flag set?
  396. usb_ack_dat1(2);
  397. break;
  398. case USB_REQUEST_CLEAR_FEATURE:
  399. // As this is really is an application event and there
  400. // should be a call back and protocol for handling the
  401. // possible lost of a data packet.
  402. // TODO: ping-ping support.
  403. epnum = packet[USB_wIndex] & 0x0F; // JTR Added V0.2 after microchip stuff up with their documentation.
  404. pUEP = USB_UEP;
  405. pUEP += epnum;
  406. *pUEP &= ~USB_UEP_EPSTALL;
  407. dir = packet[USB_wIndex] >> 7;
  408. epbd = &usb_bdt[USB_CALC_BD(epnum, dir, USB_PP_EVEN)];
  409. epbd->BDSTAT &= ~BSTALL;
  410. if (dir) epbd->BDSTAT |= DTS; // JTR added IN EP set DTS as it will be toggled to zero next transfer
  411. if (0 == dir) epbd->BDSTAT &= ~DTS; // JTR added
  412. // JTR this pointless ATM. If ping-pong is enabled then you need to track PPBI
  413. // and set up ODD and EVEN BDs in respect to this. See complicated system in
  414. // microchip stack >= 2.8
  415. // epbd = &usb_bdt[USB_CALC_BD(epnum, dir, USB_PP_ODD)];
  416. // epbd->BDSTAT &= ~BSTALL;
  417. // if (dir) epbd->BDSTAT |= DTS; // JTR added
  418. // if (0 == dir) epbd->BDSTAT &= ~DTS; // JTR added
  419. usb_ack_dat1(0);
  420. break;
  421. case USB_REQUEST_SET_FEATURE:
  422. epnum = packet[USB_wIndex] & 0x0F;
  423. dir = packet[USB_wIndex] >> 7;
  424. epbd = &usb_bdt[USB_CALC_BD(epnum, dir, USB_PP_EVEN)];
  425. epbd->BDSTAT |= BSTALL;
  426. //epbd = &usb_bdt[USB_CALC_BD(epnum, dir, USB_PP_ODD)];
  427. //epbd->BDSTAT |= BSTALL;
  428. usb_ack_dat1(0);
  429. break;
  430. case USB_REQUEST_SYNCH_FRAME:
  431. default:
  432. usb_RequestError();
  433. }
  434. }
  435. void usb_handle_in(void) {
  436. if (endpoints[USB_STAT2EP(trn_status)].in_handler) {
  437. endpoints[USB_STAT2EP(trn_status)].in_handler();
  438. }
  439. }
  440. void usb_handle_out(void) {
  441. if (endpoints[USB_STAT2EP(trn_status)].out_handler) {
  442. endpoints[USB_STAT2EP(trn_status)].out_handler();
  443. }
  444. }
  445. void usb_register_sof_handler(usb_handler_t handler) {
  446. sof_handler = handler;
  447. }
  448. void usb_register_class_setup_handler(usb_handler_t handler) {
  449. class_setup_handler = handler;
  450. }
  451. void usb_register_vendor_setup_handler(usb_handler_t handler) {
  452. vendor_setup_handler = handler;
  453. }
  454. void usb_set_in_handler(int ep, usb_handler_t in_handler) {
  455. endpoints[ep].in_handler = in_handler;
  456. }
  457. void usb_set_out_handler(int ep, usb_handler_t out_handler) {
  458. endpoints[ep].out_handler = out_handler;
  459. }
  460. // JTR New added helper function use extensively by the standard and class
  461. // request handlers. All status IN packets are DAT1 as is the first DATA packet
  462. // of a IN transfer. Currently with this CDC stack the only IN DATA transfers
  463. // that are > 8 bytes is the descriptor transfer and these are transfered in
  464. // usb_send_rom()
  465. void usb_ack_dat1(int bdcnt) {
  466. EP0_Inbdp->BDCNT = (bdcnt & 0xFF);
  467. EP0_Inbdp->BDSTAT = (DTS | UOWN | DTSEN); // | ((bdcnt & 0x300) >> 8));
  468. }
  469. void usb_RequestError(void) {
  470. usb_bdt[USB_CALC_BD(0, USB_DIR_OUT, USB_PP_EVEN)].BDCNT = USB_EP0_BUFFER_SIZE;
  471. //usb_bdt[USB_CALC_BD(0, USB_DIR_OUT, USB_PP_ODD)].BDCNT = USB_EP0_BUFFER_SIZE;
  472. usb_bdt[USB_CALC_BD(0, USB_DIR_IN, USB_PP_EVEN)].BDSTAT = UOWN + BSTALL;
  473. usb_bdt[USB_CALC_BD(0, USB_DIR_OUT, USB_PP_EVEN)].BDSTAT = UOWN + BSTALL;
  474. //usb_bdt[USB_CALC_BD(0, USB_DIR_IN, USB_PP_ODD)].BDSTAT = UOWN + BSTALL;
  475. //usb_bdt[USB_CALC_BD(0, USB_DIR_OUT, USB_PP_ODD)].BDSTAT = UOWN + BSTALL;
  476. // JTR TODO: Should also kill the IN and OUT handlers?
  477. }
  478. void usb_set_address(void) {
  479. if (0x00u == usb_addr_pending) {
  480. usb_device_state = DEFAULT_STATE;
  481. } else {
  482. usb_device_state = ADDRESS_STATE;
  483. }
  484. SetUsbAddress(usb_addr_pending);
  485. usb_addr_pending = 0xFF;
  486. usb_unset_in_handler(0); // Unregister handler
  487. }
  488. void usb_send_rom(void) {
  489. unsigned int i;
  490. size_t packet_len;
  491. if (usb_rom_len) {
  492. packet_len = (usb_rom_len < USB_EP0_BUFFER_SIZE) ? usb_rom_len : USB_EP0_BUFFER_SIZE; // JTR changed from MAX_BUFFER_SIZE
  493. for (i = 0; i < packet_len; i++) {
  494. EP0_Inbdp->BDADDR[i] = usb_rom_ptr[i];
  495. }
  496. } else {
  497. packet_len = 0;
  498. usb_unset_in_handler(0);
  499. }
  500. EP0_Inbdp->BDCNT = (BYTE) packet_len;
  501. EP0_Inbdp->BDSTAT = ((EP0_Inbdp->BDSTAT ^ DTS) & DTS) | UOWN | DTSEN; // Packet length always less then 256 on endpoint 0
  502. usb_rom_ptr += packet_len;
  503. usb_rom_len -= packet_len;
  504. }