]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - msp430-bsl/msp430-bsl.git/blob - source/USB_API/USB_Common/usb.c
MSP-BSL v3.0
[msp430-bsl/msp430-bsl.git] / source / USB_API / USB_Common / usb.c
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 usb.c\r
33  *  @brief Contains APIs related to handling of Control Endpoint\r
34  */\r
35 /* \r
36  * ======== usb.c ========\r
37  */\r
38 /*----------------------------------------------------------------------------+\r
39  | Include files                                                               |\r
40  +----------------------------------------------------------------------------*/\r
41 \r
42 //\r
43 //! \cond\r
44 //\r
45 #include <string.h>\r
46 #include "driverlib.h"\r
47 \r
48 #include "../USB_Common/device.h"\r
49 #include "../USB_Common/defMSP430USB.h"\r
50 #include "../USB_Common/usb.h"      //USB-specific Data Structures\r
51 #include "../USB_CDC_API/UsbCdc.h"\r
52 #include "../USB_PHDC_API/UsbPHDC.h"\r
53 #include "../USB_HID_API/UsbHidReq.h"\r
54 #include "../USB_MSC_API/UsbMscScsi.h"\r
55 #include "../USB_Common/UsbIsr.h"\r
56 #include <descriptors.h>\r
57 \r
58 \r
59 /*----------------------------------------------------------------------------+\r
60  | Internal Constant Definition                                               |\r
61  +----------------------------------------------------------------------------*/\r
62 #define NO_MORE_DATA    0xFFFF\r
63 #define EPBCT_NAK       0x80\r
64 #define EPCNF_TOGLE     0x20\r
65 \r
66 #define DIRECTION_IN    0x80\r
67 #define DIRECTION_OUT   0x00\r
68 \r
69 #if defined(__TI_COMPILER_VERSION__)  || defined(__GNUC__)\r
70 #define __no_init\r
71 #define __data16\r
72 #endif\r
73 \r
74 /*----------------------------------------------------------------------------+\r
75  | Internal Variables                                                          |\r
76  +----------------------------------------------------------------------------*/\r
77 \r
78 static uint8_t bConfigurationNumber;   //Set to 1 when USB device has been\r
79 //configured, set to 0 when unconfigured\r
80 \r
81 static uint8_t bInterfaceNumber;       //interface number\r
82 \r
83 uint16_t wBytesRemainingOnIEP0;         //For endpoint zero transmitter only\r
84                                     //Holds count of bytes remaining to be\r
85                                     //transmitted by endpoint 0.  A value\r
86                                     //of 0 means that a 0-length data packet\r
87                                     //A value of 0xFFFF means that transfer\r
88                                     //is complete.\r
89 \r
90 uint16_t wBytesRemainingOnOEP0;         //For endpoint zero transmitter only\r
91                                     //Holds count of bytes remaining to be\r
92                                     //received by endpoint 0.  A value\r
93                                     //of 0 means that a 0-length data packet\r
94                                     //A value of 0xFFFF means that transfer\r
95                                     //is complete.\r
96 \r
97 static const uint8_t* pbIEP0Buffer;          //A buffer pointer to input end point 0\r
98                                     //Data sent back to host is copied from\r
99                                     //this pointed memory location\r
100 \r
101 static uint8_t* pbOEP0Buffer;          //A buffer pointer to output end point 0\r
102                                     //Data sent from host is copied to\r
103                                     //this pointed memory location\r
104 \r
105 static uint8_t bHostAskMoreDataThanAvailable = 0;\r
106 \r
107 uint8_t abUsbRequestReturnData[USB_RETURN_DATA_LENGTH];\r
108 uint8_t abUsbRequestIncomingData[USB_RETURN_DATA_LENGTH];\r
109 \r
110 __no_init uint8_t abramSerialStringDescriptor[34];\r
111 \r
112 uint8_t bStatusAction;\r
113 uint8_t bFunctionSuspended = FALSE;    //TRUE if function is suspended\r
114 uint8_t bEnumerationStatus = 0;        //is 0 if not enumerated\r
115 \r
116 static uint8_t bRemoteWakeup;\r
117 \r
118 uint16_t wUsbEventMask;                 //used by USB_getEnabledEvents() and USB_setEnabledEvents()\r
119 \r
120 #ifdef _MSC_\r
121 extern uint8_t USBMSC_reset (void);\r
122 void MscResetData ();\r
123 extern struct _MscState MscState;\r
124 #endif\r
125 \r
126 #ifdef NON_COMPOSITE_MULTIPLE_INTERFACES\r
127 \r
128 extern const void *usbConfigurationDescriptors[];\r
129 extern const void *usbDeviceDescriptors[];\r
130 extern const uint8_t usbConfigurationsSizes[];\r
131 uint8_t activeInterfaceIndex = 0;\r
132 \r
133 #endif\r
134 \r
135 /*----------------------------------------------------------------------------+\r
136  | Global Variables                                                            |\r
137  +----------------------------------------------------------------------------*/\r
138 /*----------------------------------------------------------------------------+\r
139  | Hardware Related Structure Definition                                       |\r
140  +----------------------------------------------------------------------------*/\r
141 \r
142 #ifdef __IAR_SYSTEMS_ICC__\r
143 \r
144 #pragma location = 0x2380\r
145 __no_init tDEVICE_REQUEST __data16 tSetupPacket;\r
146 \r
147 #pragma location = 0x0920\r
148 __no_init tEDB0 __data16 tEndPoint0DescriptorBlock;\r
149 \r
150 #pragma location = 0x23C8\r
151 __no_init tEDB __data16 tInputEndPointDescriptorBlock[7];\r
152 \r
153 #pragma location = 0x2388\r
154 __no_init tEDB __data16 tOutputEndPointDescriptorBlock[7];\r
155 \r
156 #pragma location = 0x2378\r
157 __no_init uint8_t __data16 abIEP0Buffer[EP0_MAX_PACKET_SIZE];\r
158 \r
159 #pragma location = 0x2370\r
160 __no_init uint8_t __data16 abOEP0Buffer[EP0_MAX_PACKET_SIZE];\r
161 \r
162 #pragma location = OEP1_X_BUFFER_ADDRESS\r
163 __no_init uint8_t __data16 pbXBufferAddressEp1[EP_MAX_PACKET_SIZE];\r
164 \r
165 #pragma location = OEP1_Y_BUFFER_ADDRESS\r
166 __no_init uint8_t __data16 pbYBufferAddressEp1[EP_MAX_PACKET_SIZE];\r
167 \r
168 #pragma location = IEP1_X_BUFFER_ADDRESS\r
169 __no_init uint8_t __data16 pbXBufferAddressEp81[EP_MAX_PACKET_SIZE];\r
170 \r
171 #pragma location = IEP1_Y_BUFFER_ADDRESS\r
172 __no_init uint8_t __data16 pbYBufferAddressEp81[EP_MAX_PACKET_SIZE];\r
173 \r
174 #pragma location = OEP2_X_BUFFER_ADDRESS\r
175 __no_init uint8_t __data16 pbXBufferAddressEp2[EP_MAX_PACKET_SIZE];\r
176 \r
177 #pragma location = OEP2_Y_BUFFER_ADDRESS\r
178 __no_init uint8_t __data16 pbYBufferAddressEp2[EP_MAX_PACKET_SIZE];\r
179 \r
180 #pragma location = IEP2_X_BUFFER_ADDRESS\r
181 __no_init uint8_t __data16 pbXBufferAddressEp82[EP_MAX_PACKET_SIZE];\r
182 \r
183 #pragma location = IEP2_Y_BUFFER_ADDRESS\r
184 __no_init uint8_t __data16 pbYBufferAddressEp82[EP_MAX_PACKET_SIZE];\r
185 \r
186 #pragma location = OEP3_X_BUFFER_ADDRESS\r
187 __no_init uint8_t __data16 pbXBufferAddressEp3[EP_MAX_PACKET_SIZE];\r
188 \r
189 #pragma location = OEP3_Y_BUFFER_ADDRESS\r
190 __no_init uint8_t __data16 pbYBufferAddressEp3[EP_MAX_PACKET_SIZE];\r
191 \r
192 #pragma location = IEP3_X_BUFFER_ADDRESS\r
193 __no_init uint8_t __data16 pbXBufferAddressEp83[EP_MAX_PACKET_SIZE];\r
194 \r
195 #pragma location = IEP3_Y_BUFFER_ADDRESS\r
196 __no_init uint8_t __data16 pbYBufferAddressEp83[EP_MAX_PACKET_SIZE];\r
197 \r
198 #pragma location = OEP4_X_BUFFER_ADDRESS\r
199 __no_init uint8_t __data16 pbXBufferAddressEp4[EP_MAX_PACKET_SIZE];\r
200 \r
201 #pragma location = OEP4_Y_BUFFER_ADDRESS\r
202 __no_init uint8_t __data16 pbYBufferAddressEp4[EP_MAX_PACKET_SIZE];\r
203 \r
204 #pragma location = IEP4_X_BUFFER_ADDRESS\r
205 __no_init uint8_t __data16 pbXBufferAddressEp84[EP_MAX_PACKET_SIZE];\r
206 \r
207 #pragma location = IEP4_Y_BUFFER_ADDRESS\r
208 __no_init uint8_t __data16 pbYBufferAddressEp84[EP_MAX_PACKET_SIZE];\r
209 \r
210 #pragma location = OEP5_X_BUFFER_ADDRESS\r
211 __no_init uint8_t __data16 pbXBufferAddressEp5[EP_MAX_PACKET_SIZE];\r
212 \r
213 #pragma location = OEP5_Y_BUFFER_ADDRESS\r
214 __no_init uint8_t __data16 pbYBufferAddressEp5[EP_MAX_PACKET_SIZE];\r
215 \r
216 #pragma location = IEP5_X_BUFFER_ADDRESS\r
217 __no_init uint8_t __data16 pbXBufferAddressEp85[EP_MAX_PACKET_SIZE];\r
218 \r
219 #pragma location = IEP5_Y_BUFFER_ADDRESS\r
220 __no_init uint8_t __data16 pbYBufferAddressEp85[EP_MAX_PACKET_SIZE];\r
221 \r
222 #pragma location = OEP6_X_BUFFER_ADDRESS\r
223 __no_init uint8_t __data16 pbXBufferAddressEp6[EP_MAX_PACKET_SIZE];\r
224 \r
225 #pragma location = OEP6_Y_BUFFER_ADDRESS\r
226 __no_init uint8_t __data16 pbYBufferAddressEp6[EP_MAX_PACKET_SIZE];\r
227 \r
228 #pragma location = IEP6_X_BUFFER_ADDRESS\r
229 __no_init uint8_t __data16 pbXBufferAddressEp86[EP_MAX_PACKET_SIZE];\r
230 \r
231 #pragma location = IEP6_Y_BUFFER_ADDRESS\r
232 __no_init uint8_t __data16 pbYBufferAddressEp86[EP_MAX_PACKET_SIZE];\r
233 \r
234 #pragma location = OEP7_X_BUFFER_ADDRESS\r
235 __no_init uint8_t __data16 pbXBufferAddressEp7[EP_MAX_PACKET_SIZE];\r
236 \r
237 #pragma location = OEP7_Y_BUFFER_ADDRESS\r
238 __no_init uint8_t __data16 pbYBufferAddressEp7[EP_MAX_PACKET_SIZE];\r
239 \r
240 #pragma location = IEP7_X_BUFFER_ADDRESS\r
241 __no_init uint8_t __data16 pbXBufferAddressEp87[EP_MAX_PACKET_SIZE];\r
242 \r
243 #pragma location = IEP7_Y_BUFFER_ADDRESS\r
244 __no_init uint8_t __data16 pbYBufferAddressEp87[EP_MAX_PACKET_SIZE];\r
245 \r
246 \r
247 \r
248 #endif\r
249 \r
250 #if defined(__TI_COMPILER_VERSION__)  || defined(__GNUC__)\r
251 extern __no_init tDEVICE_REQUEST tSetupPacket;\r
252 extern __no_init tEDB0 tEndPoint0DescriptorBlock;\r
253 extern __no_init tEDB tInputEndPointDescriptorBlock[7];\r
254 extern __no_init tEDB tOutputEndPointDescriptorBlock[7];\r
255 extern __no_init uint8_t abIEP0Buffer[EP0_MAX_PACKET_SIZE];\r
256 extern __no_init uint8_t abOEP0Buffer[EP0_MAX_PACKET_SIZE];\r
257 extern __no_init uint8_t pbXBufferAddressEp1[EP_MAX_PACKET_SIZE];\r
258 extern __no_init uint8_t pbYBufferAddressEp1[EP_MAX_PACKET_SIZE];\r
259 extern __no_init uint8_t pbXBufferAddressEp81[EP_MAX_PACKET_SIZE];\r
260 extern __no_init uint8_t pbYBufferAddressEp81[EP_MAX_PACKET_SIZE];\r
261 extern __no_init uint8_t pbXBufferAddressEp2[EP_MAX_PACKET_SIZE];\r
262 extern __no_init uint8_t pbYBufferAddressEp2[EP_MAX_PACKET_SIZE];\r
263 extern __no_init uint8_t pbXBufferAddressEp82[EP_MAX_PACKET_SIZE];\r
264 extern __no_init uint8_t pbYBufferAddressEp82[EP_MAX_PACKET_SIZE];\r
265 extern __no_init uint8_t pbXBufferAddressEp3[EP_MAX_PACKET_SIZE];\r
266 extern __no_init uint8_t pbYBufferAddressEp3[EP_MAX_PACKET_SIZE];\r
267 extern __no_init uint8_t pbXBufferAddressEp83[EP_MAX_PACKET_SIZE];\r
268 extern __no_init uint8_t pbYBufferAddressEp83[EP_MAX_PACKET_SIZE];\r
269 \r
270 extern __no_init uint8_t pbXBufferAddressEp4[EP_MAX_PACKET_SIZE];\r
271 extern __no_init uint8_t pbYBufferAddressEp4[EP_MAX_PACKET_SIZE];\r
272 extern __no_init uint8_t pbXBufferAddressEp84[EP_MAX_PACKET_SIZE];\r
273 extern __no_init uint8_t pbYBufferAddressEp84[EP_MAX_PACKET_SIZE];\r
274 \r
275 extern __no_init uint8_t pbXBufferAddressEp5[EP_MAX_PACKET_SIZE];\r
276 extern __no_init uint8_t pbYBufferAddressEp5[EP_MAX_PACKET_SIZE];\r
277 extern __no_init uint8_t pbXBufferAddressEp85[EP_MAX_PACKET_SIZE];\r
278 extern __no_init uint8_t pbYBufferAddressEp85[EP_MAX_PACKET_SIZE];\r
279 \r
280 #endif\r
281 \r
282 void CdcResetData ();\r
283 void HidResetData ();\r
284 void PHDCResetData();\r
285 \r
286 void USB_InitSerialStringDescriptor (void);\r
287 void USB_initMemcpy (void);\r
288 uint16_t USB_determineFreq(void);\r
289 \r
290 /* Version string to embed in executable. May need to change for ELF compiler */\r
291 const char *VERSION = "USB_DEVELOPERS_PACKAGE_4_10_02";\r
292 char *USB_getVersion(void)\r
293 {\r
294         return ((char *)&VERSION);\r
295 }\r
296 \r
297 //\r
298 //! \endcond\r
299 //\r
300 \r
301 //*****************************************************************************\r
302 //\r
303 //! Initializes the USB Module.\r
304 //!\r
305 //! \r
306 //! Initializes the USB module by configuring power and clocks, and configures\r
307 //! pins that are critical for USB. This should be called very soon after the \r
308 //! beginning of program execution. \r
309 //! \r
310 //! Note that this does not enable the USB module (that is, does not set \r
311 //! USB_EN bit). Rather, it prepares the USB module to detect the application of\r
312 //! power to VBUS, after which the application may choose to enable the module\r
313 //! and connect to USB. Calling this function is necessary to achieve expected \r
314 //! LPM3 current consumption into DVCC.\r
315 //!\r
316 //! \return \b kUSB_succeed\r
317 //\r
318 //*****************************************************************************\r
319 \r
320 uint8_t USB_init (void)\r
321 {\r
322     uint16_t bGIE  = __get_SR_register() & GIE;                                 //save interrupt status\r
323     uint16_t MCLKFreq = USB_determineFreq();\r
324     uint16_t DelayConstant_250us = ((MCLKFreq >> 6) + (MCLKFreq >> 7) + (MCLKFreq >> 9));\r
325     volatile uint16_t i, j;\r
326 \r
327     char *(*fp)(void);\r
328 \r
329         /* force version string into executable */\r
330     fp = &USB_getVersion;\r
331     fp();\r
332 \r
333     //atomic operation - disable interrupts\r
334     __disable_interrupt();                                                      //Disable global interrupts\r
335 \r
336     //configuration of USB module\r
337     USBKEYPID   =     0x9628;                                                   //set KEY and PID to 0x9628 -> access to\r
338                                                                                                                                                                 //configuration registers enabled\r
339     /* If USB device is self-powered, USB_SUPPORT_SELF_POWERED = 0xc0 */\r
340 #if (USB_SUPPORT_SELF_POWERED == 0xc0)\r
341         /* To fix USB9 enumeration issue */\r
342         USBPWRCTL = 0;\r
343 #endif\r
344         \r
345     USBPHYCTL   =     PUSEL;                                                    //use DP and DM as USB terminals (not needed\r
346                                                                                 //because an external PHY is connected to port\r
347                                                                                 //9)\r
348     if(USB_USE_INTERNAL_3V3LDO == TRUE)\r
349         USBPWRCTL   =     VUSBEN + SLDOAON;                                     //enable 3.3v and 1.8v LDO (3.3 and 1.8V)\r
350     else\r
351         USBPWRCTL   =     SLDOEN + USBDETEN;                                    //enable 1.8v and VBUS voltage detection while internal 3.3v\r
352                                                                                 //LDO is turned off.\r
353 \r
354     for (j = 0; j < 20; j++) {\r
355         for (i = 0; i < (DelayConstant_250us); i++) {//wait some time for LDOs (5ms delay)\r
356             _NOP();\r
357         }\r
358     }\r
359 \r
360     USBPWRCTL   |=   VBONIE;                                                                    //enable interrupt VBUSon\r
361     USBKEYPID   =    0x9600;                                                    //access to configuration registers disabled\r
362 \r
363     //reset events mask\r
364     wUsbEventMask = 0;\r
365 \r
366     //init Serial Number\r
367 #if (USB_STR_INDEX_SERNUM != 0)\r
368     USB_InitSerialStringDescriptor();\r
369 #endif\r
370 \r
371     //init memcpy() function: DMA or non-DMA\r
372     USB_initMemcpy();\r
373 #ifdef _MSC_\r
374     MscResetCtrlLun();\r
375 #endif\r
376 \r
377 #ifdef BRIDGE_CDC_PRESENT\r
378     USBCDC_setupDMA_Bridge();\r
379 #endif\r
380     \r
381     __bis_SR_register(bGIE);                                                    //restore interrupt status\r
382     return (kUSB_succeed);\r
383 }\r
384 \r
385 //*****************************************************************************\r
386 //\r
387 //! Initializes the USB Module. Also enables events and connects.\r
388 //!\r
389 //! \r
390 //! Initializes the USB module by configuring power and clocks, and configures\r
391 //! pins that are critical for USB. This should be called very soon after the \r
392 //! beginning of program execution. \r
393 //!\r
394 //! If connectEnable is TRUE, then this API then enables the USB module, which \r
395 //! includes activating the PLL and setting the USB_EN bit. AFter enabling the\r
396 //! USB module, this API will connect to the host if VBUS is present.\r
397 //!\r
398 //! If eventsEnable is set to TRUE then all USB events are enabled by this API.\r
399 //!\r
400 //! \param      connectEnable   If TRUE, Connect to host if VBUS is present by \r
401 //!                                                     pulling the D+ signal high using the PUR pin.\r
402 //! \param  eventsEnable        If TRUE, all USB events handlers are enabled\r
403 //! \return \b kUSB_succeed\r
404 //\r
405 //*****************************************************************************\r
406 \r
407 uint8_t USB_setup(uint8_t connectEnable, uint8_t eventsEnable)\r
408 {\r
409         uint8_t status;\r
410 \r
411         status = USB_init();\r
412 \r
413         if (eventsEnable) {\r
414                 USB_setEnabledEvents(kUSB_allUsbEvents);\r
415         }\r
416         if (connectEnable) {\r
417                 if (USB_connectionInfo() & kUSB_vbusPresent){\r
418                         if (USB_enable() == kUSB_succeed){\r
419                                 USB_reset();\r
420                                 USB_connect();\r
421                         }\r
422                 }\r
423         }\r
424 \r
425     return (status);\r
426 }\r
427 \r
428 //\r
429 //! \cond\r
430 //\r
431 \r
432 //----------------------------------------------------------------------------\r
433 //This function will be compiled only if\r
434 #if (USB_STR_INDEX_SERNUM != 0)\r
435 void USB_InitSerialStringDescriptor (void)\r
436 {\r
437     uint8_t i,j,hexValue;\r
438     uint8_t* pbSerNum;\r
439     uint8_t bBytes;\r
440 \r
441     j = 1;                                                                      //we start with second byte, first byte (lenght)\r
442                                                                                 //will be filled later\r
443     pbSerNum = 0;\r
444     abramSerialStringDescriptor[j++] = DESC_TYPE_STRING;\r
445 \r
446     //TLV access Function Call\r
447     TLV_getInfo(TLV_TAG_DIERECORD, 0,\r
448         (uint8_t *)&bBytes, (uint16_t **)&pbSerNum);\r
449     if (bBytes == 0){                                                           //no serial number available\r
450         //use 00 as serial number = no serial number available\r
451         abramSerialStringDescriptor[0] = 4;                                     //length\r
452         abramSerialStringDescriptor[j++] = 0;                                   //no serial number available\r
453         abramSerialStringDescriptor[j++] = 0;                                   //no serial number available\r
454     } else {\r
455         for (i = 0; (i < bBytes) && (i < 8); i++,pbSerNum++)\r
456         {\r
457             hexValue = (*pbSerNum & 0xF0) >> 4;\r
458             if (hexValue < 10){\r
459                 abramSerialStringDescriptor[j++] = (hexValue + '0');\r
460             } else {          abramSerialStringDescriptor[j++] = (hexValue + 55);}\r
461             abramSerialStringDescriptor[j++] = 0x00;                            //needed for UNI-Code\r
462 \r
463             hexValue = (*pbSerNum & 0x0F);\r
464             if (hexValue < 10){\r
465                 abramSerialStringDescriptor[j++] = (hexValue + '0');\r
466             } else {          abramSerialStringDescriptor[j++] = (hexValue + 55);}\r
467             abramSerialStringDescriptor[j++] = 0x00;                            //needed for UNI-Code\r
468         }\r
469         abramSerialStringDescriptor[0] = i * 4 + 2;                             //calculate the length\r
470     }\r
471 }\r
472 \r
473 #endif\r
474 \r
475 //\r
476 //! \endcond\r
477 //\r
478 \r
479 //*****************************************************************************\r
480 //\r
481 //! Enables the USB Module.\r
482 //!\r
483 //! Enables the USB module, which includes activating the PLL and setting the \r
484 //! USB_EN bit. Power consumption increases as a result of this operation (see \r
485 //! device datasheet for specifics). This call should only be made after an \r
486 //! earlier call to USB_init(), and prior to any other call except than \r
487 //! USB_setEnabledEvents(), or USB_getEnabledEvents(). It is usually called just\r
488 //! prior to attempting to connect with a host after a bus connection has \r
489 //! already been detected.\r
490 //! \r
491 //! \return \b kUSB_succeed\r
492 //\r
493 //*****************************************************************************\r
494 \r
495 uint8_t USB_enable ()\r
496 {\r
497 #ifdef USE_TIMER_FOR_RESUME\r
498         USB_enable_crystal();\r
499         return (kUSB_succeed);\r
500 #else\r
501 \r
502     volatile uint16_t i, k;\r
503     volatile uint16_t j = 0;\r
504     uint16_t status;\r
505     uint16_t MCLKFreq = USB_determineFreq();\r
506     uint16_t DelayConstant_250us = ((MCLKFreq >> 6) + (MCLKFreq >> 7) + (MCLKFreq >> 9));\r
507 \r
508     if (!(USBPWRCTL & USBBGVBV)){                                               //check USB Bandgap and VBUS valid\r
509         return (kUSB_generalError);\r
510     }\r
511 \r
512     if ((USBCNF & USB_EN) &&\r
513         (USBPLLCTL & UPLLEN)){\r
514         return (kUSB_succeed);                                                  //exit if PLL is already enalbed\r
515     }\r
516 \r
517 #if defined (__MSP430F552x) || defined (__MSP430F550x)\r
518         GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN2);\r
519         GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN3);\r
520 #elif defined (__MSP430F563x_F663x) || defined (__MSP430F565x_F665x)\r
521         GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P7, GPIO_PIN2);\r
522         GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P7, GPIO_PIN3);\r
523 #endif\r
524     USBKEYPID = 0x9628;                                                         //set KEY and PID to 0x9628 -> access to\r
525                                                                                 //configuration registers enabled\r
526 #ifndef DRIVERLIB_LEGACY_MODE\r
527     if (USB_XT_FREQ_VALUE >= 24) {\r
528         status = UCS_XT2StartWithTimeout(\r
529                         XT2DRIVE_3, 50000);\r
530     }\r
531     else if(USB_XT_FREQ_VALUE >= 16) {\r
532         status = UCS_XT2StartWithTimeout(\r
533                         XT2DRIVE_2, 50000);\r
534     }\r
535     else if(USB_XT_FREQ_VALUE >= 8) {\r
536         status = UCS_XT2StartWithTimeout(\r
537                         XT2DRIVE_1, 50000);\r
538     }\r
539     else {\r
540         status = UCS_XT2StartWithTimeout(\r
541                         XT2DRIVE_0, 50000);\r
542     }\r
543 #else\r
544     if (USB_XT_FREQ_VALUE >= 24) {\r
545         status = UCS_XT2StartWithTimeout(UCS_BASE,\r
546                         XT2DRIVE_3, 50000);\r
547     }\r
548     else if(USB_XT_FREQ_VALUE >= 16) {\r
549         status = UCS_XT2StartWithTimeout(UCS_BASE,\r
550                         XT2DRIVE_2, 50000);\r
551     }\r
552     else if(USB_XT_FREQ_VALUE >= 8) {\r
553         status = UCS_XT2StartWithTimeout(UCS_BASE,\r
554                         XT2DRIVE_1, 50000);\r
555     }\r
556     else {\r
557         status = UCS_XT2StartWithTimeout(UCS_BASE,\r
558                         XT2DRIVE_0, 50000);\r
559     }\r
560 #endif\r
561 \r
562         if (status == STATUS_FAIL) {\r
563                 return (kUSB_generalError);\r
564         }\r
565         \r
566     USBPLLDIVB = USB_XT_FREQ;                                                   //Settings desired frequency\r
567 \r
568     USBPLLCTL = UPFDEN + UPLLEN;                                                    //Select XT2 as Ref / Select PLL for USB / Discrim.\r
569                                                                                 //on, enable PLL\r
570 \r
571     //Wait some time till PLL is settled\r
572     do\r
573     {\r
574         USBPLLIR    =     0x0000;                                               //make sure no interrupts can occur on\r
575                                                                                 //PLL-module\r
576         if ((((bFunctionSuspended == TRUE) || (bFunctionSuspended == FALSE)) && (USB_DISABLE_XT_SUSPEND == 1)) ||\r
577                         ((USB_DISABLE_XT_SUSPEND == 0) && (bFunctionSuspended == FALSE))){  //BUG NUMBER 4879\r
578 #ifdef __MSP430F6638\r
579             //wait 1 ms till enable USB\r
580             for(k = 0; k < 4; k++)\r
581             {\r
582                 for (i = 0; i < (DelayConstant_250us); i++){\r
583                     _NOP();\r
584                 }\r
585             }\r
586 #else\r
587             //wait 1/2 ms till enable USB\r
588             for(k = 0; k < 2; k++)\r
589             {\r
590                 for (i = 0; i < (DelayConstant_250us); i++){\r
591                    _NOP();\r
592                 }\r
593             }        \r
594 #endif\r
595         }\r
596 \r
597         if (j++ > 10){\r
598             USBKEYPID   =    0x9600;                                            //access to configuration registers disabled\r
599             return (kUSB_generalError);\r
600         }\r
601     } while (USBPLLIR != 0);\r
602 \r
603     USBCNF     |=    USB_EN;                                                    //enable USB module\r
604     USBKEYPID   =    0x9600;                                                    //access to configuration registers disabled\r
605     return (kUSB_succeed);\r
606 #endif\r
607 }\r
608 \r
609 #ifdef USE_TIMER_FOR_RESUME\r
610 \r
611 //*****************************************************************************\r
612 //\r
613 //! First phase of enabling the USB Module when USE_TIMER_FOR_RESUME is defined\r
614 //!\r
615 //! This functions is only used by USB_resume to reduce the interrupt latency\r
616 //! of the resume interrupt.\r
617 //! This function starts the XT2 crystal and then calls an event handler\r
618 //! USB_handleCrystalStartedEvent() to allow the application to get control. The\r
619 //! application can use a timer or other peripheral to "wait" for the XT2\r
620 //! crystal to stabilize. See the crystal datasheet for typical wait times.\r
621 //! The application then informs the stack of XT2\r
622 //! stabilization by calling USB_enable_PLL().\r
623 //!\r
624 //! \return \b kUSB_succeed or kUSB_generalError\r
625 //\r
626 //*****************************************************************************\r
627 \r
628 uint8_t USB_enable_crystal (void)\r
629 {\r
630     volatile uint16_t i, k;\r
631     volatile uint16_t j = 0;\r
632 \r
633     if (!(USBPWRCTL & USBBGVBV)){                                               //check USB Bandgap and VBUS valid\r
634         return (kUSB_generalError);\r
635     }\r
636 \r
637     if ((USBCNF & USB_EN) &&\r
638         (USBPLLCTL & UPLLEN)){\r
639         return (kUSB_succeed);                                                  //exit if PLL is already enalbed\r
640     }\r
641 \r
642 #if defined (__MSP430F552x) || defined (__MSP430F550x)\r
643         GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN2);\r
644         GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN3);\r
645 #elif defined (__MSP430F563x_F663x) || defined (__MSP430F565x_F665x)\r
646         GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P7, GPIO_PIN2);\r
647         GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P7, GPIO_PIN3);\r
648 #endif\r
649  \r
650 #ifndef DRIVERLIB_LEGACY_MODE \r
651     if (USB_XT_FREQ_VALUE >= 24) {\r
652         UCS_XT2StartWithTimeout(XT2DRIVE_3, 1);\r
653     }\r
654     else if(USB_XT_FREQ_VALUE >= 16) {\r
655         UCS_XT2StartWithTimeout(XT2DRIVE_2, 1);\r
656     }\r
657     else if(USB_XT_FREQ_VALUE >= 8) {\r
658         UCS_XT2StartWithTimeout(XT2DRIVE_1, 1);\r
659     }\r
660     else {\r
661         UCS_XT2StartWithTimeout(XT2DRIVE_0, 1);\r
662     }\r
663 \r
664 #else\r
665     if (USB_XT_FREQ_VALUE >= 24) {\r
666         UCS_XT2StartWithTimeout(UCS_BASE, XT2DRIVE_3, 1);\r
667     }\r
668     else if(USB_XT_FREQ_VALUE >= 16) {\r
669         UCS_XT2StartWithTimeout(UCS_BASE, XT2DRIVE_2, 1);\r
670     }\r
671     else if(USB_XT_FREQ_VALUE >= 8) {\r
672         UCS_XT2StartWithTimeout(UCS_BASE, XT2DRIVE_1, 1);\r
673     }\r
674     else {\r
675         UCS_XT2StartWithTimeout(UCS_BASE, XT2DRIVE_0, 1);\r
676     }\r
677 \r
678 #endif\r
679 \r
680     USB_handleCrystalStartedEvent();\r
681 \r
682     return (kUSB_succeed);\r
683 }\r
684 \r
685 //*****************************************************************************\r
686 //\r
687 //! Second phase of enabling the USB Module when USE_TIMER_FOR_RESUME is defined\r
688 //!\r
689 //! This functions is only used by USB_resume to reduce the interrupt latency\r
690 //! of the resume interrupt.\r
691 //! This function starts the PLL and then calls an event handler\r
692 //! USB_handlePLLStartedEvent() to allow the application to get control. The\r
693 //! application can use a timer or other peripheral to "wait" for the USB PLL\r
694 //! to stabilize. See the datasheet for typical PLL wait times.\r
695 //! The application then informs the stack of XT2\r
696 //! stabilization by calling USB_enable_final().\r
697 //!\r
698 //! \return \b kUSB_succeed or kUSB_generalError\r
699 //\r
700 //*****************************************************************************\r
701 void USB_enable_PLL(void)\r
702 {\r
703     USBKEYPID = 0x9628;                                                         //set KEY and PID to 0x9628 -> access to\r
704                                                                                 //configuration registers enabled\r
705     USBPLLDIVB = USB_XT_FREQ;                                                   //Settings desired frequency\r
706 \r
707     USBPLLCTL = UPFDEN + UPLLEN;                                               //Select XT2 as Ref / Select PLL for USB / Discrim.\r
708                                                                                 //on, enable PLL\r
709 \r
710     USB_handlePLLStartedEvent();\r
711 }\r
712 \r
713 //*****************************************************************************\r
714 //\r
715 //! Final phase of enabling the USB Module when USE_TIMER_FOR_RESUME is defined\r
716 //!\r
717 //! This function is only used by USB_resume to reduce the interrupt latency\r
718 //! of the resume interrupt.\r
719 //! This function gets called by the application when thye USB PLL has stabilized\r
720 //! to allow the resume process to finish.\r
721 //!\r
722 //\r
723 //*****************************************************************************\r
724 void USB_enable_final(void)\r
725 {\r
726     USBCNF     |=    USB_EN;                                                    //enable USB module\r
727     USBKEYPID   =    0x9600;                                                    //access to configuration registers disabled\r
728     USBIFG &= ~(RESRIFG | SUSRIFG);     //clear interrupt flags\r
729     USBIE = SETUPIE | RSTRIE | SUSRIE;  //enable USB specific interrupts (setup, reset, suspend)\r
730 \r
731     bFunctionSuspended  = FALSE;\r
732 }\r
733 \r
734 #endif\r
735 \r
736 //*****************************************************************************\r
737 //\r
738 //! Disables the USB Module and PLL.\r
739 //!\r
740 //!\r
741 //! Disables the USB module and PLL. If USB is not enabled when this call is \r
742 //! made, no error is returned - the call simply exits with success.\r
743 //! \r
744 //! If a handleVbusOffEvent() occurs, or if USB_connectionState() begins \r
745 //! returning ST_USB_DISCONNECTED, this function should be called (following a \r
746 //! call to USB_disconnect()), in order to avoid unnecessary current draw.\r
747 //!\r
748 //! \return \b kUSB_succeed\r
749 //\r
750 //*****************************************************************************\r
751 \r
752 uint8_t USB_disable (void)\r
753 {\r
754     USBKEYPID = 0x9628;                                                         //set KEY and PID to 0x9628 -> access to\r
755                                                                                 //configuration registers enabled\r
756     USBCNF    = 0;                                                              //disable USB module\r
757     USBPLLCTL &= ~UPLLEN;                                                       //disable PLL\r
758     USBKEYPID = 0x9600;                                                         //access to configuration registers disabled\r
759     bEnumerationStatus = 0x00;                                                  //device is not enumerated\r
760     bFunctionSuspended = FALSE;                                                 //device is not suspended\r
761     return (kUSB_succeed);\r
762 }\r
763 \r
764 //*****************************************************************************\r
765 //\r
766 //! Enables/Disables the Various USB Events.\r
767 //!\r
768 //! \param events is the mask for what is to be enabled/disabled.\r
769 //!       - Valid values are:\r
770 //!                     - \b kUSB_clockFaultEvent\r
771 //!                     - \b kUSB_VbusOnEvent\r
772 //!                     - \b kUSB_VbusOffEvent\r
773 //!                     - \b kUSB_UsbResetEvent\r
774 //!                     - \b kUSB_UsbSuspendEvent\r
775 //!                     - \b kUSB_UsbResumeEvent\r
776 //!                     - \b kUSBCDC_dataReceivedEvent\r
777 //!                     - \b kUSBCDC_sendCompletedEvent\r
778 //!                     - \b kUSBCDC_receiveCompletedEvent\r
779 //!                     - \b kUSBHID_dataReceivedEvent\r
780 //!                     - \b kUSBHID_sendCompletedEvent\r
781 //!                     - \b kUSBHID_receiveCompletedEvent\r
782 //!                     - \b kUSB_allUsbEvents\r
783 //!\r
784 //! Enables/disables various USB events. Within the events byte, all bits with\r
785 //! '1' values will be enabled, and all bits with '0' values will be disabled.\r
786 //! (There are no bit-wise operations). By default (that is, prior to any call \r
787 //! to this function), all events are disabled.\r
788 //! \r
789 //! The status of event enabling can be read with the USB_getEnabledEvents() \r
790 //! function. This call can be made at any time after a call to USB_init().\r
791 //! \r
792 //! USB_setEnabledEvents() can be thought of in a similar fashion to \r
793 //! setting/clearing interrupt enable bits. The only benefit in keeping an event \r
794 //! disabled is to save the unnecessary execution cycles incurred from running \r
795 //! an "empty" event handler.\r
796 //! \r
797 //! The mask constant \b kUSB_allUsbEvents is used to enable/disable all events \r
798 //! pertaining to core USB functions; in other words, it enables all those with \r
799 //! a \b kUSB_ prefix. \r
800 //! \r
801 //! See Sec. 10 of \e "Programmer's Guide: MSP430 USB API Stack for CDC/PHDC/HID/MSC" for more information about\r
802 //! events.\r
803 //! \r
804 //! \return \b kUSB_succeed\r
805 //\r
806 //*****************************************************************************\r
807 \r
808 uint8_t USB_setEnabledEvents (uint16_t events)\r
809 {\r
810     wUsbEventMask = events;\r
811     return (kUSB_succeed);\r
812 }\r
813 \r
814 //*****************************************************************************\r
815 //\r
816 //! Returns Which Events are Enabled/Disabled.\r
817 //!\r
818 //! Returns which events are enabled and which are disabled. The definition of \r
819 //! events is the same as for USB_enableEvents() above.\r
820 //! \r
821 //! If the bit is set, the event is enabled. If cleared, the event is disabled. \r
822 //! By default (that is, prior to calling USB_setEnabledEvents() ), all events \r
823 //! are disabled. This call can be made at any time after a call to USB_init().\r
824 //! \r
825 //! \return \b Events\r
826 //\r
827 //*****************************************************************************\r
828 \r
829 uint16_t USB_getEnabledEvents ()\r
830 {\r
831     return (wUsbEventMask);\r
832 }\r
833 \r
834 //*****************************************************************************\r
835 //\r
836 //! Resets the USB Module and the Internal State of the API.\r
837 //!\r
838 //! Resets the USB module and also the internal state of the API. The interrupt \r
839 //! register is cleared to make sure no interrupts are pending. If the device \r
840 //! had been enumerated, the enumeration is now lost. All open send/receive \r
841 //! operations are aborted. \r
842 //! \r
843 //! This function is most often called immediately before a call to \r
844 //! USB_connect(). It should not be called prior to USB_enable().\r
845 //!\r
846 //! \return \b kUSB_succeed\r
847 //\r
848 //*****************************************************************************\r
849 \r
850 uint8_t USB_reset ()\r
851 {\r
852     int16_t i;\r
853 \r
854     USBKEYPID = 0x9628;                                                             //set KEY and PID to 0x9628 -> access to\r
855                                                                                     //configuration registers enabled\r
856 \r
857     //reset should be on the bus after this!\r
858     bEnumerationStatus = 0x00;                                                      //Device not enumerated yet\r
859     bFunctionSuspended = FALSE;                                                     //Device is not in suspend mode\r
860 \r
861     bRemoteWakeup = DISABLE;\r
862 \r
863     bConfigurationNumber    = 0x00;                                                 //device unconfigured\r
864     bInterfaceNumber        = 0x00;\r
865 \r
866     //FRSTE handling:\r
867     //Clear FRSTE in the RESRIFG interrupt service routine before re-configuring USB control registers.\r
868     //Set FRSTE at the beginning of SUSRIFG, SETUP, IEPIFG.EP0 and OEPIFG.EP0 interrupt service routines.\r
869     USBCTL = 0;                                                                     //Function Reset Connection disable (FRSTE)\r
870 \r
871     wBytesRemainingOnIEP0   = NO_MORE_DATA;\r
872     wBytesRemainingOnOEP0   = NO_MORE_DATA;\r
873     bStatusAction           = STATUS_ACTION_NOTHING;\r
874 \r
875     //The address reset normally will be done automatically during bus function reset\r
876     USBFUNADR   =     0x00;                                                         //reset address of USB device (unconfigured)\r
877 \r
878     /* Set settings for EP0 */\r
879     //NAK both 0 endpoints and enable endpoint 0 interrupt\r
880     tEndPoint0DescriptorBlock.bIEPBCNT = EPBCNT_NAK;\r
881     tEndPoint0DescriptorBlock.bOEPBCNT = EPBCNT_NAK;\r
882     tEndPoint0DescriptorBlock.bIEPCNFG = EPCNF_USBIE | EPCNF_UBME | EPCNF_STALL;    //8 byte data packet\r
883     tEndPoint0DescriptorBlock.bOEPCNFG = EPCNF_USBIE | EPCNF_UBME | EPCNF_STALL;    //8 byte data packet\r
884 \r
885     USBOEPIE = USB_OUTEP_INT_EN;\r
886     USBIEPIE = USB_INEP_INT_EN;\r
887 \r
888     //loop for initialization all of used enpoints\r
889     for (i = 0;\r
890          i < (CDC_NUM_INTERFACES + HID_NUM_INTERFACES + MSC_NUM_INTERFACES + PHDC_NUM_INTERFACES);\r
891          i++)\r
892     {\r
893         uint8_t edbIndex = stUsbHandle[i].edb_Index;\r
894 \r
895         /* Set settings for IEPx */\r
896         tInputEndPointDescriptorBlock[edbIndex].bEPCNF   = EPCNF_USBIE |\r
897                                                            EPCNF_UBME |\r
898                                                            EPCNF_DBUF;              //double buffering\r
899         tInputEndPointDescriptorBlock[edbIndex].bEPBBAX  =\r
900             (uint8_t)(((stUsbHandle[i].iep_X_Buffer -\r
901                      START_OF_USB_BUFFER) >> 3) & 0x00ff);\r
902         tInputEndPointDescriptorBlock[edbIndex].bEPBBAY  =\r
903             (uint8_t)(((stUsbHandle[i].iep_Y_Buffer -\r
904                      START_OF_USB_BUFFER) >> 3) & 0x00ff);\r
905         tInputEndPointDescriptorBlock[edbIndex].bEPBCTX  = EPBCNT_NAK;\r
906         tInputEndPointDescriptorBlock[edbIndex].bEPBCTY  = EPBCNT_NAK;\r
907         tInputEndPointDescriptorBlock[edbIndex].bEPSIZXY = MAX_PACKET_SIZE;\r
908 \r
909         /* Set settings for OEPx */\r
910 #ifdef BRIDGE_CDC_PRESENT\r
911         if (i == BRIDGE_CDC_INTFNUM) {\r
912             tOutputEndPointDescriptorBlock[edbIndex].bEPCNF   = EPCNF_USBIE |\r
913                                                                 EPCNF_UBME;            \r
914         }\r
915         else\r
916         {\r
917             tOutputEndPointDescriptorBlock[edbIndex].bEPCNF   = EPCNF_USBIE |\r
918                                                                 EPCNF_UBME |\r
919                                                                 EPCNF_DBUF ;            //double buffering\r
920         }\r
921 #else        \r
922         tOutputEndPointDescriptorBlock[edbIndex].bEPCNF   = EPCNF_USBIE |\r
923                                                             EPCNF_UBME |\r
924                                                             EPCNF_DBUF ;            //double buffering\r
925 #endif\r
926         \r
927         tOutputEndPointDescriptorBlock[edbIndex].bEPBBAX  =\r
928             (uint8_t)(((stUsbHandle[i].oep_X_Buffer -\r
929                      START_OF_USB_BUFFER) >> 3) & 0x00ff);\r
930         tOutputEndPointDescriptorBlock[edbIndex].bEPBBAY  =\r
931             (uint8_t)(((stUsbHandle[i].oep_Y_Buffer -\r
932                      START_OF_USB_BUFFER) >> 3) & 0x00ff);\r
933         tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX  = 0x00;\r
934         tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY  = 0x00;\r
935         tOutputEndPointDescriptorBlock[edbIndex].bEPSIZXY = MAX_PACKET_SIZE;\r
936 \r
937 #       ifdef _CDC_\r
938         /* Additional interrupt end point for CDC */\r
939         if (stUsbHandle[i].dev_Class == CDC_CLASS){\r
940             //The decriptor tool always generates the managemnet endpoint before the data endpoint\r
941             tInputEndPointDescriptorBlock[edbIndex -\r
942                                           1].bEPCNF   = EPCNF_USBIE |\r
943                                                         EPCNF_UBME | EPCNF_DBUF;    //double buffering\r
944             tInputEndPointDescriptorBlock[edbIndex -\r
945                                           1].bEPBBAX  =\r
946                 (uint8_t)(((stUsbHandle[i].intepEP_X_Buffer -\r
947                          START_OF_USB_BUFFER) >> 3) & 0x00ff);\r
948             tInputEndPointDescriptorBlock[edbIndex -\r
949                                           1].bEPBBAY  =\r
950                 (uint8_t)(((stUsbHandle[i].intepEP_Y_Buffer -\r
951                          START_OF_USB_BUFFER) >> 3) & 0x00ff);\r
952             tInputEndPointDescriptorBlock[edbIndex - 1].bEPBCTX  = EPBCNT_NAK;\r
953             tInputEndPointDescriptorBlock[edbIndex - 1].bEPBCTY  = EPBCNT_NAK;\r
954             tInputEndPointDescriptorBlock[edbIndex -\r
955                                           1].bEPSIZXY = MAX_PACKET_SIZE;\r
956         }\r
957 #       endif\r
958     }\r
959 \r
960 #   ifdef _HID_\r
961     HidResetData();                                                                 //reset HID specific data structures\r
962 #   endif //_HID_\r
963 \r
964 #   ifdef _MSC_\r
965     MscState.isMSCConfigured = FALSE;\r
966     USBMSC_reset();\r
967     MscResetData();\r
968 #   endif\r
969 \r
970 #   ifdef _CDC_\r
971     CdcResetData();                                                                 //reset CDC specific data structures\r
972 #   endif //_CDC_\r
973 \r
974 #   ifdef _PHDC_\r
975         PHDCResetData();                     // reset CDC specific data structures\r
976 #   endif // _PHDC_\r
977 \r
978     USBCTL = FEN;                                                                   //enable function\r
979     USBIFG = 0;                                                                     //make sure no interrupts are pending\r
980 \r
981     USBIE = SETUPIE | RSTRIE | SUSRIE;                                              //enable USB specific interrupts (setup, reset,\r
982                                                                                     //suspend)\r
983     USBKEYPID = 0x9600;                                                             //access to configuration registers disabled\r
984     return (kUSB_succeed);\r
985 }\r
986 \r
987 //*****************************************************************************\r
988 //\r
989 //! Makes USB Module Available to Host for Connection.\r
990 //!\r
991 //! Instructs the USB module to make itself available to the host for \r
992 //! connection, by pulling the D+ signal high using the PUR pin. This call \r
993 //! should only be made after a call to USB_enable().\r
994 //!\r
995 //! \return \b kUSB_succeed\r
996 //\r
997 //*****************************************************************************\r
998 \r
999 uint8_t USB_connect ()\r
1000 {\r
1001     USBKEYPID = 0x9628;                                                             //set KEY and PID to 0x9628 -> access to\r
1002                                                                                     //configuration registers enabled\r
1003     USBCNF |= PUR_EN;                                                               //generate rising edge on DP -> the host\r
1004                                                                                     //enumerates our device as full speed device\r
1005     USBPWRCTL |= VBOFFIE;                                                           //enable interrupt VUSBoff\r
1006     USBKEYPID = 0x9600;                                                             //access to configuration registers disabled\r
1007 \r
1008     return (kUSB_succeed);\r
1009 }\r
1010 \r
1011 //*****************************************************************************\r
1012 //\r
1013 //! Forces a Disconnect From the USB Host.\r
1014 //!\r
1015 //! Forces a logical disconnect from the USB host by pulling the PUR pin low, \r
1016 //! removing the pullup on the D+ signal. The USB module and PLL remain enabled.\r
1017 //! If the USB is not connected when this call is made, no error is returned -\r
1018 //! the call simply exits with success after ensuring PUR is low.\r
1019 //!\r
1020 //! \return \b kUSB_succeed\r
1021 //\r
1022 //*****************************************************************************\r
1023 \r
1024 uint8_t USB_disconnect ()\r
1025 {\r
1026     USBKEYPID = 0x9628;                                                             //set KEY and PID to 0x9628 -> access to\r
1027                                                                                     //configuration registers enabled\r
1028     USBCNF &= ~PUR_EN;                                                              //disconnect pull up resistor - logical\r
1029                                                                                     //disconnect from HOST\r
1030     USBPWRCTL &= ~VBOFFIE;                                                          //disable interrupt VUSBoff\r
1031     USBKEYPID = 0x9600;                                                             //access to configuration registers disabled\r
1032     bEnumerationStatus = 0;                                                         //not enumerated\r
1033     bFunctionSuspended = FALSE;                                                     //device is not suspended\r
1034     return (kUSB_succeed);\r
1035 }\r
1036 \r
1037 //*****************************************************************************\r
1038 //\r
1039 //! Remote Wakeup of USB Host.\r
1040 //!\r
1041 //! Prompts a remote wakeup of the USB host. The user must ensure that the USB \r
1042 //! descriptors had indicated remote wakeup capability (using the Descriptor \r
1043 //! Tool); otherwise the host will ignore the request.\r
1044 //! \r
1045 //! If the function returns \b kUSB_generalError, it means that the host did not \r
1046 //! grant the device the ability to perform a remote wakeup, when it enumerated \r
1047 //! the device.\r
1048 //!\r
1049 //! \return \b kUSB_succeed, \b kUSBgeneralError or \b kUSB_notSuspended.\r
1050 //\r
1051 //*****************************************************************************\r
1052 \r
1053 uint8_t USB_forceRemoteWakeup ()\r
1054 {\r
1055     if (bFunctionSuspended == FALSE){                                               //device is not suspended\r
1056         return (kUSB_NotSuspended);\r
1057     }\r
1058     if (bRemoteWakeup == ENABLE){\r
1059         volatile uint16_t i;\r
1060         USBCTL |= RWUP;                                                             //USB - Device Remote Wakeup Request - this bit\r
1061                                                                                     //is self-cleaned\r
1062         return (kUSB_succeed);\r
1063     }\r
1064     return (kUSB_generalError);\r
1065 }\r
1066 \r
1067 //*****************************************************************************\r
1068 //\r
1069 //! Gets Connection Info.\r
1070 //! \r
1071 //! Returns low-level status information about the USB connection.\r
1072 //! \r
1073 //! Because multiple flags can be returned, the possible values can be masked \r
1074 //! together - for example, \b kUSB_vbusPresent + \b kUSB_suspended.\r
1075 //!\r
1076 //! \return A single mask that is the all the statuses together and may\r
1077 //!             consist of the following:\r
1078 //!                             - \b kUSB_purHigh\r
1079 //!                             - \b kUSB_suspended\r
1080 //!                             - \b kUSB_NotSuspended\r
1081 //!                             - \b kUSB_Enumerated\r
1082 //!                             - \b kUSB_vbusPresent\r
1083 //\r
1084 //*****************************************************************************\r
1085 \r
1086 uint8_t USB_connectionInfo ()\r
1087 {\r
1088     uint8_t retVal = 0;\r
1089 \r
1090     if (USBPWRCTL & USBBGVBV){\r
1091         retVal |= kUSB_vbusPresent;\r
1092     }\r
1093 \r
1094     if (bEnumerationStatus == ENUMERATION_COMPLETE){\r
1095         retVal |= kUSB_Enumerated;\r
1096     }\r
1097 \r
1098     if (USBCNF & PUR_EN){\r
1099         retVal |= kUSB_purHigh;\r
1100     }\r
1101 \r
1102     if (bFunctionSuspended == TRUE){\r
1103         retVal |= kUSB_suspended;\r
1104     } else {\r
1105         retVal |= kUSB_NotSuspended;\r
1106     }\r
1107     return (retVal);\r
1108 }\r
1109 \r
1110 //*****************************************************************************\r
1111 //\r
1112 //! Gets State of the USB Connection.\r
1113 //!\r
1114 //! Returns the state of the USB connection, according to the state diagram \r
1115 //! in Sec. 6 of \e "Programmer's Guide: MSP430 USB API Stack for CDC/PHDC/HID/MSC".\r
1116 //! \r
1117 //! \return Any of the following: \r
1118 //!                     - \b ST_USB_DISCONNECTED\r
1119 //!                     - \b ST_USB_CONNECTED_NO_ENUM\r
1120 //!                     - \b ST_ENUM_IN_PROGRESS\r
1121 //!                     - \b ST_ENUM_ACTIVE\r
1122 //!                     - \b ST_ENUM_SUSPENDED\r
1123 //!                     - \b ST_NOENUM_SUSPENDED,\r
1124 //!                     - \b ST_ERROR.\r
1125 //\r
1126 //*****************************************************************************\r
1127 \r
1128 uint8_t USB_connectionState ()\r
1129 {\r
1130     //If no VBUS present\r
1131     if (!(USBPWRCTL & USBBGVBV)){\r
1132         return (ST_USB_DISCONNECTED);\r
1133     }\r
1134 \r
1135     //If VBUS present, but PUR is low\r
1136     if ((USBPWRCTL & USBBGVBV) && (!(USBCNF & PUR_EN))){\r
1137         return (ST_USB_CONNECTED_NO_ENUM);\r
1138     }\r
1139 \r
1140     //If VBUS present, PUR is high, and enumeration is complete, and not suspended\r
1141     if ((USBPWRCTL & USBBGVBV) && (USBCNF & PUR_EN)\r
1142         && (bEnumerationStatus == ENUMERATION_COMPLETE)\r
1143         && (!(bFunctionSuspended == TRUE))){\r
1144         return (ST_ENUM_ACTIVE);\r
1145     }\r
1146 \r
1147     //If VBUS present, PUR is high, and enumeration is NOT complete, and  suspended\r
1148     if ((USBPWRCTL & USBBGVBV) && (USBCNF & PUR_EN)\r
1149         && (!(bEnumerationStatus == ENUMERATION_COMPLETE))\r
1150         && (bFunctionSuspended == TRUE)){\r
1151         return (ST_NOENUM_SUSPENDED);\r
1152     }\r
1153 \r
1154     //If VBUS present, PUR is high, and enumeration is complete, and  suspended\r
1155     if ((USBPWRCTL & USBBGVBV) && (USBCNF & PUR_EN)\r
1156         && (bEnumerationStatus == ENUMERATION_COMPLETE)\r
1157         && (bFunctionSuspended == TRUE)){\r
1158         return (ST_ENUM_SUSPENDED);\r
1159     }\r
1160 \r
1161     //If VBUS present, PUR is high, but no enumeration yet\r
1162     if ((USBPWRCTL & USBBGVBV) && (USBCNF & PUR_EN)\r
1163         && (!(bEnumerationStatus == ENUMERATION_COMPLETE))){\r
1164         return (ST_ENUM_IN_PROGRESS);\r
1165     }\r
1166 \r
1167     return (ST_ERROR);\r
1168 }\r
1169 \r
1170 //\r
1171 //! \cond\r
1172 //\r
1173 \r
1174 //----------------------------------------------------------------------------\r
1175 \r
1176 uint8_t USB_suspend (void)\r
1177 {\r
1178     bFunctionSuspended  = TRUE;\r
1179     USBKEYPID = 0x9628;                 //set KEY and PID to 0x9628 -> access to configuration registers enabled\r
1180     USBCTL |= FRSTE;                    //Function Reset Connection Enable\r
1181     USBIFG &= ~SUSRIFG;                 //clear interrupt flag\r
1182 \r
1183     USBPLLCTL &= ~UPLLEN;\r
1184 \r
1185     if (USB_DISABLE_XT_SUSPEND){\r
1186 #ifndef DRIVERLIB_LEGACY_MODE\r
1187         UCS_XT2Off();         //disable XT2\r
1188 #else\r
1189         UCS_XT2Off(UCS_BASE);         //disable XT2\r
1190 #endif\r
1191     }\r
1192 \r
1193     USBIE = RESRIE;                     //disable USB specific interrupts (setup, suspend, reset), enable resume.\r
1194                                         //If the reset occured during device in suspend, the resume-interrupt will come, after -\r
1195                                         //reset interrupt\r
1196     USBKEYPID = 0x9600;                 //access to configuration registers disabled\r
1197 \r
1198     return (kUSB_succeed);\r
1199 }\r
1200 \r
1201 //----------------------------------------------------------------------------\r
1202 \r
1203 uint8_t USB_resume (void)\r
1204 {\r
1205     USB_enable();                       //enable PLL\r
1206 \r
1207     USBIFG &= ~(RESRIFG | SUSRIFG);     //clear interrupt flags\r
1208     USBIE = SETUPIE | RSTRIE | SUSRIE;  //enable USB specific interrupts (setup, reset, suspend)\r
1209 \r
1210     bFunctionSuspended  = FALSE;\r
1211     return (kUSB_succeed);\r
1212 }\r
1213 \r
1214 //----------------------------------------------------------------------------\r
1215 \r
1216 void usbStallEndpoint0 (void)\r
1217 {\r
1218     tEndPoint0DescriptorBlock.bIEPCNFG |= EPCNF_STALL;\r
1219     tEndPoint0DescriptorBlock.bOEPCNFG |= EPCNF_STALL;\r
1220 }\r
1221 \r
1222 //----------------------------------------------------------------------------\r
1223 \r
1224 void usbClearOEP0ByteCount (void)\r
1225 {\r
1226     tEndPoint0DescriptorBlock.bOEPBCNT = 0x00;\r
1227 }\r
1228 \r
1229 //----------------------------------------------------------------------------\r
1230 \r
1231 void usbStallOEP0 (void)\r
1232 {\r
1233     //in standard USB request, there is not control write request with data stage\r
1234     //control write, stall output endpoint 0\r
1235     //wLength should be 0 in all cases\r
1236     tEndPoint0DescriptorBlock.bOEPCNFG |= EPCNF_STALL;\r
1237 }\r
1238 \r
1239 //----------------------------------------------------------------------------\r
1240 \r
1241 void usbSendNextPacketOnIEP0 (void)\r
1242 {\r
1243     uint8_t bPacketSize,bIndex;\r
1244 \r
1245     //First check if there are bytes remaining to be transferred\r
1246     if (wBytesRemainingOnIEP0 != NO_MORE_DATA){\r
1247         if (wBytesRemainingOnIEP0 > EP0_PACKET_SIZE){\r
1248             //More bytes are remaining than will fit in one packet\r
1249             //there will be More IN Stage\r
1250             bPacketSize = EP0_PACKET_SIZE;\r
1251             wBytesRemainingOnIEP0 -= EP0_PACKET_SIZE;\r
1252             bStatusAction = STATUS_ACTION_DATA_IN;\r
1253         } else if (wBytesRemainingOnIEP0 < EP0_PACKET_SIZE){\r
1254             //The remaining data will fit in one packet.\r
1255             //This case will properly handle wBytesRemainingOnIEP0 == 0\r
1256             bPacketSize = (uint8_t)wBytesRemainingOnIEP0;\r
1257             wBytesRemainingOnIEP0 = NO_MORE_DATA;   //No more data need to be Txed\r
1258             bStatusAction = STATUS_ACTION_NOTHING;\r
1259         } else {\r
1260             bPacketSize = EP0_PACKET_SIZE;\r
1261             if (bHostAskMoreDataThanAvailable == TRUE){\r
1262                 wBytesRemainingOnIEP0 = 0;\r
1263                 bStatusAction = STATUS_ACTION_DATA_IN;\r
1264             } else {\r
1265                 wBytesRemainingOnIEP0 = NO_MORE_DATA;\r
1266                 bStatusAction = STATUS_ACTION_NOTHING;\r
1267             }\r
1268         }\r
1269 \r
1270         for (bIndex = 0; bIndex < bPacketSize; bIndex++)\r
1271         {\r
1272             abIEP0Buffer[bIndex] = *pbIEP0Buffer;\r
1273             pbIEP0Buffer++;\r
1274         }\r
1275         tEndPoint0DescriptorBlock.bIEPBCNT = bPacketSize;\r
1276     } else {\r
1277         bStatusAction = STATUS_ACTION_NOTHING;\r
1278     }\r
1279 }\r
1280 \r
1281 //----------------------------------------------------------------------------\r
1282 \r
1283 void usbSendDataPacketOnEP0 (const uint8_t* pbBuffer)\r
1284 {\r
1285     uint16_t wTemp;\r
1286 \r
1287     pbIEP0Buffer = pbBuffer;\r
1288     wTemp = tSetupPacket.wLength;\r
1289 \r
1290     //Limit transfer size to wLength if needed\r
1291     //this prevent USB device sending 'more than require' data back to host\r
1292     if (wBytesRemainingOnIEP0 >= wTemp){\r
1293         wBytesRemainingOnIEP0 = wTemp;\r
1294         bHostAskMoreDataThanAvailable = FALSE;\r
1295     } else {\r
1296         bHostAskMoreDataThanAvailable = TRUE;\r
1297     }\r
1298     usbSendNextPacketOnIEP0();\r
1299 }\r
1300 \r
1301 //----------------------------------------------------------------------------\r
1302 void usbReceiveNextPacketOnOEP0 (void)\r
1303 {\r
1304     uint8_t bIndex,bByte;\r
1305 \r
1306     bByte = tEndPoint0DescriptorBlock.bOEPBCNT & EPBCNT_BYTECNT_MASK;\r
1307 \r
1308     if (wBytesRemainingOnOEP0 >= (uint16_t)bByte){\r
1309         for (bIndex = 0; bIndex < bByte; bIndex++)\r
1310         {\r
1311             *pbOEP0Buffer = abOEP0Buffer[bIndex];\r
1312             pbOEP0Buffer++;\r
1313         }\r
1314         wBytesRemainingOnOEP0 -= (uint16_t)bByte;\r
1315 \r
1316         //clear the NAK bit for next packet\r
1317         if (wBytesRemainingOnOEP0 > 0){\r
1318             usbClearOEP0ByteCount();\r
1319             bStatusAction = STATUS_ACTION_DATA_OUT;\r
1320         } else {\r
1321             usbStallOEP0();\r
1322             bStatusAction = STATUS_ACTION_NOTHING;\r
1323         }\r
1324     } else {\r
1325         usbStallOEP0();\r
1326         bStatusAction = STATUS_ACTION_NOTHING;\r
1327     }\r
1328 }\r
1329 \r
1330 //----------------------------------------------------------------------------\r
1331 \r
1332 void usbReceiveDataPacketOnEP0 (uint8_t* pbBuffer)\r
1333 {\r
1334     pbOEP0Buffer = pbBuffer;\r
1335 \r
1336     wBytesRemainingOnOEP0 = tSetupPacket.wLength;\r
1337     bStatusAction = STATUS_ACTION_DATA_OUT;\r
1338 \r
1339     usbClearOEP0ByteCount();\r
1340 }\r
1341 \r
1342 //----------------------------------------------------------------------------\r
1343 \r
1344 void usbSendZeroLengthPacketOnIEP0 (void)\r
1345 {\r
1346     wBytesRemainingOnIEP0 = NO_MORE_DATA;\r
1347     bStatusAction = STATUS_ACTION_NOTHING;\r
1348     tEndPoint0DescriptorBlock.bIEPBCNT = 0x00;\r
1349 }\r
1350 \r
1351 //----------------------------------------------------------------------------\r
1352 \r
1353 uint8_t usbClearEndpointFeature (void)\r
1354 {\r
1355     uint8_t bEndpointNumber;\r
1356 \r
1357     //EP is from EP1 to EP7 while C language start from 0\r
1358     bEndpointNumber = (tSetupPacket.wIndex & EP_DESC_ADDR_EP_NUM);\r
1359     if (bEndpointNumber == 0x00){\r
1360         usbSendZeroLengthPacketOnIEP0();\r
1361     } else {\r
1362         bEndpointNumber--;\r
1363         if (bEndpointNumber < MAX_ENDPOINT_NUMBER){\r
1364             if ((tSetupPacket.wIndex & EP_DESC_ADDR_DIR_IN) ==\r
1365                 EP_DESC_ADDR_DIR_IN){\r
1366 #ifdef _MSC_\r
1367                 if (!MscState.bMscResetRequired){\r
1368 #endif\r
1369                 tInputEndPointDescriptorBlock[bEndpointNumber].bEPCNF &=\r
1370                     ~(EPCNF_STALL | EPCNF_TOGGLE );\r
1371 #ifdef _MSC_\r
1372             }\r
1373 #endif\r
1374 #               ifdef _MSC_\r
1375                 if (stUsbHandle[MSC0_INTFNUM].edb_Index == bEndpointNumber){\r
1376                     MscReadControl.bCurrentBufferXY = 0;    //Set current buffer to X\r
1377                     MscState.bMcsCommandSupported = TRUE;\r
1378                 }\r
1379 #               endif\r
1380             } else {\r
1381 #ifdef _MSC_\r
1382                 if (!MscState.bMscResetRequired){\r
1383 #endif\r
1384                                         tOutputEndPointDescriptorBlock[bEndpointNumber].bEPCNF &=\r
1385                                                 ~(EPCNF_STALL | EPCNF_TOGGLE );\r
1386 #ifdef _MSC_                                            \r
1387                                         tOutputEndPointDescriptorBlock[bEndpointNumber].bEPBCTX = 0;\r
1388                     tOutputEndPointDescriptorBlock[bEndpointNumber].bEPBCTY = 0;\r
1389                     MscState.stallEndpoint = FALSE;\r
1390 #endif                                  \r
1391 #ifdef _MSC_\r
1392             }\r
1393 #endif\r
1394 #               ifdef _MSC_\r
1395                 if (stUsbHandle[MSC0_INTFNUM].edb_Index == bEndpointNumber){\r
1396                     MscWriteControl.bCurrentBufferXY = 0;   //Set current buffer to X\r
1397                     MscState.bMcsCommandSupported = TRUE;\r
1398                 }\r
1399 #               endif\r
1400             }\r
1401             usbSendZeroLengthPacketOnIEP0();\r
1402         }\r
1403     }\r
1404 \r
1405     return (FALSE);\r
1406 }\r
1407 \r
1408 //----------------------------------------------------------------------------\r
1409 \r
1410 uint8_t usbGetConfiguration (void)\r
1411 {\r
1412     usbClearOEP0ByteCount();                                //for status stage\r
1413     wBytesRemainingOnIEP0 = 1;\r
1414     usbSendDataPacketOnEP0((uint8_t*)&bConfigurationNumber);\r
1415 \r
1416     return (FALSE);\r
1417 }\r
1418 \r
1419 //----------------------------------------------------------------------------\r
1420 \r
1421 uint8_t usbGetDeviceDescriptor (void)\r
1422 {\r
1423     usbClearOEP0ByteCount();\r
1424     wBytesRemainingOnIEP0 = SIZEOF_DEVICE_DESCRIPTOR;\r
1425 #ifdef NON_COMPOSITE_MULTIPLE_INTERFACES\r
1426     usbSendDataPacketOnEP0((uint8_t*)usbDeviceDescriptors[activeInterfaceIndex]);\r
1427 #else\r
1428     usbSendDataPacketOnEP0((uint8_t*)&abromDeviceDescriptor);\r
1429 #endif\r
1430     return (FALSE);\r
1431 }\r
1432 \r
1433 //----------------------------------------------------------------------------\r
1434 \r
1435 uint8_t usbGetConfigurationDescriptor (void)\r
1436 {\r
1437     usbClearOEP0ByteCount();\r
1438 #ifdef NON_COMPOSITE_MULTIPLE_INTERFACES\r
1439     wBytesRemainingOnIEP0 = usbConfigurationsSizes[activeInterfaceIndex];\r
1440     usbSendDataPacketOnEP0((uint8_t*)usbConfigurationDescriptors[activeInterfaceIndex]);\r
1441 #else\r
1442     wBytesRemainingOnIEP0 = sizeof(abromConfigurationDescriptorGroup);\r
1443     usbSendDataPacketOnEP0((uint8_t*)&abromConfigurationDescriptorGroup);\r
1444 #endif  \r
1445 \r
1446     return (FALSE);\r
1447 }\r
1448 \r
1449 //----------------------------------------------------------------------------\r
1450 \r
1451 uint8_t usbGetStringDescriptor (void)\r
1452 {\r
1453     uint16_t bIndex;\r
1454     uint8_t bVal = (uint8_t)tSetupPacket.wValue;\r
1455 \r
1456     usbClearOEP0ByteCount();    //for status stage\r
1457     if (bVal <= MAX_STRING_DESCRIPTOR_INDEX) {\r
1458 #if (USB_STR_INDEX_SERNUM != 0)\r
1459         if (bVal == 0x03){\r
1460             wBytesRemainingOnIEP0 = abramSerialStringDescriptor[0];\r
1461             usbSendDataPacketOnEP0((uint8_t*)&abramSerialStringDescriptor);\r
1462         } else\r
1463 #endif\r
1464         {\r
1465             bIndex = 0x00;\r
1466             while (bVal-- >  0x00) bIndex += abromStringDescriptor[bIndex];\r
1467             wBytesRemainingOnIEP0 = abromStringDescriptor[bIndex];\r
1468             usbSendDataPacketOnEP0((uint8_t*)&abromStringDescriptor[bIndex]);\r
1469         }\r
1470     }\r
1471     else {\r
1472         usbStallEndpoint0();\r
1473     }\r
1474 \r
1475     return (FALSE);\r
1476 }\r
1477 \r
1478 //----------------------------------------------------------------------------\r
1479 \r
1480 uint8_t usbGetInterface (void)\r
1481 {\r
1482     //not fully supported, return one byte, zero\r
1483     usbClearOEP0ByteCount();            //for status stage\r
1484     wBytesRemainingOnIEP0 = 0x02;\r
1485     abUsbRequestReturnData[0] = 0x00;   //changed to report alternative setting byte\r
1486     abUsbRequestReturnData[1] = bInterfaceNumber;\r
1487     usbSendDataPacketOnEP0((uint8_t*)&abUsbRequestReturnData[0]);\r
1488 \r
1489     return (FALSE);\r
1490 }\r
1491 \r
1492 //----------------------------------------------------------------------------\r
1493 \r
1494 uint8_t usbGetDeviceStatus (void)\r
1495 {\r
1496 #ifdef NON_COMPOSITE_MULTIPLE_INTERFACES\r
1497         if ((((struct abromConfigurationDescriptorGroup *)\r
1498                 usbConfigurationDescriptors[activeInterfaceIndex])->\r
1499                 abromConfigurationDescriptorGenric.mattributes  &\r
1500                 CFG_DESC_ATTR_SELF_POWERED) == CFG_DESC_ATTR_SELF_POWERED){\r
1501         abUsbRequestReturnData[0] = DEVICE_STATUS_SELF_POWER;\r
1502     }\r
1503 #else\r
1504     if ((abromConfigurationDescriptorGroup.abromConfigurationDescriptorGenric.\r
1505          mattributes &\r
1506          CFG_DESC_ATTR_SELF_POWERED) == CFG_DESC_ATTR_SELF_POWERED){\r
1507         abUsbRequestReturnData[0] = DEVICE_STATUS_SELF_POWER;\r
1508     }\r
1509 #endif  \r
1510     if (bRemoteWakeup == ENABLE){\r
1511         abUsbRequestReturnData[0] |= DEVICE_STATUS_REMOTE_WAKEUP;\r
1512     }\r
1513     usbClearOEP0ByteCount();            //for status stage\r
1514 \r
1515     //Return self power status and remote wakeup status\r
1516     wBytesRemainingOnIEP0 = 2;\r
1517     usbSendDataPacketOnEP0((uint8_t*)&abUsbRequestReturnData[0]);\r
1518 \r
1519     return (FALSE);\r
1520 }\r
1521 \r
1522 //----------------------------------------------------------------------------\r
1523 \r
1524 uint8_t usbGetInterfaceStatus (void)\r
1525 {\r
1526     //check bIndexL for index number (not supported)\r
1527     usbClearOEP0ByteCount();            //for status stage\r
1528 \r
1529     //Return two zero bytes\r
1530     wBytesRemainingOnIEP0 = 2;\r
1531     abUsbRequestReturnData[0] = 0x00;   //changed to support multiple interfaces\r
1532     abUsbRequestReturnData[1] = bInterfaceNumber;\r
1533     usbSendDataPacketOnEP0((uint8_t*)&abUsbRequestReturnData[0]);\r
1534 \r
1535     return (FALSE);\r
1536 }\r
1537 \r
1538 //----------------------------------------------------------------------------\r
1539 \r
1540 uint8_t usbGetEndpointStatus (void)\r
1541 {\r
1542     uint8_t bEndpointNumber;\r
1543 \r
1544     //Endpoint number is bIndexL\r
1545     bEndpointNumber = tSetupPacket.wIndex & EP_DESC_ADDR_EP_NUM;\r
1546     if (bEndpointNumber == 0x00){\r
1547         if ((tSetupPacket.wIndex & EP_DESC_ADDR_DIR_IN) ==\r
1548             EP_DESC_ADDR_DIR_IN){\r
1549             //input endpoint 0\r
1550             abUsbRequestReturnData[0] =\r
1551                 (uint8_t)(tEndPoint0DescriptorBlock.bIEPCNFG & EPCNF_STALL);\r
1552         } else {\r
1553             //output endpoint 0\r
1554             abUsbRequestReturnData[0] =\r
1555                 (uint8_t)(tEndPoint0DescriptorBlock.bOEPCNFG & EPCNF_STALL);\r
1556         }\r
1557         abUsbRequestReturnData[0] = abUsbRequestReturnData[0] >> 3; //STALL is on bit 3\r
1558         usbClearOEP0ByteCount();                                    //for status stage\r
1559         wBytesRemainingOnIEP0 = 0x02;\r
1560         usbSendDataPacketOnEP0((uint8_t*)&abUsbRequestReturnData[0]);\r
1561     } else {\r
1562         bEndpointNumber--;\r
1563         //EP is from EP1 to EP7 while C language start from 0\r
1564         //Firmware should NOT response if specified endpoint is not supported. (charpter 8)\r
1565         if (bEndpointNumber < MAX_ENDPOINT_NUMBER){\r
1566             if (tSetupPacket.wIndex & EP_DESC_ADDR_DIR_IN){\r
1567                 //input endpoint\r
1568                 abUsbRequestReturnData[0] =\r
1569                     (uint8_t)(tInputEndPointDescriptorBlock[bEndpointNumber].\r
1570                            bEPCNF &\r
1571                            EPCNF_STALL);\r
1572             } else {\r
1573                 //output endpoint\r
1574                 abUsbRequestReturnData[0] =\r
1575                     (uint8_t)(tOutputEndPointDescriptorBlock[bEndpointNumber].\r
1576                            bEPCNF &\r
1577                            EPCNF_STALL);\r
1578             }\r
1579         }                                                           //no response if endpoint is not supported.\r
1580         abUsbRequestReturnData[0] = abUsbRequestReturnData[0] >> 3; //STALL is on bit 3\r
1581         usbClearOEP0ByteCount();\r
1582         wBytesRemainingOnIEP0 = 0x02;\r
1583         usbSendDataPacketOnEP0((uint8_t*)&abUsbRequestReturnData[0]);\r
1584     }\r
1585 \r
1586     return (FALSE);\r
1587 }\r
1588 \r
1589 //----------------------------------------------------------------------------\r
1590 uint8_t usbSetAddress (void)\r
1591 {\r
1592     usbStallOEP0();                                                 //control write without data stage\r
1593 \r
1594     //bValueL contains device address\r
1595     if (tSetupPacket.wValue < 128){\r
1596         //hardware will update the address after status stage\r
1597         //therefore, firmware can set the address now.\r
1598         USBFUNADR = tSetupPacket.wValue;\r
1599         usbSendZeroLengthPacketOnIEP0();\r
1600     } else {\r
1601         usbStallEndpoint0();\r
1602     }\r
1603 \r
1604     return (FALSE);\r
1605 }\r
1606 \r
1607 //----------------------------------------------------------------------------\r
1608 \r
1609 uint8_t usbSetConfiguration (void)\r
1610 {\r
1611         uint8_t bWakeUp = FALSE;\r
1612 \r
1613     usbStallOEP0();                                                 //control write without data stage\r
1614 \r
1615     //configuration number is in bValueL\r
1616     //change the code if more than one configuration is supported\r
1617     bConfigurationNumber = tSetupPacket.wValue;\r
1618     usbSendZeroLengthPacketOnIEP0();\r
1619 \r
1620     if (bConfigurationNumber == 1){\r
1621         bEnumerationStatus = ENUMERATION_COMPLETE;                  //set device as enumerated\r
1622         //perform enumeration complete event:\r
1623         bWakeUp = USB_handleEnumCompleteEvent();\r
1624     } else {\r
1625         bEnumerationStatus = 0;                                     //device is not configured == config # is zero\r
1626     }\r
1627 \r
1628     return (bWakeUp);\r
1629 }\r
1630 \r
1631 //----------------------------------------------------------------------------\r
1632 \r
1633 uint8_t usbClearDeviceFeature (void)\r
1634 {\r
1635     //bValueL contains feature selector\r
1636     if (tSetupPacket.wValue == FEATURE_REMOTE_WAKEUP){\r
1637         bRemoteWakeup = DISABLE;\r
1638         usbSendZeroLengthPacketOnIEP0();\r
1639     } else {\r
1640         usbStallEndpoint0();\r
1641     }\r
1642 \r
1643     return (FALSE);\r
1644 }\r
1645 \r
1646 //----------------------------------------------------------------------------\r
1647 \r
1648 uint8_t usbSetDeviceFeature (void)\r
1649 {\r
1650     //bValueL contains feature selector\r
1651     if (tSetupPacket.wValue == FEATURE_REMOTE_WAKEUP){\r
1652         bRemoteWakeup = ENABLE;\r
1653         usbSendZeroLengthPacketOnIEP0();\r
1654     } else {\r
1655         usbStallEndpoint0();\r
1656     }\r
1657 \r
1658     return (FALSE);\r
1659 }\r
1660 \r
1661 //----------------------------------------------------------------------------\r
1662 \r
1663 uint8_t usbSetEndpointFeature (void)\r
1664 {\r
1665     uint8_t bEndpointNumber;\r
1666 \r
1667     //wValue contains feature selector\r
1668     //bIndexL contains endpoint number\r
1669     //Endpoint number is in low byte of wIndex\r
1670     if (tSetupPacket.wValue == FEATURE_ENDPOINT_STALL){\r
1671         bEndpointNumber = tSetupPacket.wIndex & EP_DESC_ADDR_EP_NUM;\r
1672         if (bEndpointNumber == 0x00){\r
1673             usbSendZeroLengthPacketOnIEP0();    //do nothing for endpoint 0\r
1674         } else {\r
1675             bEndpointNumber--;\r
1676             //Firmware should NOT response if specified endpoint is not supported. (charpter 8)\r
1677             if (bEndpointNumber < MAX_ENDPOINT_NUMBER){\r
1678                 if (tSetupPacket.wIndex & EP_DESC_ADDR_DIR_IN){\r
1679                     //input endpoint\r
1680                     tInputEndPointDescriptorBlock[bEndpointNumber].bEPCNF |=\r
1681                         EPCNF_STALL;\r
1682                 } else {\r
1683                     //output endpoint\r
1684                     tOutputEndPointDescriptorBlock[bEndpointNumber].bEPCNF |=\r
1685                         EPCNF_STALL;\r
1686                 }\r
1687                 usbSendZeroLengthPacketOnIEP0();\r
1688             } //no response if endpoint is not supported.\r
1689         }\r
1690     } else {\r
1691         usbStallEndpoint0();\r
1692     }\r
1693 \r
1694     return (FALSE);\r
1695 }\r
1696 \r
1697 //----------------------------------------------------------------------------\r
1698 \r
1699 uint8_t usbSetInterface (void)\r
1700 {\r
1701     //bValueL contains alternative setting\r
1702     //bIndexL contains interface number\r
1703     //change code if more than one interface is supported\r
1704     usbStallOEP0();                         //control write without data stage\r
1705     bInterfaceNumber = tSetupPacket.wIndex;\r
1706 #ifdef _MSC_\r
1707     tInputEndPointDescriptorBlock[stUsbHandle[MSC0_INTFNUM].edb_Index].bEPCNF\r
1708         &= ~(EPCNF_TOGGLE);\r
1709     tOutputEndPointDescriptorBlock[stUsbHandle[MSC0_INTFNUM].edb_Index].bEPCNF\r
1710         &= ~(EPCNF_TOGGLE);\r
1711     MscReadControl.bCurrentBufferXY = 0;    //Set current buffer to X\r
1712     MscWriteControl.bCurrentBufferXY = 0;   //Set current buffer to X\r
1713 #endif\r
1714     usbSendZeroLengthPacketOnIEP0();\r
1715 \r
1716     return (FALSE);\r
1717 }\r
1718 \r
1719 //----------------------------------------------------------------------------\r
1720 \r
1721 uint8_t usbInvalidRequest (void)\r
1722 {\r
1723     //check if setup overwrite is set\r
1724     //if set, do nothing since we might decode it wrong\r
1725     //setup packet buffer could be modified by hardware if another setup packet\r
1726     //was sent while we are deocding setup packet\r
1727     if ((USBIFG & STPOWIFG) == 0x00){\r
1728         usbStallEndpoint0();\r
1729     }\r
1730 \r
1731     return (FALSE);\r
1732 }\r
1733 \r
1734 typedef uint8_t (*tpF)(void);\r
1735 \r
1736 uint8_t usbDecodeAndProcessUsbRequest (void)\r
1737 {\r
1738     uint8_t bMask,bResult,bTemp;\r
1739     const uint8_t* pbUsbRequestList;\r
1740     uint8_t bWakeUp = FALSE;\r
1741     ptDEVICE_REQUEST ptSetupPacket = &tSetupPacket;\r
1742     uint8_t bRequestType,bRequest;\r
1743     tpF lAddrOfFunction;\r
1744 \r
1745     //point to beginning of the matrix\r
1746     pbUsbRequestList = (uint8_t*)&tUsbRequestList[0];\r
1747 \r
1748     while (1)\r
1749     {\r
1750         bRequestType = *pbUsbRequestList++;\r
1751         bRequest     = *pbUsbRequestList++;\r
1752 \r
1753         if (((bRequestType == 0xff) && (bRequest == 0xff)) ||\r
1754             (tSetupPacket.bmRequestType ==\r
1755              (USB_REQ_TYPE_INPUT | USB_REQ_TYPE_VENDOR |\r
1756               USB_REQ_TYPE_DEVICE)) ||\r
1757             (tSetupPacket.bmRequestType ==\r
1758              (USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_VENDOR |\r
1759               USB_REQ_TYPE_DEVICE))){\r
1760             pbUsbRequestList -= 2;\r
1761             break;\r
1762         }\r
1763 \r
1764         if ((bRequestType == tSetupPacket.bmRequestType) &&\r
1765             (bRequest == tSetupPacket.bRequest)){\r
1766             //compare the first two\r
1767             bResult = 0xc0;\r
1768             bMask   = 0x20;\r
1769             //first two bytes matched, compare the rest\r
1770             for (bTemp = 2; bTemp < 8; bTemp++)\r
1771             {\r
1772                 if (*((uint8_t*)ptSetupPacket + bTemp) == *pbUsbRequestList){\r
1773                     bResult |= bMask;\r
1774                 }\r
1775                 pbUsbRequestList++;\r
1776                 bMask = bMask >> 1;\r
1777             }\r
1778             //now we have the result\r
1779             if ((*pbUsbRequestList & bResult) == *pbUsbRequestList){\r
1780                 pbUsbRequestList -= 8;\r
1781                 break;\r
1782             } else {\r
1783                 pbUsbRequestList += (sizeof(tDEVICE_REQUEST_COMPARE) - 8);\r
1784             }\r
1785         } else {\r
1786             pbUsbRequestList += (sizeof(tDEVICE_REQUEST_COMPARE) - 2);\r
1787         }\r
1788     }\r
1789 \r
1790     //if another setup packet comes before we have the chance to process current\r
1791     //setup request, we return here without processing the request\r
1792     //this check is not necessary but still kept here to reduce response(or simulation) time\r
1793 \r
1794     if ((USBIFG & STPOWIFG) != 0x00){\r
1795         return (bWakeUp);\r
1796     }\r
1797 \r
1798     //now we found the match and jump to the function accordingly.\r
1799     lAddrOfFunction =\r
1800         ((tDEVICE_REQUEST_COMPARE*)pbUsbRequestList)->pUsbFunction;\r
1801 \r
1802     //call function\r
1803     bWakeUp = (*lAddrOfFunction)();\r
1804 \r
1805     return (bWakeUp);\r
1806 }\r
1807 \r
1808 uint16_t usbDisableInEndpointInterrupt(uint8_t edbIndex)\r
1809 {\r
1810         uint16_t state;\r
1811         state = USBIEPIE & (1 << (edbIndex + 1));\r
1812         USBIEPIE &= ~(1 << (edbIndex + 1));\r
1813         return (state);\r
1814 }\r
1815 void usbRestoreInEndpointInterrupt(uint16_t state)\r
1816 {\r
1817         USBIEPIE |= state;\r
1818 }\r
1819 uint16_t usbDisableOutEndpointInterrupt(uint8_t edbIndex)\r
1820 {\r
1821         uint16_t state;\r
1822         state = USBOEPIE & (1 << (edbIndex + 1));\r
1823         USBOEPIE &= ~(1 << (edbIndex + 1));\r
1824         return (state);\r
1825 }\r
1826 void usbRestoreOutEndpointInterrupt(uint16_t state)\r
1827 {\r
1828         USBOEPIE |= state;\r
1829 }\r
1830 #ifdef NON_COMPOSITE_MULTIPLE_INTERFACES\r
1831 \r
1832 uint8_t USB_switchInterface(uint8_t interfaceIndex)\r
1833 {\r
1834         if (interfaceIndex < NONCOMP_NUM_USB_INTERFACES) {\r
1835                 activeInterfaceIndex = interfaceIndex;\r
1836                 return (TRUE);\r
1837         }\r
1838         else {\r
1839                 return (FALSE);\r
1840         }\r
1841 }\r
1842 \r
1843 #endif\r
1844 \r
1845 uint16_t USB_determineFreq(void){\r
1846     uint16_t freq;                  // calculated MCLK freq in kHz\r
1847     uint16_t currentFLLN;           // value of divider N taken from UCS registers\r
1848     uint8_t currentSELM;           // MCLK reference taken from UCS registers\r
1849     uint8_t currentFLLREFDIV;      // value of divider n taken from UCS registers\r
1850     uint16_t currentFLLD;           // value of prescalar D taken from UCS registers\r
1851     uint16_t FLLRefFreq;\r
1852 \r
1853     currentSELM = (UCSCTL4_L & SELM_7);   // get clock selection control register\r
1854 \r
1855     if(currentSELM<=4) // MCLK = DCO, DCOCLKDIV, XT1, VLO, or REFO.  The last three aren't supported by the API.\r
1856     {\r
1857         FLLRefFreq = 33;                    // The reference is usually 32.768 kHz.\r
1858         if((UCSCTL3_L & SELREF_7) > 0x50){  // Unless it's XT2 frequency\r
1859             FLLRefFreq = USB_XT_FREQ_VALUE * 1000;\r
1860         }\r
1861 \r
1862         // determine factors N and n\r
1863         currentFLLN = UCSCTL2 & 0x03FF;          // get FLL multiplier register\r
1864         currentFLLN++;\r
1865         if(currentSELM == SELM_3)            // if MCLK is sourced by DCOCLK\r
1866         {\r
1867             // determine D\r
1868             currentFLLD = UCSCTL2 & FLLD_7;  // get FLLD register\r
1869             currentFLLD >>= 12;\r
1870             currentFLLN <<= currentFLLD;\r
1871         }\r
1872 \r
1873         currentFLLREFDIV = UCSCTL3_L & FLLREFDIV_7; // get FLL reference divider register\r
1874         if(currentFLLREFDIV>=4)\r
1875         {\r
1876             currentFLLREFDIV = FLLREFDIV_5;\r
1877         }\r
1878         freq = currentFLLN * (FLLRefFreq >> currentFLLREFDIV);\r
1879     }\r
1880     else\r
1881     {\r
1882         freq = USB_XT_FREQ_VALUE * 1000;\r
1883     }\r
1884     return freq >> (UCSCTL5_L & DIVM_7);  // Divide by any divider present in DIVM\r
1885 }\r
1886 \r
1887 \r
1888 //\r
1889 //! \endcond\r
1890 //\r
1891 \r
1892 /*----------------------------------------------------------------------------+\r
1893  | End of source file                                                          |\r
1894  +----------------------------------------------------------------------------*/\r
1895 /*------------------------ Nothing Below This Line --------------------------*/\r
1896 //Released_Version_4_10_02\r