]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - msp430-bsl/msp430-bsl.git/blob - usb/usbConstructs.c
Initial commit.
[msp430-bsl/msp430-bsl.git] / usb / usbConstructs.c
1 #include "USB_API/USB_Common/device.h"
2 #include "USB_API/USB_Common/types.h"      // Basic Type declarations
4 #include "USB_config/descriptors.h"
5 #include "USB_API/USB_Common/usb.h"        // USB-specific functions
7 #ifdef _CDC_
8     #include "USB_API/USB_CDC_API/UsbCdc.h"
9 #endif
10 #ifdef _HID_
11     #include "USB_API/USB_HID_API/UsbHid.h"
12 #endif
14 #include <intrinsics.h>
15 #include "usbConstructs.h"
18 /**************************************************************************************************
19 These are example, user-editable construct functions for calling the API.  
21 In cases where fast development is the priority, it's usually best to use these sending  
22 construct functions, rather than calling USBCDC_sendData() or USBHID_sendData() 
23 directly.  This is because they put boundaries on the "background execution" of sends,
24 simplfying the application.  
26 xxxsendDataWaitTilDone() essentially eliminates background processing altogether, always 
27 polling after the call to send and not allowing execution to resume until it's done.  This
28 allows simpler coding at the expense of wasted MCU cycles, and MCU execution being "locked" 
29 to the host (also called "synchronous" operation).  
31 xxxsendDataInBackground() takes advantage of background processing ("asynchronous" operation) 
32 by allowing sending to happen during application execution; while at the same time ensuring 
33 that the sending always definitely occurs.  It provides most of the simplicity of 
34 xxxsendDataWaitTilDone() while minimizing wasted cycles.  It's probably the best choice 
35 for most applications.    
37 A true, asynchronous implementation would be the most cycle-efficient, but is the most 
38 difficult to code; and can't be "contained" in an example function as these other approaches 
39 are.  Such an implementation might be advantageous in RTOS-based implementations or those 
40 requiring the highest levels of efficiency.  
42 These functions take into account all the pertinent return codes, toward ensuring fully 
43 robust operation.   The send functions implement a timeout feature, using a loose "number of 
44 retries" approach.  This was done in order to avoid using additional hardware resources.  A 
45 more sophisticated approach, which the developer might want to implement, would be to use a 
46 hardware timer.  
48 Please see the MSP430 CDC/HID/MSC USB API Programmer's Guide for a full description of these 
49 functions, how they work, and how to use them.  
50 **************************************************************************************************/
54 #ifdef _HID_
55 /* This construct implements post-call polling to ensure the sending completes before the function
56    returns.  It provides the simplest coding, at the expense of wasted cycles and potentially
57    allowing MCU execution to become "locked" to the host, a disadvantage if the host (or bus) is
58    slow.  The function also checks all valid return codes, and returns non-zero if an error occurred.  
59    It assumes no previous send operation is underway; also assumes size is non-zero.  */
60 BYTE hidSendDataWaitTilDone(BYTE* dataBuf, WORD size, BYTE intfNum, ULONG ulTimeout)
61 {
62   ULONG sendCounter = 0;
63   WORD bytesSent, bytesReceived;
65   switch(USBHID_sendData(dataBuf,size,intfNum)) {
66      case kUSBHID_sendStarted:
67           break;
68      case kUSBHID_busNotAvailable:
69           return 2;
70      case kUSBHID_intfBusyError:
71           return 3;
72      case kUSBHID_generalError:
73           return 4;
74      default:;                                  
75   }
76   
77   /* If execution reaches this point, then the operation successfully started.  Now wait til it's finished. */ 
78   while(1) {
79     BYTE ret = USBHID_intfStatus(intfNum,&bytesSent,&bytesReceived);
80     if(ret & kUSBHID_busNotAvailable)                /* This may happen at any time */
81       return 2;
82     if(ret & kUSBHID_waitingForSend)
83     {
84       if(ulTimeout && (sendCounter++ >= ulTimeout))  /* Incr counter & try again */
85         return 1 ;                                   /* Timed out */
86     }
87     else 
88       return 0;                                      /* If neither busNotAvailable nor waitingForSend, it succeeded */
89   }
90 }
93 /* This construct implements pre-call polling to ensure the sending completes before the function
94 returns.  It provides simple coding while also taking advantage of the efficiencies of background
95 processing.  If a previous send operation is underway, this function does waste cycles polling,
96 like xxxsendDataWaitTilDone(); however it's less likely to do so since much of the sending
97 presumably took place in the background since the last call to xxxsendDataInBackground().  
98 The function also checks all valid return codes, and returns non-zero if an error occurred.  
99 It assumes no previous send operation is underway; also assumes size is non-zero.  
100 This call assumes a previous send operation might be underway; also assumes size is non-zero.  
101 Returns zero if send completed; non-zero if it failed, with 1 = timeout and 2 = bus is gone. */ 
102 BYTE hidSendDataInBackground(BYTE* dataBuf, WORD size, BYTE intfNum, ULONG ulTimeout)
104   ULONG sendCounter = 0; 
105   WORD bytesSent, bytesReceived;
106   
107   while(USBHID_intfStatus(intfNum,&bytesSent,&bytesReceived) & kUSBHID_waitingForSend) {
108     if(ulTimeout && ((sendCounter++)>ulTimeout))  /* A send operation is underway; incr counter & try again */
109       return 1;                                   /* Timed out */       
110   }
111   
112   /* The interface is now clear.  Call sendData(). */ 
113   switch(USBHID_sendData(dataBuf,size,intfNum)) {
114      case kUSBHID_sendStarted:
115           return 0;
116      case kUSBHID_busNotAvailable:
117           return 2;
118      default:
119           return 4;
120   }
121 }                                  
123   
124                          
125 /* This call only retrieves data that is already waiting in the USB buffer -- that is, data that has
126 already been received by the MCU.  It assumes a previous, open receive operation (began by a direct
127 call to USBxxx_receiveData()) is NOT underway on this interface; and no receive operation remains 
128 open after this call returns.  It doesn't check for kUSBxxx_busNotAvailable, because it doesn't 
129 matter if it's not.  size is the maximum that is allowed to be received before exiting; i.e., it 
130 is the size allotted to dataBuf.  Returns the number of bytes received. */ 
131 WORD hidReceiveDataInBuffer(BYTE* dataBuf, WORD size, BYTE intfNum)
133   WORD bytesInBuf,rxCount;
134   BYTE* currentPos=dataBuf;
135  
136   while(bytesInBuf = USBHID_bytesInUSBBuffer(intfNum))
137   {
138     if((WORD)(currentPos-dataBuf+bytesInBuf) <= size) {
139         rxCount = bytesInBuf;
140         }
141     else {
142             rxCount = size;
143     }
144  
145     USBHID_receiveData(currentPos,rxCount,intfNum); 
146     currentPos += bytesInBuf;
147   } 
148   return (currentPos-dataBuf);
150 #endif
152 /*********************************************************************************************
153 Please see the MSP430 USB CDC API Programmer's Guide Sec. 9 for a full description of these 
154 functions, how they work, and how to use them.  
155 **********************************************************************************************/
157 #ifdef _CDC_
158 /* This construct implements post-call polling to ensure the sending completes before the function
159 returns.  It provides the simplest coding, at the expense of wasted cycles and potentially
160 allowing MCU execution to become "locked" to the host, a disadvantage if the host (or bus) is
161 slow.  The function also checks all valid return codes, and returns non-zero if an error occurred.  
162 It assumes no previous send operation is underway; also assumes size is non-zero.  */
163 BYTE cdcSendDataWaitTilDone(BYTE* dataBuf, WORD size, BYTE intfNum, ULONG ulTimeout)
165   ULONG sendCounter = 0;
166   WORD bytesSent, bytesReceived;
168   switch(USBCDC_sendData(dataBuf,size,intfNum))
169   {
170      case kUSBCDC_sendStarted:
171           break;
172      case kUSBCDC_busNotAvailable:
173           return 2;
174      case kUSBCDC_intfBusyError:
175           return 3;
176      case kUSBCDC_generalError:
177           return 4;
178      default:;                                  
179   }
180   
181   /* If execution reaches this point, then the operation successfully started.  Now wait til it's finished. */ 
182   while(1) {
183     BYTE ret = USBCDC_intfStatus(intfNum,&bytesSent,&bytesReceived);
184     if(ret & kUSBCDC_busNotAvailable)                /* This may happen at any time */
185       return 2;
186     if(ret & kUSBCDC_waitingForSend) {
187       if(ulTimeout && (sendCounter++ >= ulTimeout))  /* Incr counter & try again */
188         return 1 ;                                   /* Timed out */
189     }
190     else 
191       return 0;                                   /* If neither busNotAvailable nor waitingForSend, it succeeded */
192   }
197 /* This construct implements pre-call polling to ensure the sending completes before the function
198 returns.  It provides simple coding while also taking advantage of the efficiencies of background
199 processing.  If a previous send operation is underway, this function does waste cycles polling,
200 like xxxsendDataWaitTilDone(); however it's less likely to do so since much of the sending
201 presumably took place in the background since the last call to xxxsendDataInBackground().  
202 The function also checks all valid return codes, and returns non-zero if an error occurred.  
203 It assumes no previous send operation is underway; also assumes size is non-zero.  
204 This call assumes a previous send operation might be underway; also assumes size is non-zero.  
205 Returns zero if send completed; non-zero if it failed, with 1 = timeout and 2 = bus is gone. */ 
206 BYTE cdcSendDataInBackground(BYTE* dataBuf, WORD size, BYTE intfNum, ULONG ulTimeout)
208   ULONG sendCounter = 0; 
209   WORD bytesSent, bytesReceived;
210   
211   while(USBCDC_intfStatus(intfNum,&bytesSent,&bytesReceived) & kUSBCDC_waitingForSend) {
212     if(ulTimeout && ((sendCounter++)>ulTimeout))  /* A send operation is underway; incr counter & try again */
213       return 1;                                   /* Timed out                */
214   }
215   
216   /* The interface is now clear.  Call sendData().   */
217   switch(USBCDC_sendData(dataBuf,size,intfNum)) {
218      case kUSBCDC_sendStarted:
219           return 0;
220      case kUSBCDC_busNotAvailable:
221           return 2;
222      default:
223           return 4;
224   }
225 }                                  
227                          
228                          
229 /* This call only retrieves data that is already waiting in the USB buffer -- that is, data that has
230 already been received by the MCU.  It assumes a previous, open receive operation (began by a direct
231 call to USBxxx_receiveData()) is NOT underway on this interface; and no receive operation remains 
232 open after this call returns.  It doesn't check for kUSBxxx_busNotAvailable, because it doesn't 
233 matter if it's not.  size is the maximum that is allowed to be received before exiting; i.e., it 
234 is the size allotted to dataBuf.  Returns the number of bytes received. */ 
235 WORD cdcReceiveDataInBuffer(BYTE* dataBuf, WORD size, BYTE intfNum)
237   WORD bytesInBuf,rxCount;
238   BYTE* currentPos=dataBuf;
239  
240   while(bytesInBuf = USBCDC_bytesInUSBBuffer(intfNum)) {
241     if((WORD)(currentPos-dataBuf+bytesInBuf) <= size) {
242         rxCount = bytesInBuf;
243         }
244     else  {
245             rxCount = size;
246     }
247     
248     USBCDC_receiveData(currentPos,rxCount,intfNum); 
249     currentPos += bytesInBuf;
250   } 
251   return (currentPos-dataBuf);
253 #endif