1 /* --COPYRIGHT--,BSD\r
2 * Copyright (c) 2014, Texas Instruments Incorporated\r
3 * All rights reserved.\r
4 *\r
5 * Redistribution and use in source and binary forms, with or without\r
6 * modification, are permitted provided that the following conditions\r
7 * are met:\r
8 *\r
9 * * Redistributions of source code must retain the above copyright\r
10 * notice, this list of conditions and the following disclaimer.\r
11 *\r
12 * * Redistributions in binary form must reproduce the above copyright\r
13 * notice, this list of conditions and the following disclaimer in the\r
14 * documentation and/or other materials provided with the distribution.\r
15 *\r
16 * * Neither the name of Texas Instruments Incorporated nor the names of\r
17 * its contributors may be used to endorse or promote products derived\r
18 * from this software without specific prior written permission.\r
19 *\r
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
31 * --/COPYRIGHT--*/\r
32 /** @file UsbCdc.c\r
33 * @brief Contains APIs related to CDC (Virtual COMport) device class\r
34 */\r
35 \r
36 \r
37 //\r
38 //! \cond\r
39 //\r
40 \r
41 /*\r
42 * ======== UsbCdc.c ========\r
43 */\r
44 #include <descriptors.h>\r
45 \r
46 #ifdef _CDC_\r
47 \r
48 \r
49 #include "../USB_Common/device.h"\r
50 #include "../USB_Common/defMSP430USB.h"\r
51 #include "../USB_Common/usb.h" //USB-specific Data Structures\r
52 #include "../USB_CDC_API/UsbCdc.h"\r
53 \r
54 #include <string.h>\r
55 \r
56 //Local Macros\r
57 #define INTFNUM_OFFSET(X) (X - CDC0_INTFNUM) //Get the CDC offset\r
58 \r
59 static struct _CdcControl {\r
60 uint32_t lBaudrate;\r
61 uint8_t bDataBits;\r
62 uint8_t bStopBits;\r
63 uint8_t bParity;\r
64 } CdcControl[CDC_NUM_INTERFACES];\r
65 \r
66 static struct _CdcWrite {\r
67 uint16_t nCdcBytesToSend; //holds counter of bytes to be sent\r
68 uint16_t nCdcBytesToSendLeft; //holds counter how many bytes is still to be sent\r
69 const uint8_t* pUsbBufferToSend; //holds the buffer with data to be sent\r
70 uint8_t bCurrentBufferXY; //is 0 if current buffer to write data is X, or 1 if current buffer is Y\r
71 uint8_t bZeroPacketSent; //= FALSE;\r
72 uint8_t last_ByteSend;\r
73 } CdcWriteCtrl[CDC_NUM_INTERFACES];\r
74 \r
75 static struct _CdcRead {\r
76 uint8_t *pUserBuffer; //holds the current position of user's receiving buffer. If NULL- no receiving\r
77 //operation started\r
78 uint8_t *pCurrentEpPos; //current positon to read of received data from curent EP\r
79 uint16_t nBytesToReceive; //holds how many bytes was requested by receiveData() to receive\r
80 uint16_t nBytesToReceiveLeft; //holds how many bytes is still requested by receiveData() to receive\r
81 uint8_t * pCT1; //holds current EPBCTxx register\r
82 uint8_t * pCT2; //holds next EPBCTxx register\r
83 uint8_t * pEP2; //holds addr of the next EP buffer\r
84 uint8_t nBytesInEp; //how many received bytes still available in current EP\r
85 uint8_t bCurrentBufferXY; //indicates which buffer is used by host to transmit data via OUT endpoint3\r
86 } CdcReadCtrl[CDC_NUM_INTERFACES];\r
87 \r
88 #ifdef BRIDGE_CDC_PRESENT\r
89 \r
90 static struct _CdcBridgeCtrl {\r
91 uint8_t *uartRx;\r
92 uint8_t *uartTx;\r
93 uint8_t *uartIFG;\r
94 uint16_t *usbToUartDmaChSz;\r
95 uint16_t *usbToUartDmaChCtl;\r
96 uint8_t ctsState;\r
97 } CdcBridgeCtrl;\r
98 \r
99 #endif\r
100 \r
101 extern uint16_t wUsbEventMask;\r
102 \r
103 //function pointers\r
104 extern void *(*USB_TX_memcpy)(void * dest, const void * source, size_t count);\r
105 extern void *(*USB_RX_memcpy)(void * dest, const void * source, size_t count);\r
106 \r
107 \r
108 /*----------------------------------------------------------------------------+\r
109 | Global Variables |\r
110 +----------------------------------------------------------------------------*/\r
111 \r
112 extern __no_init tEDB __data16 tInputEndPointDescriptorBlock[];\r
113 extern __no_init tEDB __data16 tOutputEndPointDescriptorBlock[];\r
114 \r
115 \r
116 void CdcResetData ()\r
117 {\r
118 int16_t i;\r
119 \r
120 //indicates which buffer is used by host to transmit data via OUT endpoint3 - X buffer is first\r
121 //CdcReadCtrl[intfIndex].bCurrentBufferXY = X_BUFFER;\r
122 \r
123 memset(&CdcWriteCtrl, 0, sizeof(CdcWriteCtrl));\r
124 memset(&CdcReadCtrl, 0, sizeof(CdcReadCtrl));\r
125 memset(&CdcControl, 0, sizeof(CdcControl));\r
126 \r
127 for (i = 0; i < CDC_NUM_INTERFACES; i++){\r
128 CdcControl[i].bDataBits = 8;\r
129 }\r
130 }\r
131 \r
132 //\r
133 //! \endcond\r
134 //\r
135 \r
136 //*****************************************************************************\r
137 //\r
138 //! Begins a Send Operation to the USB Host.\r
139 //!\r
140 //! \param *data is an array of data to be sent.\r
141 //! \param size is the number of bytes to be sent, starting from address\r
142 //! \b data.\r
143 //! \param intfNum selects which data should be transmitted over.\r
144 //!\r
145 //! Initiates sending of a user buffer over CDC interface \b intfNum, of size\r
146 //! \b size and starting at address \b data. If \b size is larger than the\r
147 //! packet size, the function handles all packetization and buffer management.\r
148 //! \b size has no inherent upper limit (beyond being a 16-bit value).\r
149 //!\r
150 //! In most cases where a send operation is successfully started, the function\r
151 //! will return \b kUSBCDC_sendStarted. A send operation is said to be underway. At\r
152 //! some point, either before or after the function returns, the send operation\r
153 //! will complete, barring any events that would preclude it. (Even if the\r
154 //! operation completes before the function returns, the return code will still\r
155 //! be \b kUSBCDC_sendStarted.)\r
156 //! If the bus is not connected when the function is called, the function\r
157 //! returns \b kUSBCDC_busNotAvailable, and no operation is begun. If \b size is 0,\r
158 //! the function returns \b kUSBCDC_generalError. If a previous send operation is\r
159 //! already underway for this data interface, the function returns with\r
160 //! \b kUSBCDC_intfBusyError.\r
161 //!\r
162 //! USB includes low-level mechanisms that ensure valid transmission of data.\r
163 //!\r
164 //! See Sec. 7.2 of \e "Programmer's Guide: MSP430 USB API Stack for CDC/PHDC/HID/MSC" for a detailed discussion of\r
165 //! send operations.\r
166 //!\r
167 //! \return Any of the following:\r
168 //! - \b kUSBCDC_sendStarted: a send operation was successfully\r
169 //! started\r
170 //! - \b kUSBCDC_intfBusyError: a previous send operation is\r
171 //! underway\r
172 //! - \b kUSBCDC_busNotAvailable: the bus is either suspended or\r
173 //! disconnected\r
174 //! - \b kUSBCDC_generalError: \b size was zero, or other error\r
175 //\r
176 //*****************************************************************************\r
177 \r
178 uint8_t USBCDC_sendData (const uint8_t* data, uint16_t size, uint8_t intfNum)\r
179 {\r
180 uint8_t edbIndex;\r
181 uint16_t state;\r
182 \r
183 edbIndex = stUsbHandle[intfNum].edb_Index;\r
184 \r
185 if (size == 0){\r
186 return (kUSBCDC_generalError);\r
187 }\r
188 \r
189 state = usbDisableInEndpointInterrupt(edbIndex);\r
190 \r
191 //do not access USB memory if suspended (PLL uce BUS_ERROR\r
192 if ((bFunctionSuspended) ||\r
193 (bEnumerationStatus != ENUMERATION_COMPLETE)){\r
194 //data can not be read because of USB suspended\r
195 usbRestoreInEndpointInterrupt(state); //restore interrupt status\r
196 return (kUSBCDC_busNotAvailable);\r
197 }\r
198 \r
199 if (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft != 0){\r
200 //the USB still sends previous data, we have to wait\r
201 usbRestoreInEndpointInterrupt(state); //restore interrupt status\r
202 return (kUSBCDC_intfBusyError);\r
203 }\r
204 \r
205 //This function generate the USB interrupt. The data will be sent out from interrupt\r
206 \r
207 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSend = size;\r
208 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft = size;\r
209 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].pUsbBufferToSend = data;\r
210 \r
211 //trigger Endpoint Interrupt - to start send operation\r
212 USBIEPIFG |= 1 << (edbIndex + 1); //IEPIFGx;\r
213 \r
214 usbRestoreInEndpointInterrupt(state);\r
215 \r
216 return (kUSBCDC_sendStarted);\r
217 }\r
218 \r
219 //\r
220 //! \cond\r
221 //\r
222 \r
223 #define EP_MAX_PACKET_SIZE_CDC 0x40\r
224 \r
225 //this function is used only by USB interrupt\r
226 int16_t CdcToHostFromBuffer (uint8_t intfNum)\r
227 {\r
228 uint8_t byte_count, nTmp2;\r
229 uint8_t * pEP1;\r
230 uint8_t * pEP2;\r
231 uint8_t * pCT1;\r
232 uint8_t * pCT2;\r
233 uint8_t bWakeUp = FALSE; //TRUE for wake up after interrupt\r
234 uint8_t edbIndex;\r
235 \r
236 edbIndex = stUsbHandle[intfNum].edb_Index;\r
237 \r
238 if (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft == 0){ //do we have somtething to send?\r
239 if (!CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].bZeroPacketSent){ //zero packet was not yet sent\r
240 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].bZeroPacketSent = TRUE;\r
241 \r
242 if (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].last_ByteSend ==\r
243 EP_MAX_PACKET_SIZE_CDC){\r
244 if (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY ==\r
245 X_BUFFER){\r
246 if (tInputEndPointDescriptorBlock[edbIndex].bEPBCTX &\r
247 EPBCNT_NAK){\r
248 tInputEndPointDescriptorBlock[edbIndex].bEPBCTX = 0;\r
249 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY\r
250 = Y_BUFFER; //switch buffer\r
251 }\r
252 } else {\r
253 if (tInputEndPointDescriptorBlock[edbIndex].bEPBCTY &\r
254 EPBCNT_NAK){\r
255 tInputEndPointDescriptorBlock[edbIndex].bEPBCTY = 0;\r
256 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY\r
257 = X_BUFFER; //switch buffer\r
258 }\r
259 }\r
260 }\r
261 \r
262 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSend = 0; //nothing to send\r
263 \r
264 //call event callback function\r
265 if (wUsbEventMask & kUSB_sendCompletedEvent){\r
266 bWakeUp = USBCDC_handleSendCompleted(intfNum);\r
267 }\r
268 } //if (!bSentZeroPacket)\r
269 \r
270 return (bWakeUp);\r
271 }\r
272 \r
273 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].bZeroPacketSent = FALSE; //zero packet will be not sent: we have data\r
274 \r
275 if (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY == X_BUFFER){\r
276 //this is the active EP buffer\r
277 pEP1 = (uint8_t*)stUsbHandle[intfNum].iep_X_Buffer;\r
278 pCT1 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTX;\r
279 \r
280 //second EP buffer\r
281 pEP2 = (uint8_t*)stUsbHandle[intfNum].iep_Y_Buffer;\r
282 pCT2 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTY;\r
283 } else {\r
284 //this is the active EP buffer\r
285 pEP1 = (uint8_t*)stUsbHandle[intfNum].iep_Y_Buffer;\r
286 pCT1 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTY;\r
287 \r
288 //second EP buffer\r
289 pEP2 = (uint8_t*)stUsbHandle[intfNum].iep_X_Buffer;\r
290 pCT2 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTX;\r
291 }\r
292 \r
293 //how many byte we can send over one endpoint buffer\r
294 byte_count =\r
295 (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft >\r
296 EP_MAX_PACKET_SIZE_CDC) ? EP_MAX_PACKET_SIZE_CDC : CdcWriteCtrl[\r
297 INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft;\r
298 nTmp2 = *pCT1;\r
299 \r
300 if (nTmp2 & EPBCNT_NAK){\r
301 USB_TX_memcpy(pEP1, CdcWriteCtrl[INTFNUM_OFFSET(\r
302 intfNum)].pUsbBufferToSend,\r
303 byte_count); //copy data into IEP3 X or Y buffer\r
304 *pCT1 = byte_count; //Set counter for usb In-Transaction\r
305 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY =\r
306 (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY + 1) & 0x01; //switch buffer\r
307 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft -= byte_count;\r
308 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].pUsbBufferToSend += byte_count; //move buffer pointer\r
309 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].last_ByteSend = byte_count;\r
310 \r
311 //try to send data over second buffer\r
312 nTmp2 = *pCT2;\r
313 if ((CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft > 0) && //do we have more data to send?\r
314 (nTmp2 & EPBCNT_NAK)){ //if the second buffer is free?\r
315 //how many byte we can send over one endpoint buffer\r
316 byte_count =\r
317 (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft >\r
318 EP_MAX_PACKET_SIZE_CDC) ? EP_MAX_PACKET_SIZE_CDC :\r
319 CdcWriteCtrl[\r
320 INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft;\r
321 \r
322 USB_TX_memcpy(pEP2, CdcWriteCtrl[INTFNUM_OFFSET(\r
323 intfNum)].pUsbBufferToSend,\r
324 byte_count); //copy data into IEP3 X or Y buffer\r
325 *pCT2 = byte_count; //Set counter for usb In-Transaction\r
326 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY =\r
327 (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY +\r
328 1) & 0x01; //switch buffer\r
329 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft -=\r
330 byte_count;\r
331 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].pUsbBufferToSend +=\r
332 byte_count; //move buffer pointer\r
333 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].last_ByteSend = byte_count;\r
334 }\r
335 }\r
336 return (bWakeUp);\r
337 }\r
338 \r
339 //\r
340 //! \endcond\r
341 //\r
342 \r
343 //*****************************************************************************\r
344 //\r
345 //! Aborts an Active Send Operation.\r
346 //!\r
347 //! \param size is the number of bytes that were sent prior to the abort action.\r
348 //! \param intfNum is the data interface for which the send should be aborted.\r
349 //!\r
350 //! Aborts an active send operation on data interface \b intfNum. Returns the\r
351 //! number of bytes that were sent prior to the abort, in \b size.\r
352 //!\r
353 //! An application may choose to call this function if sending failed, due to\r
354 //! factors such as:\r
355 //! - a surprise removal of the bus\r
356 //! - a USB suspend event\r
357 //! - any send operation that extends longer than desired (perhaps due\r
358 //! to no open COM port on the host.)\r
359 //!\r
360 //! \return \b kUSB_succeed\r
361 //\r
362 //*****************************************************************************\r
363 \r
364 uint8_t USBCDC_abortSend (uint16_t* size, uint8_t intfNum)\r
365 {\r
366 uint8_t edbIndex;\r
367 uint16_t state;\r
368 \r
369 edbIndex = stUsbHandle[intfNum].edb_Index;\r
370 \r
371 state = usbDisableInEndpointInterrupt(edbIndex); //disable interrupts - atomic operation\r
372 \r
373 *size =\r
374 (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSend -\r
375 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft);\r
376 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSend = 0;\r
377 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft = 0;\r
378 \r
379 usbRestoreInEndpointInterrupt(state);\r
380 return (kUSB_succeed);\r
381 }\r
382 \r
383 //\r
384 //! \cond\r
385 //\r
386 \r
387 //This function copies data from OUT endpoint into user's buffer\r
388 //Arguments:\r
389 //pEP - pointer to EP to copy from\r
390 //pCT - pointer to pCT control reg\r
391 //\r
392 void CopyUsbToBuff (uint8_t* pEP, uint8_t* pCT, uint8_t intfNum)\r
393 {\r
394 uint8_t nCount;\r
395 \r
396 //how many byte we can get from one endpoint buffer\r
397 nCount =\r
398 (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft >\r
399 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp) ? CdcReadCtrl[\r
400 INTFNUM_OFFSET(intfNum)].nBytesInEp : CdcReadCtrl[INTFNUM_OFFSET(\r
401 intfNum)].\r
402 nBytesToReceiveLeft;\r
403 \r
404 USB_RX_memcpy(CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer, pEP, nCount); //copy data from OEP3 X or Y buffer\r
405 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft -= nCount;\r
406 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer += nCount; //move buffer pointer\r
407 //to read rest of data next time from this place\r
408 \r
409 if (nCount == CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp){ //all bytes are copied from receive buffer?\r
410 //switch current buffer\r
411 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY =\r
412 (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY + 1) & 0x01;\r
413 \r
414 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = 0;\r
415 \r
416 //clear NAK, EP ready to receive data\r
417 *pCT = 0x00;\r
418 } else {\r
419 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp -= nCount;\r
420 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos = pEP + nCount;\r
421 }\r
422 }\r
423 \r
424 //\r
425 //! \endcond\r
426 //\r
427 \r
428 //*****************************************************************************\r
429 //\r
430 //! Begins a Receive Operation from the USB Host.\r
431 //!\r
432 //! \param *data is an array to contain the data received.\r
433 //! \param size is the number of bytes to be received.\r
434 //! \param intfNum is which data interface to receive from.\r
435 //!\r
436 //! Receives \b size bytes over CDC interface \b intfNum into memory starting at\r
437 //! address \b data. \b size has no inherent upper limit (beyond being a 16-bit\r
438 //! value).\r
439 //!\r
440 //! The function may return with \b kUSBCDC_receiveStarted, indicating that a\r
441 //! receive operation is underway. The operation completes when \b size bytes\r
442 //! are received. The application should ensure that the data memory buffer be\r
443 //! available during the whole of the receive operation.\r
444 //!\r
445 //! The function may also return with \b kUSBCDC_receiveCompleted. This means that\r
446 //! the receive operation was complete by the time the function returned.\r
447 //!\r
448 //! If the bus is not connected when the function is called, the function\r
449 //! returns \b kUSBCDC_busNotAvailable, and no operation is begun. If \b size is 0,\r
450 //! the function returns \b kUSBCDC_generalError. If a previous receive operation\r
451 //! is already underway for this data interface, the function returns\r
452 //! \b kUSBCDC_intfBusyError.\r
453 //!\r
454 //! USB includes low-level mechanisms that ensure valid transmission of data.\r
455 //!\r
456 //! See Sec. 7.2 of \e "Programmer's Guide: MSP430 USB API Stack for CDC/PHDC/HID/MSC" for a detailed discussion of\r
457 //! receive operations.\r
458 //!\r
459 //! \return Any of the following:\r
460 //! - \b kUSBCDC_receiveStarted: A receive operation has been\r
461 //! succesfully started.\r
462 //! - \b kUSBCDC_receiveCompleted: The receive operation is already\r
463 //! completed.\r
464 //! - \b kUSBCDC_intfBusyError: a previous receive operation is\r
465 //! underway.\r
466 //! - \b kUSBCDC_busNotAvailable: the bus is either suspended or\r
467 //! disconnected.\r
468 //! - \b kUSBCDC_generalError: \b size was zero, or other error.\r
469 //\r
470 //*****************************************************************************\r
471 \r
472 uint8_t USBCDC_receiveData (uint8_t* data, uint16_t size, uint8_t intfNum)\r
473 {\r
474 uint8_t nTmp1;\r
475 uint8_t edbIndex;\r
476 uint16_t state;\r
477 \r
478 edbIndex = stUsbHandle[intfNum].edb_Index;\r
479 \r
480 if ((size == 0) || //read size is 0\r
481 (data == NULL)){\r
482 return (kUSBCDC_generalError);\r
483 }\r
484 \r
485 state = usbDisableOutEndpointInterrupt(edbIndex);\r
486 //atomic operation - disable interrupts\r
487 \r
488 //do not access USB memory if suspended (PLL off). It may produce BUS_ERROR\r
489 if ((bFunctionSuspended) ||\r
490 (bEnumerationStatus != ENUMERATION_COMPLETE)){\r
491 //data can not be read because of USB suspended\r
492 usbRestoreOutEndpointInterrupt(state);\r
493 return (kUSBCDC_busNotAvailable);\r
494 }\r
495 \r
496 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer != NULL){ //receive process already started\r
497 usbRestoreOutEndpointInterrupt(state);\r
498 return (kUSBCDC_intfBusyError);\r
499 }\r
500 \r
501 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceive = size; //bytes to receive\r
502 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft = size; //left bytes to receive\r
503 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = data; //set user receive buffer\r
504 \r
505 //read rest of data from buffer, if any\r
506 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp > 0){\r
507 //copy data from pEP-endpoint into User's buffer\r
508 CopyUsbToBuff(CdcReadCtrl[INTFNUM_OFFSET(\r
509 intfNum)].pCurrentEpPos,\r
510 CdcReadCtrl[INTFNUM_OFFSET(\r
511 intfNum)\r
512 ].pCT1, intfNum);\r
513 \r
514 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //the Receive opereation is completed\r
515 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending\r
516 if (wUsbEventMask & kUSB_receiveCompletedEvent){\r
517 USBCDC_handleReceiveCompleted(intfNum); //call event handler in interrupt context\r
518 }\r
519 usbRestoreOutEndpointInterrupt(state);\r
520 return (kUSBCDC_receiveCompleted); //receive completed\r
521 }\r
522 \r
523 //check other EP buffer for data - exchange pCT1 with pCT2\r
524 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 ==\r
525 &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX){\r
526 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 =\r
527 &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY;\r
528 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos =\r
529 (uint8_t*)stUsbHandle[intfNum].oep_Y_Buffer;\r
530 } else {\r
531 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 =\r
532 &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX;\r
533 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos =\r
534 (uint8_t*)stUsbHandle[intfNum].oep_X_Buffer;\r
535 }\r
536 \r
537 nTmp1 = *CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1;\r
538 //try read data from second buffer\r
539 if (nTmp1 & EPBCNT_NAK){ //if the second buffer has received data?\r
540 nTmp1 = nTmp1 & 0x7f; //clear NAK bit\r
541 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1; //holds how many valid bytes in the EP buffer\r
542 CopyUsbToBuff(CdcReadCtrl[INTFNUM_OFFSET(\r
543 intfNum)].pCurrentEpPos,\r
544 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1, intfNum);\r
545 }\r
546 \r
547 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //the Receive opereation is completed\r
548 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending\r
549 if (wUsbEventMask & kUSB_receiveCompletedEvent){\r
550 USBCDC_handleReceiveCompleted(intfNum); //call event handler in interrupt context\r
551 }\r
552 usbRestoreOutEndpointInterrupt(state);\r
553 return (kUSBCDC_receiveCompleted); //receive completed\r
554 }\r
555 } //read rest of data from buffer, if any\r
556 \r
557 //read 'fresh' data, if available\r
558 nTmp1 = 0;\r
559 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY == X_BUFFER){ //this is current buffer\r
560 if (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX & EPBCNT_NAK){ //this buffer has a valid data packet\r
561 //this is the active EP buffer\r
562 //pEP1\r
563 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos =\r
564 (uint8_t*)stUsbHandle[intfNum].oep_X_Buffer;\r
565 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 =\r
566 &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX;\r
567 \r
568 //second EP buffer\r
569 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 =\r
570 (uint8_t*)stUsbHandle[intfNum].oep_Y_Buffer;\r
571 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 =\r
572 &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY;\r
573 nTmp1 = 1; //indicate that data is available\r
574 }\r
575 } else { //Y_BUFFER\r
576 if (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY & EPBCNT_NAK){\r
577 //this is the active EP buffer\r
578 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos =\r
579 (uint8_t*)stUsbHandle[intfNum].oep_Y_Buffer;\r
580 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 =\r
581 &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY;\r
582 \r
583 //second EP buffer\r
584 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 =\r
585 (uint8_t*)stUsbHandle[intfNum].oep_X_Buffer;\r
586 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 =\r
587 &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX;\r
588 nTmp1 = 1; //indicate that data is available\r
589 }\r
590 }\r
591 \r
592 if (nTmp1){\r
593 //how many byte we can get from one endpoint buffer\r
594 nTmp1 = *CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1;\r
595 while (nTmp1 == 0)\r
596 {\r
597 nTmp1 = *CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1;\r
598 }\r
599 \r
600 if (nTmp1 & EPBCNT_NAK){\r
601 nTmp1 = nTmp1 & 0x7f; //clear NAK bit\r
602 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1; //holds how many valid bytes in the EP buffer\r
603 \r
604 CopyUsbToBuff(CdcReadCtrl[INTFNUM_OFFSET(\r
605 intfNum)].pCurrentEpPos,\r
606 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1, intfNum);\r
607 \r
608 nTmp1 = *CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2;\r
609 //try read data from second buffer\r
610 if ((CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft >\r
611 0) && //do we have more data to send?\r
612 (nTmp1 & EPBCNT_NAK)){ //if the second buffer has received data?\r
613 nTmp1 = nTmp1 & 0x7f; //clear NAK bit\r
614 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1; //holds how many valid bytes in the EP buffer\r
615 CopyUsbToBuff(CdcReadCtrl[INTFNUM_OFFSET(\r
616 intfNum)].pEP2,\r
617 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2, intfNum);\r
618 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 =\r
619 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2;\r
620 }\r
621 }\r
622 }\r
623 \r
624 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //the Receive opereation is completed\r
625 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending\r
626 if (wUsbEventMask & kUSB_receiveCompletedEvent){\r
627 USBCDC_handleReceiveCompleted(intfNum); //call event handler in interrupt context\r
628 }\r
629 usbRestoreOutEndpointInterrupt(state);\r
630 return (kUSBCDC_receiveCompleted);\r
631 }\r
632 \r
633 //interrupts enable\r
634 usbRestoreOutEndpointInterrupt(state);\r
635 return (kUSBCDC_receiveStarted);\r
636 }\r
637 \r
638 //\r
639 //! \cond\r
640 //\r
641 \r
642 //this function is used only by USB interrupt.\r
643 //It fills user receiving buffer with received data\r
644 int16_t CdcToBufferFromHost (uint8_t intfNum)\r
645 {\r
646 uint8_t * pEP1;\r
647 uint8_t nTmp1;\r
648 uint8_t bWakeUp = FALSE; //per default we do not wake up after interrupt\r
649 \r
650 uint8_t edbIndex;\r
651 \r
652 edbIndex = stUsbHandle[intfNum].edb_Index;\r
653 \r
654 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //do we have somtething to receive?\r
655 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending\r
656 return (bWakeUp);\r
657 }\r
658 \r
659 //No data to receive...\r
660 if (!((tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX |\r
661 tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY)\r
662 & 0x80)){\r
663 return (bWakeUp);\r
664 }\r
665 \r
666 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY == X_BUFFER){ //X is current buffer\r
667 //this is the active EP buffer\r
668 pEP1 = (uint8_t*)stUsbHandle[intfNum].oep_X_Buffer;\r
669 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 =\r
670 &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX;\r
671 \r
672 //second EP buffer\r
673 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 =\r
674 (uint8_t*)stUsbHandle[intfNum].oep_Y_Buffer;\r
675 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 =\r
676 &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY;\r
677 } else {\r
678 //this is the active EP buffer\r
679 pEP1 = (uint8_t*)stUsbHandle[intfNum].oep_Y_Buffer;\r
680 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 =\r
681 &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY;\r
682 \r
683 //second EP buffer\r
684 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 =\r
685 (uint8_t*)stUsbHandle[intfNum].oep_X_Buffer;\r
686 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 =\r
687 &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX;\r
688 }\r
689 \r
690 //how many byte we can get from one endpoint buffer\r
691 nTmp1 = *CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1;\r
692 \r
693 if (nTmp1 & EPBCNT_NAK){\r
694 nTmp1 = nTmp1 & 0x7f; //clear NAK bit\r
695 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1; //holds how many valid bytes in the EP buffer\r
696 \r
697 CopyUsbToBuff(pEP1, CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1, intfNum);\r
698 \r
699 nTmp1 = *CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2;\r
700 //try read data from second buffer\r
701 if ((CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft > 0) && //do we have more data to send?\r
702 (nTmp1 & EPBCNT_NAK)){ //if the second buffer has received data?\r
703 nTmp1 = nTmp1 & 0x7f; //clear NAK bit\r
704 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1; //holds how many valid bytes in the EP buffer\r
705 CopyUsbToBuff(CdcReadCtrl[INTFNUM_OFFSET(\r
706 intfNum)].pEP2,\r
707 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2, intfNum);\r
708 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 =\r
709 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2;\r
710 }\r
711 }\r
712 \r
713 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //the Receive opereation is completed\r
714 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending\r
715 if (wUsbEventMask & kUSB_receiveCompletedEvent){\r
716 bWakeUp |= USBCDC_handleReceiveCompleted(intfNum);\r
717 }\r
718 \r
719 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp){ //Is not read data still available in the EP?\r
720 if (wUsbEventMask & kUSB_dataReceivedEvent){\r
721 bWakeUp |= USBCDC_handleDataReceived(intfNum);\r
722 }\r
723 }\r
724 }\r
725 return (bWakeUp);\r
726 }\r
727 \r
728 //helper for USB interrupt handler\r
729 int16_t CdcIsReceiveInProgress (uint8_t intfNum)\r
730 {\r
731 return (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer != NULL);\r
732 }\r
733 \r
734 //\r
735 //! \endcond\r
736 //\r
737 \r
738 //*****************************************************************************\r
739 //\r
740 //! Aborts an Active Receive Operation.\r
741 //!\r
742 //! \param *size is the number of bytes that were received and are waiting\r
743 //! at the assigned address.\r
744 //! \param intfNum is the data interface for which the send should be\r
745 //! aborted.\r
746 //!\r
747 //! Aborts an active receive operation on CDC interface \b intfNum. Returns the\r
748 //! number of bytes that were received and transferred to the data location\r
749 //! established for this receive operation. The data moved to the buffer up to\r
750 //! that time remains valid.\r
751 //!\r
752 //! An application may choose to call this function if it decides it no longer\r
753 //! wants to receive data from the USB host. It should be noted that if a\r
754 //! continuous stream of data is being received from the host, aborting the\r
755 //! operation is akin to pressing a "pause" button; the host will be NAK'ed\r
756 //! until another receive operation is opened.\r
757 //!\r
758 //! See Sec. 7.2 of \e "Programmer's Guide: MSP430 USB API Stack for CDC/PHDC/HID/MSC" for a detailed discussion of\r
759 //! receive operations.\r
760 //!\r
761 //! \return \b kUSB_succeed\r
762 //\r
763 //*****************************************************************************\r
764 \r
765 uint8_t USBCDC_abortReceive (uint16_t* size, uint8_t intfNum)\r
766 {\r
767 //interrupts disable\r
768 uint8_t edbIndex;\r
769 uint16_t state;\r
770 \r
771 edbIndex = stUsbHandle[intfNum].edb_Index;\r
772 state = usbDisableOutEndpointInterrupt(edbIndex);\r
773 \r
774 *size = 0; //set received bytes count to 0\r
775 \r
776 //is receive operation underway?\r
777 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer){\r
778 //how many bytes are already received?\r
779 *size = CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceive -\r
780 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft;\r
781 \r
782 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = 0;\r
783 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL;\r
784 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft = 0;\r
785 }\r
786 \r
787 //restore interrupt status\r
788 usbRestoreOutEndpointInterrupt(state);\r
789 return (kUSB_succeed);\r
790 }\r
791 \r
792 //*****************************************************************************\r
793 //\r
794 //! Rejects the Data Received from the Host.\r
795 //!\r
796 //! This function rejects data that has been received from the host, for\r
797 //! interface inftNum, that does not have an active receive operation underway.\r
798 //! It resides in the USB endpoint buffer and blocks further data until a\r
799 //! receive operation is opened, or until rejected. When this function is\r
800 //! called, the buffer for this interface is purged, and the data lost. This\r
801 //! frees the USB path to resume communication.\r
802 //!\r
803 //! See Sec. 7.2 of \e "Programmer's Guide: MSP430 USB API Stack for CDC/PHDC/HID/MSC" for a detailed discussion of\r
804 //! receive operations.\r
805 //!\r
806 //! \return \b kUSB_succeed\r
807 //\r
808 //*****************************************************************************\r
809 \r
810 uint8_t USBCDC_rejectData (uint8_t intfNum)\r
811 {\r
812 uint8_t edbIndex;\r
813 uint16_t state;\r
814 \r
815 edbIndex = stUsbHandle[intfNum].edb_Index;\r
816 state = usbDisableOutEndpointInterrupt(edbIndex);\r
817 \r
818 //atomic operation - disable interrupts\r
819 \r
820 //do not access USB memory if suspended (PLL off). It may produce BUS_ERROR\r
821 if (bFunctionSuspended){\r
822 usbRestoreOutEndpointInterrupt(state);\r
823 return (kUSBCDC_busNotAvailable);\r
824 }\r
825 \r
826 //Is receive operation underway?\r
827 //- do not flush buffers if any operation still active.\r
828 if (!CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer){\r
829 uint8_t tmp1 = tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX &\r
830 EPBCNT_NAK;\r
831 uint8_t tmp2 = tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY &\r
832 EPBCNT_NAK;\r
833 \r
834 if (tmp1 ^ tmp2){ //switch current buffer if any and only ONE of buffers\r
835 //is full\r
836 //switch current buffer\r
837 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY =\r
838 (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY +\r
839 1) & 0x01;\r
840 }\r
841 \r
842 tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX = 0; //flush buffer X\r
843 tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY = 0; //flush buffer Y\r
844 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = 0; //indicates that no more data available in the EP\r
845 }\r
846 \r
847 usbRestoreOutEndpointInterrupt(state);\r
848 return (kUSB_succeed);\r
849 }\r
850 \r
851 //*****************************************************************************\r
852 //\r
853 //! Indicates the Status of the CDC Interface.\r
854 //!\r
855 //! \param intfNum is the interface number for which status is being retrieved.\r
856 //! \param bytesSent If a send operation is underway, the number of bytes that\r
857 //! send have been transferred to the host is returned in this location. If\r
858 //! no operation is underway, this returns zero.\r
859 //! \param bytesReceived If a receive operation is underway, the number of bytes\r
860 //! that have been transferred to the assigned memory location is returned\r
861 //! in this location. If no receive operation is underway, this returns\r
862 //! zero.\r
863 //!\r
864 //! Indicates the status of the CDC interface \b intfNum. If a send operation is\r
865 //! active for this interface, the function also returns the number of bytes\r
866 //! that have been transmitted to the host. If a receive operation is active for\r
867 //! this interface, the function also returns the number of bytes that have been\r
868 //! received from the host and are waiting at the assigned address.\r
869 //!\r
870 //! Because multiple flags can be returned, the possible values can be masked\r
871 //! together - for example, \b kUSBCDC_waitingForSend + \b kUSBCDC_dataWaiting.\r
872 //!\r
873 //! \return Any combination of the following:\r
874 //! - \b kUSBCDC_waitingForSend: Indicates that a send operation is\r
875 //! open ont his interface\r
876 //! - \b kUSBCDC_waitingForReceive: Indicates that a receive operation\r
877 //! is open on this interface\r
878 //! - \b kUSBCDC_dataWaiting: Indicates that data has been received\r
879 //! from the host for this interface, waiting in the USB receive\r
880 //! buffers, lacking an open receive operation to accept it.\r
881 //! - \b kUSBCDC_busNotAvailable: Indicates that the bus is either\r
882 //! suspended or disconnected. Any operations that had previously\r
883 //! been underway are now aborted.\r
884 //\r
885 //*****************************************************************************\r
886 \r
887 uint8_t USBCDC_intfStatus (uint8_t intfNum, uint16_t* bytesSent, uint16_t* bytesReceived)\r
888 {\r
889 uint8_t ret = 0;\r
890 uint16_t stateIn, stateOut;\r
891 uint8_t edbIndex;\r
892 \r
893 *bytesSent = 0;\r
894 *bytesReceived = 0;\r
895 \r
896 edbIndex = stUsbHandle[intfNum].edb_Index;\r
897 \r
898 stateIn = usbDisableInEndpointInterrupt(edbIndex);\r
899 stateOut = usbDisableOutEndpointInterrupt(edbIndex);\r
900 \r
901 //Is send operation underway?\r
902 if (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft != 0){\r
903 ret |= kUSBCDC_waitingForSend;\r
904 *bytesSent = CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSend -\r
905 CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft;\r
906 }\r
907 \r
908 //Is receive operation underway?\r
909 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer != NULL){\r
910 ret |= kUSBCDC_waitingForReceive;\r
911 *bytesReceived = CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceive -\r
912 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].\r
913 nBytesToReceiveLeft;\r
914 } else { //receive operation not started\r
915 //do not access USB memory if suspended (PLL off).\r
916 //It may produce BUS_ERROR\r
917 if (!bFunctionSuspended){\r
918 if ((tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX &\r
919 EPBCNT_NAK) | //any of buffers has a valid data packet\r
920 (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY &\r
921 EPBCNT_NAK)){\r
922 ret |= kUSBCDC_dataWaiting;\r
923 }\r
924 }\r
925 }\r
926 \r
927 if ((bFunctionSuspended) ||\r
928 (bEnumerationStatus != ENUMERATION_COMPLETE)){\r
929 //if suspended or not enumerated - report no other tasks pending\r
930 ret = kUSBCDC_busNotAvailable;\r
931 }\r
932 \r
933 //restore interrupt status\r
934 usbRestoreInEndpointInterrupt(stateIn);\r
935 usbRestoreOutEndpointInterrupt(stateOut);\r
936 \r
937 __no_operation();\r
938 return (ret);\r
939 }\r
940 \r
941 //*****************************************************************************\r
942 //\r
943 //! Gives the Number of Bytes in the USB Endpoint Buffer.\r
944 //!\r
945 //! \param intfNum is the data interface whose buffer is to be checked.\r
946 //!\r
947 //! Returns the number of bytes waiting in the USB endpoint buffer for\r
948 //! \b intfNum. A non-zero value generally means that no receive operation is\r
949 //! open by which these bytes can be copied to a user buffer. If the value is\r
950 //! non-zero, the application should either open a receive operation so that the\r
951 //! data can be moved out of the endpoint buffer, or the data should be rejected\r
952 //! (USBCDC_rejectData()).\r
953 //!\r
954 //! \return The number of bytes waiting in this buffer.\r
955 //\r
956 //*****************************************************************************\r
957 \r
958 uint8_t USBCDC_bytesInUSBBuffer (uint8_t intfNum)\r
959 {\r
960 uint8_t bTmp1 = 0;\r
961 uint16_t state;\r
962 uint8_t edbIndex;\r
963 \r
964 edbIndex = stUsbHandle[intfNum].edb_Index;\r
965 \r
966 state = usbDisableOutEndpointInterrupt(edbIndex);\r
967 //atomic operation - disable interrupts\r
968 \r
969 if ((bFunctionSuspended) ||\r
970 (bEnumerationStatus != ENUMERATION_COMPLETE)){\r
971 usbRestoreOutEndpointInterrupt(state);\r
972 //if suspended or not enumerated - report 0 bytes available\r
973 return (0);\r
974 }\r
975 \r
976 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp > 0){ //If a RX operation is underway, part of data may\r
977 //was read of the OEP buffer\r
978 bTmp1 = CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp;\r
979 if (*CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 & EPBCNT_NAK){ //the next buffer has a valid data packet\r
980 bTmp1 += *CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 & 0x7F;\r
981 }\r
982 } else {\r
983 if (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX & EPBCNT_NAK){ //this buffer has a valid data packet\r
984 bTmp1 = tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX & 0x7F;\r
985 }\r
986 if (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY & EPBCNT_NAK){ //this buffer has a valid data packet\r
987 bTmp1 += tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY & 0x7F;\r
988 }\r
989 }\r
990 \r
991 usbRestoreOutEndpointInterrupt(state);\r
992 return (bTmp1);\r
993 }\r
994 \r
995 //\r
996 //! \cond\r
997 //\r
998 \r
999 //----------------------------------------------------------------------------\r
1000 //Line Coding Structure\r
1001 //dwDTERate | 4 | Data terminal rate, in bits per second\r
1002 //bCharFormat | 1 | Stop bits, 0 = 1 Stop bit, 1 = 1,5 Stop bits, 2 = 2 Stop bits\r
1003 //bParityType | 1 | Parity, 0 = None, 1 = Odd, 2 = Even, 3= Mark, 4 = Space\r
1004 //bDataBits | 1 | Data bits (5,6,7,8,16)\r
1005 //----------------------------------------------------------------------------\r
1006 uint8_t usbGetLineCoding (void)\r
1007 {\r
1008 uint8_t infIndex;\r
1009 \r
1010 if(tSetupPacket.wIndex % 2)\r
1011 {\r
1012 infIndex = (tSetupPacket.wIndex-1) / 2;\r
1013 }\r
1014 else\r
1015 {\r
1016 infIndex = (tSetupPacket.wIndex) / 2;\r
1017 }\r
1018 \r
1019 abUsbRequestReturnData[6] =\r
1020 CdcControl[infIndex].bDataBits; //Data bits = 8\r
1021 abUsbRequestReturnData[5] =\r
1022 CdcControl[infIndex].bParity; //No Parity\r
1023 abUsbRequestReturnData[4] =\r
1024 CdcControl[infIndex].bStopBits; //Stop bits = 1\r
1025 \r
1026 abUsbRequestReturnData[3] =\r
1027 CdcControl[infIndex].lBaudrate >> 24;\r
1028 abUsbRequestReturnData[2] =\r
1029 CdcControl[infIndex].lBaudrate >> 16;\r
1030 abUsbRequestReturnData[1] =\r
1031 CdcControl[infIndex].lBaudrate >> 8;\r
1032 abUsbRequestReturnData[0] =\r
1033 CdcControl[infIndex].lBaudrate;\r
1034 \r
1035 wBytesRemainingOnIEP0 = 0x07; //amount of data to be send over EP0 to host\r
1036 usbSendDataPacketOnEP0((uint8_t*)&abUsbRequestReturnData[0]); //send data to host\r
1037 \r
1038 return (FALSE);\r
1039 }\r
1040 \r
1041 //----------------------------------------------------------------------------\r
1042 \r
1043 uint8_t usbSetLineCoding (void)\r
1044 {\r
1045 usbReceiveDataPacketOnEP0((uint8_t*)&abUsbRequestIncomingData); //receive data over EP0 from Host\r
1046 \r
1047 return (FALSE);\r
1048 }\r
1049 \r
1050 //----------------------------------------------------------------------------\r
1051 \r
1052 uint8_t usbSetControlLineState (void)\r
1053 {\r
1054 USBCDC_handleSetControlLineState((uint8_t)tSetupPacket.wIndex,\r
1055 (uint8_t)tSetupPacket.wValue);\r
1056 usbSendZeroLengthPacketOnIEP0(); //Send ZLP for status stage\r
1057 \r
1058 return (FALSE);\r
1059 }\r
1060 \r
1061 //----------------------------------------------------------------------------\r
1062 \r
1063 uint8_t Handler_SetLineCoding (void)\r
1064 {\r
1065 uint8_t bWakeUp;\r
1066 volatile uint8_t infIndex;\r
1067 \r
1068 if(tSetupPacket.wIndex % 2)\r
1069 {\r
1070 infIndex = (tSetupPacket.wIndex-1) / 2;\r
1071 }\r
1072 else\r
1073 {\r
1074 infIndex = (tSetupPacket.wIndex) / 2;\r
1075 }\r
1076 \r
1077 //Baudrate Settings\r
1078 \r
1079 CdcControl[infIndex].lBaudrate =\r
1080 (uint32_t)abUsbRequestIncomingData[3] << 24 |\r
1081 (uint32_t)abUsbRequestIncomingData[2] << 16 |\r
1082 (uint32_t)\r
1083 abUsbRequestIncomingData[1] << 8 | abUsbRequestIncomingData[0];\r
1084 bWakeUp =\r
1085 USBCDC_handleSetLineCoding(tSetupPacket.wIndex,\r
1086 CdcControl[infIndex].lBaudrate);\r
1087 \r
1088 return (bWakeUp);\r
1089 }\r
1090 \r
1091 #endif //ifdef _CDC_\r
1092 \r
1093 //\r
1094 //! \endcond\r
1095 //\r
1096 \r
1097 /*----------------------------------------------------------------------------+\r
1098 | End of source file |\r
1099 +----------------------------------------------------------------------------*/\r
1100 /*------------------------ Nothing Below This Line --------------------------*/\r
1101 //Released_Version_4_10_02\r