cdc.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  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. */
  13. // JTR V0.1a
  14. // JTR v0.1b
  15. // JTR v0.1c // tidy up added code line code handler to set the SPBRG based on line coding.
  16. // JTR V0.2a // 26th Jan 2012
  17. #include "usb_stack_globals.h" // USB stack only defines Not function related.
  18. #include <string.h>
  19. enum stopbits {
  20. one = 0, oneandahalf = 1, two = 2
  21. };
  22. enum parity {
  23. none = 0, odd = 1, even = 2, mark = 3, space = 4
  24. };
  25. const char parity_str[] = {'N', 'O', 'E', 'M', 'S'};
  26. struct cdc_LineCodeing {
  27. unsigned long int dwDTERate;
  28. enum stopbits bCharFormat;
  29. enum parity bParityType;
  30. BYTE bDataBits;
  31. } linecodeing;
  32. #pragma udata usb_data
  33. BYTE cdc_acm_in_buffer[CDC_NOTICE_BUFFER_SIZE]; //JTR NEWLY defined NOTICE BUFFER SIZE and increased from 8 to 10 bytes in usb_config.h
  34. #pragma udata usb_data3
  35. BYTE cdc_In_bufferA[CDC_BUFFER_SIZE];
  36. BYTE cdc_In_bufferB[CDC_BUFFER_SIZE];
  37. BYTE cdc_Out_bufferA[CDC_BUFFER_SIZE];
  38. BYTE cdc_Out_bufferB[CDC_BUFFER_SIZE];
  39. #pragma udata
  40. struct _cdc_ControlLineState cls;
  41. BYTE cdc_In_len; // total cdc In length
  42. volatile BYTE cdc_Out_len; // total cdc out length
  43. BYTE IsInBufferA;
  44. BYTE IsOutBufferA;
  45. BYTE *InPtr;
  46. BYTE *OutPtr;
  47. BYTE LineStateUpdated = 0;
  48. BYTE cdc_timeout_count = 0;
  49. BYTE ZLPpending = 0;
  50. BYTE lock = 0;
  51. BDentry *CDC_Outbdp, *CDC_Inbdp;
  52. BYTE CDCFunctionError;
  53. volatile BYTE cdc_trf_state; // JTR don't see that it is really volatile in current context may be in future.
  54. void initCDC(void) {
  55. // JTR The function usb_init() is now called from main.c prior to anything else belonging to the CDC CLASS
  56. // If we have multiple functions we want the USB initialization to be in only one consistant place.
  57. // The sort of things we would do in InitCDC would be to setup I/O pins and the HARDWARE UART so it
  58. // is not transmitting junk between a RESET and the device being enumerated. Hardware CTS/RTS
  59. // would also be setup here if being used.
  60. linecodeing.dwDTERate = 115200;
  61. linecodeing.bCharFormat = one;
  62. linecodeing.bParityType = none;
  63. linecodeing.bDataBits = 8;
  64. cls.DTR = 0;
  65. cls.RTS = 0;
  66. usb_register_class_setup_handler(cdc_setup);
  67. }
  68. void user_configured_init(void) {
  69. // JTR NEW FUNCTION
  70. // After the device is enumerated and configured then we set up non EP0 endpoints.
  71. // We only enable the endpoints we are using, not all of them.
  72. // Prior to this they are held in a disarmed state.
  73. // This function belongs to the current USB function and IS NOT generic. This is CLASS specific
  74. // and will vary from implementation to implementation.
  75. usb_unset_in_handler(1);
  76. usb_unset_in_handler(2);
  77. usb_unset_out_handler(2);
  78. USB_UEP1 = USB_EP_IN;
  79. USB_UEP2 = USB_EP_INOUT;
  80. /* Configure buffer descriptors */
  81. #if USB_PP_BUF_MODE == 0
  82. // JTR Setup CDC LINE_NOTICE EP (Interrupt IN)
  83. usb_bdt[USB_CALC_BD(1, USB_DIR_IN, USB_PP_EVEN)].BDCNT = 0;
  84. usb_bdt[USB_CALC_BD(1, USB_DIR_IN, USB_PP_EVEN)].BDADDR = cdc_acm_in_buffer;
  85. usb_bdt[USB_CALC_BD(1, USB_DIR_IN, USB_PP_EVEN)].BDSTAT = DTS + DTSEN; // Set DTS => First packet inverts, ie. is Data0
  86. #else
  87. // TODO: Implement Ping-Pong buffering setup.
  88. #error "PP Mode not implemented yet"
  89. #endif
  90. usb_register_class_setup_handler(cdc_setup);
  91. cdc_trf_state = 0;
  92. CDC_Outbdp = &usb_bdt[USB_CALC_BD(2, USB_DIR_OUT, USB_PP_EVEN)];
  93. CDC_Inbdp = &usb_bdt[USB_CALC_BD(2, USB_DIR_IN, USB_PP_EVEN)];
  94. IsInBufferA = 0xFF;
  95. InPtr = cdc_In_bufferA;
  96. cdc_In_len = 0;
  97. CDC_Inbdp->BDADDR = &cdc_In_bufferA[0];
  98. CDC_Inbdp->BDCNT = 0;
  99. CDC_Inbdp->BDSTAT = DTS + DTSEN;
  100. cdc_Out_len = 0;
  101. IsOutBufferA = 0xFF;
  102. OutPtr = cdc_Out_bufferA;
  103. CDC_Outbdp->BDCNT = CDC_BUFFER_SIZE;
  104. CDC_Outbdp->BDADDR = &cdc_Out_bufferA[0];
  105. CDC_Outbdp->BDSTAT = UOWN + DTSEN;
  106. }
  107. void cdc_setup(void) {
  108. BYTE *packet;
  109. size_t reply_len;
  110. packet = EP0_Outbdp->BDADDR;
  111. switch (packet[USB_bmRequestType] & (USB_bmRequestType_TypeMask | USB_bmRequestType_RecipientMask)) {
  112. case (USB_bmRequestType_Class | USB_bmRequestType_Interface):
  113. switch (packet[USB_bRequest]) {
  114. //JTR This is just a dummy, nothing defined to do for CDC ACM
  115. case CDC_SEND_ENCAPSULATED_COMMAND:
  116. usb_ack_dat1(0);
  117. break;
  118. //JTR This is just a dummy, nothing defined to do for CDC ACM
  119. case CDC_GET_ENCAPSULATED_RESPONSE:
  120. //usb_ack_zero(rbdp);
  121. usb_ack_dat1(0);
  122. break;
  123. case CDC_SET_COMM_FEATURE: // Optional
  124. case CDC_GET_COMM_FEATURE: // Optional
  125. case CDC_CLEAR_COMM_FEATURE: // Optional
  126. usb_RequestError(); // Not advertised in ACM functional descriptor
  127. break;
  128. case CDC_SET_LINE_CODING: // Optional, strongly recomended
  129. usb_set_out_handler(0, cdc_set_line_coding_data); // Register out handler function
  130. break;
  131. case CDC_GET_LINE_CODING: // Optional, strongly recomended
  132. // JTR reply length (7) is always going to be less than minimum EP0 size (8)
  133. reply_len = *((unsigned int *) &packet[USB_wLength]);
  134. if (sizeof (struct cdc_LineCodeing) < reply_len) {
  135. reply_len = sizeof (struct cdc_LineCodeing);
  136. }
  137. memcpy(EP0_Inbdp->BDADDR, (const void *) &linecodeing, reply_len);
  138. usb_ack_dat1(reply_len); // JTR common addition for STD and CLASS ACK
  139. usb_set_in_handler(0, cdc_get_line_coding);
  140. break;
  141. case CDC_SET_CONTROL_LINE_STATE: // Optional
  142. cls = *((struct _cdc_ControlLineState *) &packet[USB_wValue]);
  143. usb_set_in_handler(0, cdc_set_control_line_state_status); // JTR why bother?
  144. usb_ack_dat1(0); // JTR common addition for STD and CLASS ACK
  145. LineStateUpdated = 1;
  146. break;
  147. case CDC_SEND_BREAK: // Optional
  148. default:
  149. usb_RequestError();
  150. }
  151. break;
  152. default:
  153. usb_RequestError();
  154. }
  155. }
  156. void cdc_get_line_coding(void) {
  157. usb_unset_in_handler(0); // Unregister IN handler;
  158. }
  159. void cdc_set_line_coding_data(void) { // JTR handling an OUT token In the CDC stack this is the only function that handles an OUT data stage.
  160. unsigned long dwBaud, dwBaudrem;
  161. memcpy(&linecodeing, (const void *) EP0_Outbdp->BDADDR, sizeof (struct cdc_LineCodeing));
  162. dwBaud = BAUDCLOCK_FREQ / linecodeing.dwDTERate;
  163. dwBaudrem = BAUDCLOCK_FREQ % linecodeing.dwDTERate;
  164. if (linecodeing.dwDTERate > (dwBaudrem << 1))
  165. dwBaud--;
  166. UART_BAUD_setup(dwBaud);
  167. usb_unset_out_handler(0); // Unregister OUT handler; JTR serious bug fix in macro!
  168. usb_set_in_handler(0, cdc_set_line_coding_status); // JTR why bother?
  169. usb_ack_dat1(0); // JTR common addition for STD and CLASS ACK
  170. // JTR This part of the USB-CDC stack is worth highlighting
  171. // This is the only place that we have an OUT DATA packet on
  172. // EP0. At this point it has been completed. This stack unlike
  173. // the microchip stack does not have a common IN or OUT data
  174. // packet complete tail and therefore it is the responsibility
  175. // of each section to ensure that EP0 is set-up correctly for
  176. // the next setup packet.
  177. // Force EP0 OUT to the DAT0 state
  178. // after we have all our data packets.
  179. EP0_Outbdp->BDCNT = USB_EP0_BUFFER_SIZE;
  180. EP0_Outbdp->BDSTAT = UOWN | DTSEN;
  181. }
  182. void cdc_set_line_coding_status(void) {
  183. usb_unset_in_handler(0);
  184. }
  185. void cdc_set_control_line_state_status(void) {
  186. usb_unset_in_handler(0);
  187. }
  188. /*****************************************************************************/
  189. void WaitOutReady() // JTR2 added reduced overhead
  190. {
  191. while ((CDC_Outbdp->BDSTAT & UOWN));
  192. }
  193. /******************************************************************************/
  194. void WaitInReady() // JTR2 added reduced overhead
  195. {
  196. while ((CDC_Inbdp->BDSTAT & UOWN));
  197. }//end WaitInReady
  198. /******************************************************************************/
  199. BYTE getOutReady(void) {
  200. return !(CDC_Outbdp->BDSTAT & UOWN); // Do we have a packet from host?
  201. }
  202. /******************************************************************************/
  203. BYTE getInReady(void) {
  204. return !(CDC_Inbdp->BDSTAT & UOWN); // Is the CDC In buffer ready?
  205. }
  206. /******************************************************************************/
  207. BYTE getda_cdc(void) {
  208. CDCFunctionError = 0;
  209. WaitOutReady();
  210. if ((IsOutBufferA & 1)) {
  211. OutPtr = &cdc_Out_bufferA[0];
  212. CDC_Outbdp->BDADDR = &cdc_Out_bufferB[0];
  213. } else {
  214. OutPtr = &cdc_Out_bufferB[0];
  215. CDC_Outbdp->BDADDR = &cdc_Out_bufferA[0];
  216. }
  217. IsOutBufferA ^= 0xFF;
  218. cdc_Out_len = CDC_Outbdp->BDCNT;
  219. CDC_Outbdp->BDCNT = CDC_BUFFER_SIZE;
  220. CDC_Outbdp->BDSTAT = ((CDC_Outbdp->BDSTAT ^ DTS) & DTS) | UOWN | DTSEN;
  221. #ifndef USB_INTERRUPTS
  222. usb_handler();
  223. #endif
  224. return cdc_Out_len;
  225. }//end getCDC_Out_ArmNext
  226. BYTE putda_cdc(BYTE count) {
  227. // CDCFunctionError = 0;
  228. // WaitInReady();
  229. while ((CDC_Inbdp->BDSTAT & UOWN));
  230. if (IsInBufferA) {
  231. CDC_Inbdp->BDADDR = cdc_In_bufferA;
  232. InPtr = cdc_In_bufferB;
  233. } else {
  234. CDC_Inbdp->BDADDR = cdc_In_bufferB;
  235. InPtr = cdc_In_bufferA;
  236. }
  237. CDC_Inbdp->BDCNT = count;
  238. CDC_Inbdp->BDSTAT = ((CDC_Inbdp->BDSTAT ^ DTS) & DTS) | UOWN | DTSEN;
  239. IsInBufferA ^= 0xFF;
  240. #ifndef USB_INTERRUPTS
  241. usb_handler();
  242. #endif
  243. return 0; //CDCFunctionError;
  244. }
  245. void SendZLP(void) {
  246. putda_cdc(0);
  247. }
  248. /******************************************************************************/
  249. void CDC_Flush_In_Now(void) {
  250. if (cdc_In_len > 0) {
  251. while (!getInReady());
  252. putda_cdc(cdc_In_len);
  253. if (cdc_In_len == CDC_BUFFER_SIZE) {
  254. ZLPpending = 1;
  255. } else {
  256. ZLPpending = 0;
  257. }
  258. cdc_In_len = 0;
  259. cdc_timeout_count = 0;
  260. }
  261. }
  262. /******************************************************************************/
  263. void CDCFlushOnTimeout(void) {
  264. if (cdc_timeout_count >= CDC_FLUSH_MS) { // For timeout value see: cdc_config.h -> [hardware] -> CDC_FLUSH_MS
  265. if (cdc_In_len > 0) {
  266. if ((lock == 0) && getInReady()) {
  267. putda_cdc(cdc_In_len);
  268. if (cdc_In_len == CDC_BUFFER_SIZE) {
  269. ZLPpending = 1;
  270. } else {
  271. ZLPpending = 0;
  272. }
  273. cdc_In_len = 0;
  274. cdc_timeout_count = 0;
  275. }
  276. } else if (ZLPpending) {
  277. putda_cdc(0);
  278. ZLPpending = 0;
  279. cdc_timeout_count = 0;
  280. }
  281. } else {
  282. cdc_timeout_count++;
  283. }
  284. }
  285. /******************************************************************************/
  286. void putc_cdc(BYTE c) {
  287. lock = 1; // Stops CDCFlushOnTimeout() from sending per chance it is on interrupts.
  288. *InPtr = c;
  289. InPtr++;
  290. cdc_In_len++;
  291. ZLPpending = 0;
  292. if (cdc_In_len == CDC_BUFFER_SIZE) {
  293. putda_cdc(cdc_In_len); // This will stall tranfers if both buffers are full then return when a buffer is available.
  294. cdc_In_len = 0;
  295. ZLPpending = 1; // timeout handled in the SOF handler below.
  296. }
  297. lock = 0;
  298. cdc_timeout_count = 0; //setup timer to throw data if the buffer doesn't fill
  299. }
  300. /******************************************************************************/
  301. // Waits for a byte to be available and returns that byte as a
  302. // function return value. The byte is removed from the CDC OUT queue.
  303. // No return count is required as this function always returns one byte.
  304. BYTE getc_cdc(void) { // Must be used only in double buffer mode.
  305. BYTE c = 0;
  306. if (cdc_Out_len == 0) {
  307. do {
  308. cdc_Out_len = getda_cdc();
  309. } while (cdc_Out_len == 0); // Skip any ZLP
  310. }
  311. c = *OutPtr;
  312. OutPtr++;
  313. cdc_Out_len--;
  314. return c;
  315. }
  316. /******************************************************************************/
  317. // Checks to see if there is a byte available in the CDC buffer.
  318. // If so, it returns that byte at the dereferenced pointer *C
  319. // and the function returns a count of 1. The byte is effectively
  320. // removed from the queue.
  321. // IF no byte is available function returns immediately with a count of zero.
  322. BYTE poll_getc_cdc(BYTE * c) { // Must be used only in double buffer mode.
  323. if (cdc_Out_len) { // Do we have a byte waiting?
  324. *c = *OutPtr; // pass it on and adjust OutPtr and count
  325. OutPtr++;
  326. cdc_Out_len--;
  327. return 1; // Return byte count, always one.
  328. }
  329. if (getOutReady()) { // No byte in queue check for new arrivals.
  330. cdc_Out_len = getda_cdc();
  331. if (cdc_Out_len) {
  332. *c = *OutPtr;
  333. OutPtr++;
  334. cdc_Out_len--;
  335. return 1;
  336. }
  337. }
  338. return 0;
  339. }
  340. /******************************************************************************/
  341. // Checks (PEEKS) to see if there is a byte available in the CDC buffer.
  342. // If so, it returns that byte at the dereferenced pointer *C
  343. // and the function returns a count of 1. The byte however is NOT
  344. // removed from the queue and can still be read with the poll_getc_cdc()
  345. // and getc_cdc() functions that will remove it from the queue.
  346. // IF no byte is available function returns immediately with a count of zero.
  347. BYTE peek_getc_cdc(BYTE * c) { // Must be used only in double buffer mode.
  348. if (cdc_Out_len) {
  349. *c = *OutPtr;
  350. return 1;
  351. }
  352. if (getOutReady()) {
  353. cdc_Out_len = getda_cdc();
  354. if (cdc_Out_len) {
  355. *c = *OutPtr;
  356. return 1;
  357. }
  358. }
  359. return 0;
  360. }