usb_framework.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /***********************************************************************************
  2. Filename: usb_framework.c
  3. Description: USB library common functionality.
  4. ***********************************************************************************/
  5. /// \addtogroup module_usb_framework
  6. /// @{
  7. #define USBFRAMEWORK_C ///< Modifies the behavior of "EXTERN" in usb_framework.h
  8. #include "usb_firmware_library_headers.h"
  9. #include "usb_board_cfg.h"
  10. // Function pointer used by usbfwSetupHandler()
  11. static VFPTR __data ProcessFunc;
  12. /** \brief Initializes the USB framework
  13. *
  14. * This function should be called when the microcontroller is ready to accept USB traffic. It enables the
  15. * USB peripheral unit and enables the pull-up resistor on the D+ line. Endpoint status, current
  16. * configuration value, etc. are initialized and evenetually re-initialized in the
  17. * \ref usbfwResetHandler() function.
  18. */
  19. void usbfwInit(void)
  20. {
  21. // Set default values
  22. usbfwData.selfPowered = (usbdpGetConfigurationDesc(1, 0)->bmAttributes & 0x40) ? TRUE : FALSE;
  23. usbfwData.remoteWakeup = FALSE;
  24. HAL_USB_ENABLE();
  25. // Enable Resume Interrupt
  26. HAL_USB_RESUME_INT_ENABLE();
  27. } // usbfwInit
  28. /** \brief Handles USB reset signalling
  29. *
  30. * This function should be called, either from the USB interrupt or the main loop, when the \c USBCIF.RST
  31. * flag has been set. Keep in mind that all bits in \c USBCIF register are cleared when the register is
  32. * read. The function puts the device into the default state (not yet addressed), and puts all endpoints
  33. * (except EP0) into the \ref EP_HALT state
  34. */
  35. void usbfwResetHandler(void)
  36. {
  37. // Reset the USB state
  38. usbfwData.usbState = DEV_DEFAULT;
  39. usbfwData.configurationValue = 0;
  40. // Reset all endpoints
  41. usbfwData.ep0Status = EP_IDLE;
  42. usbfwSetAllEpStatus(EP_HALT);
  43. // Reset last function pointer
  44. ProcessFunc = NULL;
  45. } // usbfwResetHandler
  46. /** \brief USB Setup Handler
  47. *
  48. * This function should be called either from the USB interrupt or the main loop when the \c USBIIF.EP0IF
  49. * flag has been set. Keep in mind that all bits in \c USBIIF register are cleared when the register is
  50. * read. A detailed description of the framework is found in the \ref section_setup_handler_usage
  51. * section.
  52. *
  53. * \note The USB header data is always little-endian, so if a big-endian compiler is used (such as Keil
  54. * C51), the 16-bit values in the \ref usbSetupHeader must be flipped before they are used.
  55. */
  56. void usbfwSetupHandler(void)
  57. {
  58. uint8 controlReg;
  59. uint8 bytesNow;
  60. uint8 oldEndpoint;
  61. // Save the old index setting, then select endpoint 0 and fetch the control register
  62. oldEndpoint = USBFW_GET_SELECTED_ENDPOINT();
  63. USBFW_SELECT_ENDPOINT(0);
  64. controlReg = USBCS0;
  65. // The last transfer was ended prematurely by a new SETUP packet
  66. if (controlReg & USBCS0_SETUP_END) {
  67. USBCS0 = USBCS0_CLR_SETUP_END;
  68. usbfwData.ep0Status = EP_CANCEL;
  69. if (ProcessFunc) ProcessFunc();
  70. usbfwData.ep0Status = EP_IDLE;
  71. }
  72. // A STALL handshake was transmitted to the PC
  73. if (controlReg & USBCS0_SENT_STALL) {
  74. USBCS0 = 0x00;
  75. usbfwData.ep0Status = EP_IDLE;
  76. }
  77. // Receive OUT packets
  78. if (usbfwData.ep0Status == EP_RX) {
  79. // Read FIFO
  80. bytesNow = USBCNT0;
  81. usbfwReadFifo(&USBF0, bytesNow, usbSetupData.pBuffer);
  82. usbSetupData.bytesLeft -= bytesNow;
  83. usbSetupData.pBuffer += bytesNow;
  84. // Arm the endpoint
  85. USBCS0 = usbSetupData.bytesLeft ? USBCS0_CLR_OUTPKT_RDY : (USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END);
  86. // Make a call to the appropriate request handler when done
  87. if (usbSetupData.bytesLeft == 0) {
  88. if (ProcessFunc) ProcessFunc();
  89. usbfwData.ep0Status = EP_IDLE;
  90. }
  91. // Return here since nothing more will happen until the next interrupt
  92. USBFW_SELECT_ENDPOINT(oldEndpoint);
  93. return;
  94. // Let the application handle the reception
  95. } else if (usbfwData.ep0Status == EP_MANUAL_RX) {
  96. ProcessFunc();
  97. }
  98. // Receive SETUP header
  99. if (usbfwData.ep0Status == EP_IDLE) {
  100. if (controlReg & USBCS0_OUTPKT_RDY) {
  101. usbfwReadFifo(&USBF0, 8, (uint8 __xdata *) &usbSetupHeader);
  102. // Handle control transfers individually
  103. ProcessFunc = NULL;
  104. switch (usbSetupHeader.requestType & (RT_MASK_TYPE | RT_MASK_DIR)) {
  105. // Standard requests with data from the host (OUT)
  106. case RT_STD_OUT:
  107. switch (usbSetupHeader.request) {
  108. case SET_ADDRESS: usbsrSetAddress(); break;
  109. case SET_FEATURE: usbsrSetFeature(); break;
  110. case CLEAR_FEATURE: usbsrClearFeature(); break;
  111. case SET_CONFIGURATION: usbsrSetConfiguration(); break;
  112. case SET_INTERFACE: usbsrSetInterface(); break;
  113. case SET_DESCRIPTOR: /*usbsrHookSetDescriptor(); break; - unsupported */
  114. default: usbfwData.ep0Status = EP_STALL; break;
  115. }
  116. break;
  117. // Standard requests with data to the host (IN)
  118. case RT_STD_IN:
  119. switch (usbSetupHeader.request) {
  120. case GET_STATUS: usbsrGetStatus(); break;
  121. case GET_DESCRIPTOR: usbsrGetDescriptor(); break;
  122. case GET_CONFIGURATION: usbsrGetConfiguration(); break;
  123. case GET_INTERFACE: usbsrGetInterface(); break;
  124. case SYNCH_FRAME: /*usbsrHookSynchFrame(); break; - unsupported */
  125. default: usbfwData.ep0Status = EP_STALL; break;
  126. }
  127. break;
  128. // Vendor requests
  129. case RT_VEND_OUT:
  130. ProcessFunc = usbvrHookProcessOut; usbvrHookProcessOut();
  131. break;
  132. case RT_VEND_IN:
  133. ProcessFunc = usbvrHookProcessIn; usbvrHookProcessIn();
  134. break;
  135. // Class requests
  136. case RT_CLASS_OUT:
  137. ProcessFunc = usbcrHookProcessOut; usbcrHookProcessOut();
  138. break;
  139. case RT_CLASS_IN:
  140. ProcessFunc = usbcrHookProcessIn; usbcrHookProcessIn();
  141. break;
  142. // Unrecognized request: Stall the endpoint
  143. default:
  144. usbfwData.ep0Status = EP_STALL;
  145. break;
  146. }
  147. // Arm/stall the endpoint
  148. USBCS0 = (usbfwData.ep0Status == EP_STALL) ? (USBCS0_CLR_OUTPKT_RDY | USBCS0_SEND_STALL) : USBCS0_CLR_OUTPKT_RDY;
  149. }
  150. }
  151. // Transmit IN packets
  152. if (usbfwData.ep0Status == EP_TX) {
  153. controlReg = USBCS0_INPKT_RDY;
  154. // The last frame should contain 0 to (EP0_PACKET_SIZE - 1) bytes
  155. if (usbSetupData.bytesLeft < EP0_PACKET_SIZE) {
  156. bytesNow = usbSetupData.bytesLeft;
  157. controlReg |= USBCS0_DATA_END;
  158. // All other packets should have the maximum length
  159. } else {
  160. bytesNow = EP0_PACKET_SIZE;
  161. }
  162. // Load the FIFO and move the pointer
  163. usbfwWriteFifo(&USBF0, bytesNow, usbSetupData.pBuffer);
  164. usbSetupData.pBuffer += bytesNow;
  165. usbSetupData.bytesLeft -= bytesNow;
  166. // Arm the FIFO (even for a zero-length packet)
  167. USBCS0 = controlReg;
  168. // Make a call to the appropriate request handler when done
  169. if (bytesNow < EP0_PACKET_SIZE) {
  170. if (ProcessFunc) ProcessFunc();
  171. usbfwData.ep0Status = EP_IDLE;
  172. }
  173. // Let the application handle the transmission
  174. } else if (usbfwData.ep0Status == EP_MANUAL_TX) {
  175. ProcessFunc();
  176. }
  177. // Restore the old index setting
  178. USBFW_SELECT_ENDPOINT(oldEndpoint);
  179. } // usbfwSetupHandler
  180. /** \brief Changes the state of endpoint 1-5 IN/OUT
  181. *
  182. * This is an internal function used by the library.
  183. *
  184. * \param[in] status
  185. * The new status for each endpoint
  186. */
  187. void usbfwSetAllEpStatus(EP_STATUS status)
  188. {
  189. uint8 n;
  190. for (n = 0; n < sizeof(usbfwData.pEpInStatus); n++)
  191. usbfwData.pEpInStatus[n] = status;
  192. for (n = 0; n < sizeof(usbfwData.pEpOutStatus); n++)
  193. usbfwData.pEpOutStatus[n] = status;
  194. } // usbfwSetAllEpStatus
  195. /** \brief Reads from the selected OUT endpoint FIFO, without using DMA
  196. *
  197. * The FIFO must be re-armed after reading it empty (using the \ref USBFW_ARM_OUT_ENDPOINT() macro). This
  198. * is not necessary when flushing the FIFO.
  199. *
  200. * \param[in] *pFifo
  201. * Pointer to the FIFO (\c &USBFx)
  202. * \param[in] count
  203. * The number of bytes to read
  204. * \param[in] *pData
  205. * A pointer to the storage location for the read data (in any memory space)
  206. */
  207. void usbfwReadFifo(uint8 volatile __xdata *pFifo, uint8 count, void __generic *pData)
  208. {
  209. uint8 __generic *pTemp = pData;
  210. if (count) {
  211. do {
  212. *(pTemp++) = *pFifo;
  213. } while (--count);
  214. }
  215. } // usbfwReadFifo
  216. /** \brief Writes to the selected IN endpoint FIFO, without using DMA
  217. *
  218. * Note that the FIFO must be armed in order to be transmitted (using the \ref USBFW_ARM_IN_ENDPOINT()
  219. * macro).
  220. *
  221. * \param[in] *pFifo
  222. * Pointer to the FIFO (\c &USBFx)
  223. * \param[in] count
  224. * The number of bytes to write
  225. * \param[in] *pData
  226. * A pointer to the data to be written (from any memory space)
  227. */
  228. void usbfwWriteFifo(uint8 volatile __xdata *pFifo, uint8 count, void __generic *pData)
  229. {
  230. uint8 __generic *pTemp = pData;
  231. if (count) {
  232. do {
  233. *pFifo = *(pTemp++);
  234. } while (--count);
  235. }
  236. } // usbfwWriteFifo
  237. /// @}
  238. /*
  239. +------------------------------------------------------------------------------
  240. | Copyright 2004-2007 Texas Instruments Incorporated. All rights reserved.
  241. |
  242. | IMPORTANT: Your use of this Software is limited to those specific rights
  243. | granted under the terms of a software license agreement between the user who
  244. | downloaded the software, his/her employer (which must be your employer) and
  245. | Texas Instruments Incorporated (the "License"). You may not use this Software
  246. | unless you agree to abide by the terms of the License. The License limits
  247. | your use, and you acknowledge, that the Software may not be modified, copied
  248. | or distributed unless embedded on a Texas Instruments microcontroller or used
  249. | solely and exclusively in conjunction with a Texas Instruments radio
  250. | frequency transceiver, which is integrated into your product. Other than for
  251. | the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  252. | works of, modify, distribute, perform, display or sell this Software and/or
  253. | its documentation for any purpose.
  254. |
  255. | YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  256. | PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  257. | INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  258. | NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  259. | TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  260. | NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  261. | LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING
  262. | BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
  263. | CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
  264. | SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  265. | (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  266. |
  267. | Should you have any questions regarding your right to use this Software,
  268. | contact Texas Instruments Incorporated at www.TI.com.
  269. |
  270. +------------------------------------------------------------------------------
  271. */