Rev 3332 Rev 3333
Line 1... Line 1...
1 /* Name: usbdrv.c 1 /* Name: usbdrv.c
2 * Project: AVR USB driver 2 * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
3 * Author: Christian Starkjohann 3 * Author: Christian Starkjohann
4 * Creation Date: 2004-12-29 4 * Creation Date: 2004-12-29
5 * Tabsize: 4 5 * Tabsize: 4
6 * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH 6 * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
7 * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) 7 * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
8 * This Revision: $Id: usbdrv.c,v 1.3 2007/06/07 13:53:47 harbaum Exp $ -  
9 */ 8 */
10   9  
11 #include "iarcompat.h" -  
12 #ifndef __IAR_SYSTEMS_ICC__ -  
13 # include <avr/io.h> -  
14 # include <avr/pgmspace.h> -  
15 #endif -  
16 #include "usbdrv.h" 10 #include "usbdrv.h"
17 #include "oddebug.h" 11 #include "oddebug.h"
18   12  
19 /* 13 /*
20 General Description: 14 General Description:
21 This module implements the C-part of the USB driver. See usbdrv.h for a 15 This module implements the C-part of the USB driver. See usbdrv.h for a
22 documentation of the entire driver. 16 documentation of the entire driver.
23 */ 17 */
24   18  
25 #ifndef IAR_SECTION -  
26 #define IAR_SECTION(arg) -  
27 #define __no_init -  
28 #endif -  
29 /* The macro IAR_SECTION is a hack to allow IAR-cc compatibility. On gcc, it -  
30 * is defined to nothing. __no_init is required on IAR. -  
31 */ -  
32   -  
33 /* ------------------------------------------------------------------------- */ 19 /* ------------------------------------------------------------------------- */
34   20  
35 /* raw USB registers / interface to assembler code: */ 21 /* raw USB registers / interface to assembler code: */
36 uchar usbRxBuf[2*USB_BUFSIZE]; /* raw RX buffer: PID, 8 bytes data, 2 bytes CRC */ 22 uchar usbRxBuf[2*USB_BUFSIZE]; /* raw RX buffer: PID, 8 bytes data, 2 bytes CRC */
37 uchar usbInputBufOffset; /* offset in usbRxBuf used for low level receiving */ 23 uchar usbInputBufOffset; /* offset in usbRxBuf used for low level receiving */
38 uchar usbDeviceAddr; /* assigned during enumeration, defaults to 0 */ 24 uchar usbDeviceAddr; /* assigned during enumeration, defaults to 0 */
39 uchar usbNewDeviceAddr; /* device ID which should be set after status phase */ 25 uchar usbNewDeviceAddr; /* device ID which should be set after status phase */
40 uchar usbConfiguration; /* currently selected configuration. Administered by driver, but not used */ 26 uchar usbConfiguration; /* currently selected configuration. Administered by driver, but not used */
41 volatile schar usbRxLen; /* = 0; number of bytes in usbRxBuf; 0 means free, -1 for flow control */ 27 volatile schar usbRxLen; /* = 0; number of bytes in usbRxBuf; 0 means free, -1 for flow control */
42 uchar usbCurrentTok; /* last token received, if more than 1 rx endpoint: MSb=endpoint */ 28 uchar usbCurrentTok; /* last token received or endpoint number for last OUT token if != 0 */
43 uchar usbRxToken; /* token for data we received; if more than 1 rx endpoint: MSb=endpoint */ 29 uchar usbRxToken; /* token for data we received; or endpont number for last OUT */
44 uchar usbMsgLen = 0xff; /* remaining number of bytes, no msg to send if -1 (see usbMsgPtr) */ -  
45 volatile uchar usbTxLen = USBPID_NAK; /* number of bytes to transmit with next IN token or handshake token */ 30 volatile uchar usbTxLen = USBPID_NAK; /* number of bytes to transmit with next IN token or handshake token */
46 uchar usbTxBuf[USB_BUFSIZE];/* data to transmit with next IN, free if usbTxLen contains handshake token */ 31 uchar usbTxBuf[USB_BUFSIZE];/* data to transmit with next IN, free if usbTxLen contains handshake token */
47 #if USB_CFG_HAVE_INTRIN_ENDPOINT 32 #if USB_COUNT_SOF
48 volatile uchar usbTxLen1 = USBPID_NAK; /* TX count for endpoint 1 */ 33 volatile uchar usbSofCount; /* incremented by assembler module every SOF */
-   34 #endif
49 uchar usbTxBuf1[USB_BUFSIZE]; /* TX data for endpoint 1 */ 35 #if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
-   36 usbTxStatus_t usbTxStatus1;
50 #if USB_CFG_HAVE_INTRIN_ENDPOINT3 37 # if USB_CFG_HAVE_INTRIN_ENDPOINT3
51 volatile uchar usbTxLen3 = USBPID_NAK; /* TX count for endpoint 1 */ 38 usbTxStatus_t usbTxStatus3;
52 uchar usbTxBuf3[USB_BUFSIZE]; /* TX data for endpoint 1 */ 39 # endif
53 #endif 40 #endif
-   41 #if USB_CFG_CHECK_DATA_TOGGLING
-   42 uchar usbCurrentDataToken;/* when we check data toggling to ignore duplicate packets */
54 #endif 43 #endif
55   44  
56 /* USB status registers / not shared with asm code */ 45 /* USB status registers / not shared with asm code */
57 uchar *usbMsgPtr; /* data to transmit next -- ROM or RAM address */ 46 usbMsgPtr_t usbMsgPtr; /* data to transmit next -- ROM or RAM address */
-   47 static usbMsgLen_t usbMsgLen = USB_NO_MSG; /* remaining number of bytes */
58 static uchar usbMsgFlags; /* flag values see below */ 48 static uchar usbMsgFlags; /* flag values see below */
59   49  
60 #define USB_FLG_TX_PACKET (1<<0) -  
61 /* Leave free 6 bits after TX_PACKET. This way we can increment usbMsgFlags to toggle TX_PACKET */ -  
62 #define USB_FLG_MSGPTR_IS_ROM (1<<6) 50 #define USB_FLG_MSGPTR_IS_ROM (1<<6)
63 #define USB_FLG_USE_DEFAULT_RW (1<<7) 51 #define USB_FLG_USE_USER_RW (1<<7)
64   52  
65 /* 53 /*
66 optimizing hints: 54 optimizing hints:
67 - do not post/pre inc/dec integer values in operations 55 - do not post/pre inc/dec integer values in operations
68 - assign value of PRG_RDB() to register variables and don't use side effects in arg 56 - assign value of USB_READ_FLASH() to register variables and don't use side effects in arg
69 - use narrow scope for variables which should be in X/Y/Z register 57 - use narrow scope for variables which should be in X/Y/Z register
70 - assign char sized expressions to variables to force 8 bit arithmetics 58 - assign char sized expressions to variables to force 8 bit arithmetics
71 */ 59 */
72   60  
73 /* ------------------------------------------------------------------------- */ 61 /* -------------------------- String Descriptors --------------------------- */
74   62  
75 #if USB_CFG_DESCR_PROPS_STRINGS == 0 63 #if USB_CFG_DESCR_PROPS_STRINGS == 0
76   64  
77 #if USB_CFG_DESCR_PROPS_STRING_0 == 0 65 #if USB_CFG_DESCR_PROPS_STRING_0 == 0
78 #undef USB_CFG_DESCR_PROPS_STRING_0 66 #undef USB_CFG_DESCR_PROPS_STRING_0
79 #define USB_CFG_DESCR_PROPS_STRING_0 sizeof(usbDescriptorString0) 67 #define USB_CFG_DESCR_PROPS_STRING_0 sizeof(usbDescriptorString0)
80 PROGMEM char usbDescriptorString0[] = { /* language descriptor */ 68 PROGMEM const char usbDescriptorString0[] = { /* language descriptor */
81 4, /* sizeof(usbDescriptorString0): length of descriptor in bytes */ 69 4, /* sizeof(usbDescriptorString0): length of descriptor in bytes */
82 3, /* descriptor type */ 70 3, /* descriptor type */
83 0x09, 0x04, /* language index (0x0409 = US-English) */ 71 0x09, 0x04, /* language index (0x0409 = US-English) */
84 }; 72 };
85 #endif 73 #endif
86   74  
87 #if USB_CFG_DESCR_PROPS_STRING_VENDOR == 0 && USB_CFG_VENDOR_NAME_LEN 75 #if USB_CFG_DESCR_PROPS_STRING_VENDOR == 0 && USB_CFG_VENDOR_NAME_LEN
88 #undef USB_CFG_DESCR_PROPS_STRING_VENDOR 76 #undef USB_CFG_DESCR_PROPS_STRING_VENDOR
89 #define USB_CFG_DESCR_PROPS_STRING_VENDOR sizeof(usbDescriptorStringVendor) 77 #define USB_CFG_DESCR_PROPS_STRING_VENDOR sizeof(usbDescriptorStringVendor)
90 PROGMEM int usbDescriptorStringVendor[] = { 78 PROGMEM const int usbDescriptorStringVendor[] = {
91 USB_STRING_DESCRIPTOR_HEADER(USB_CFG_VENDOR_NAME_LEN), 79 USB_STRING_DESCRIPTOR_HEADER(USB_CFG_VENDOR_NAME_LEN),
92 USB_CFG_VENDOR_NAME 80 USB_CFG_VENDOR_NAME
93 }; 81 };
94 #endif 82 #endif
95   83  
96 #if USB_CFG_DESCR_PROPS_STRING_DEVICE == 0 && USB_CFG_DEVICE_NAME_LEN 84 #if USB_CFG_DESCR_PROPS_STRING_PRODUCT == 0 && USB_CFG_DEVICE_NAME_LEN
97 #undef USB_CFG_DESCR_PROPS_STRING_DEVICE 85 #undef USB_CFG_DESCR_PROPS_STRING_PRODUCT
98 #define USB_CFG_DESCR_PROPS_STRING_DEVICE sizeof(usbDescriptorStringDevice) 86 #define USB_CFG_DESCR_PROPS_STRING_PRODUCT sizeof(usbDescriptorStringDevice)
99 PROGMEM int usbDescriptorStringDevice[] = { 87 PROGMEM const int usbDescriptorStringDevice[] = {
100 USB_STRING_DESCRIPTOR_HEADER(USB_CFG_DEVICE_NAME_LEN), 88 USB_STRING_DESCRIPTOR_HEADER(USB_CFG_DEVICE_NAME_LEN),
101 USB_CFG_DEVICE_NAME 89 USB_CFG_DEVICE_NAME
102 }; 90 };
103 #endif 91 #endif
104   92  
105 #if USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER == 0 && USB_CFG_SERIAL_NUMBER_LEN 93 #if USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER == 0 && USB_CFG_SERIAL_NUMBER_LEN
106 #undef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 94 #undef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
107 #define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER sizeof(usbDescriptorStringSerialNumber) 95 #define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER sizeof(usbDescriptorStringSerialNumber)
108 PROGMEM int usbDescriptorStringSerialNumber[] = { 96 PROGMEM const int usbDescriptorStringSerialNumber[] = {
109 USB_STRING_DESCRIPTOR_HEADER(USB_CFG_SERIAL_NUMBER_LEN), 97 USB_STRING_DESCRIPTOR_HEADER(USB_CFG_SERIAL_NUMBER_LEN),
110 USB_CFG_SERIAL_NUMBER 98 USB_CFG_SERIAL_NUMBER
111 }; 99 };
112 #endif 100 #endif
113   101  
114 #endif /* USB_CFG_DESCR_PROPS_STRINGS == 0 */ 102 #endif /* USB_CFG_DESCR_PROPS_STRINGS == 0 */
115   103  
-   104 /* --------------------------- Device Descriptor --------------------------- */
-   105  
116 #if USB_CFG_DESCR_PROPS_DEVICE == 0 106 #if USB_CFG_DESCR_PROPS_DEVICE == 0
117 #undef USB_CFG_DESCR_PROPS_DEVICE 107 #undef USB_CFG_DESCR_PROPS_DEVICE
118 #define USB_CFG_DESCR_PROPS_DEVICE sizeof(usbDescriptorDevice) 108 #define USB_CFG_DESCR_PROPS_DEVICE sizeof(usbDescriptorDevice)
119 PROGMEM char usbDescriptorDevice[] = { /* USB device descriptor */ 109 PROGMEM const char usbDescriptorDevice[] = { /* USB device descriptor */
120 18, /* sizeof(usbDescriptorDevice): length of descriptor in bytes */ 110 18, /* sizeof(usbDescriptorDevice): length of descriptor in bytes */
121 USBDESCR_DEVICE, /* descriptor type */ 111 USBDESCR_DEVICE, /* descriptor type */
122 0x10, 0x01, /* USB version supported */ 112 0x10, 0x01, /* USB version supported */
123 USB_CFG_DEVICE_CLASS, 113 USB_CFG_DEVICE_CLASS,
124 USB_CFG_DEVICE_SUBCLASS, 114 USB_CFG_DEVICE_SUBCLASS,
125 0, /* protocol */ 115 0, /* protocol */
126 8, /* max packet size */ 116 8, /* max packet size */
-   117 /* the following two casts affect the first byte of the constant only, but
-   118 * that's sufficient to avoid a warning with the default values.
-   119 */
127 USB_CFG_VENDOR_ID, /* 2 bytes */ 120 (char)USB_CFG_VENDOR_ID,/* 2 bytes */
128 USB_CFG_DEVICE_ID, /* 2 bytes */ 121 (char)USB_CFG_DEVICE_ID,/* 2 bytes */
129 USB_CFG_DEVICE_VERSION, /* 2 bytes */ 122 USB_CFG_DEVICE_VERSION, /* 2 bytes */
130 USB_CFG_DESCR_PROPS_STRING_VENDOR != 0 ? 1 : 0, /* manufacturer string index */ 123 USB_CFG_DESCR_PROPS_STRING_VENDOR != 0 ? 1 : 0, /* manufacturer string index */
131 USB_CFG_DESCR_PROPS_STRING_DEVICE != 0 ? 2 : 0, /* product string index */ 124 USB_CFG_DESCR_PROPS_STRING_PRODUCT != 0 ? 2 : 0, /* product string index */
132 USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER != 0 ? 3 : 0, /* serial number string index */ 125 USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER != 0 ? 3 : 0, /* serial number string index */
133 1, /* number of configurations */ 126 1, /* number of configurations */
134 }; 127 };
135 #endif 128 #endif
136   129  
-   130 /* ----------------------- Configuration Descriptor ------------------------ */
-   131  
137 #if USB_CFG_DESCR_PROPS_HID_REPORT != 0 && USB_CFG_DESCR_PROPS_HID == 0 132 #if USB_CFG_DESCR_PROPS_HID_REPORT != 0 && USB_CFG_DESCR_PROPS_HID == 0
138 #undef USB_CFG_DESCR_PROPS_HID 133 #undef USB_CFG_DESCR_PROPS_HID
139 #define USB_CFG_DESCR_PROPS_HID 9 /* length of HID descriptor in config descriptor below */ 134 #define USB_CFG_DESCR_PROPS_HID 9 /* length of HID descriptor in config descriptor below */
140 #endif 135 #endif
141   136  
142 #if USB_CFG_DESCR_PROPS_CONFIGURATION == 0 137 #if USB_CFG_DESCR_PROPS_CONFIGURATION == 0
143 #undef USB_CFG_DESCR_PROPS_CONFIGURATION 138 #undef USB_CFG_DESCR_PROPS_CONFIGURATION
144 #define USB_CFG_DESCR_PROPS_CONFIGURATION sizeof(usbDescriptorConfiguration) 139 #define USB_CFG_DESCR_PROPS_CONFIGURATION sizeof(usbDescriptorConfiguration)
145 PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor */ 140 PROGMEM const char usbDescriptorConfiguration[] = { /* USB configuration descriptor */
146 9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */ 141 9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
147 USBDESCR_CONFIG, /* descriptor type */ 142 USBDESCR_CONFIG, /* descriptor type */
148 18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + (USB_CFG_DESCR_PROPS_HID & 0xff), 0, 143 18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 +
-   144 (USB_CFG_DESCR_PROPS_HID & 0xff), 0,
149 /* total length of data returned (including inlined descriptors) */ 145 /* total length of data returned (including inlined descriptors) */
150 1, /* number of interfaces in this configuration */ 146 1, /* number of interfaces in this configuration */
151 1, /* index of this configuration */ 147 1, /* index of this configuration */
152 0, /* configuration name string index */ 148 0, /* configuration name string index */
153 #if USB_CFG_IS_SELF_POWERED 149 #if USB_CFG_IS_SELF_POWERED
154 USBATTR_SELFPOWER, /* attributes */ 150 (1 << 7) | USBATTR_SELFPOWER, /* attributes */
155 #else 151 #else
156 USBATTR_BUSPOWER, /* attributes */ 152 (1 << 7), /* attributes */
157 #endif 153 #endif
158 USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */ 154 USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */
159 /* interface descriptor follows inline: */ 155 /* interface descriptor follows inline: */
160 9, /* sizeof(usbDescrInterface): length of descriptor in bytes */ 156 9, /* sizeof(usbDescrInterface): length of descriptor in bytes */
161 USBDESCR_INTERFACE, /* descriptor type */ 157 USBDESCR_INTERFACE, /* descriptor type */
162 0, /* index of this interface */ 158 0, /* index of this interface */
163 0, /* alternate setting for this interface */ 159 0, /* alternate setting for this interface */
164 USB_CFG_HAVE_INTRIN_ENDPOINT, /* endpoints excl 0: number of endpoint descriptors to follow */ 160 USB_CFG_HAVE_INTRIN_ENDPOINT + USB_CFG_HAVE_INTRIN_ENDPOINT3, /* endpoints excl 0: number of endpoint descriptors to follow */
165 USB_CFG_INTERFACE_CLASS, 161 USB_CFG_INTERFACE_CLASS,
166 USB_CFG_INTERFACE_SUBCLASS, 162 USB_CFG_INTERFACE_SUBCLASS,
167 USB_CFG_INTERFACE_PROTOCOL, 163 USB_CFG_INTERFACE_PROTOCOL,
168 0, /* string index for interface */ 164 0, /* string index for interface */
169 #if (USB_CFG_DESCR_PROPS_HID & 0xff) /* HID descriptor */ 165 #if (USB_CFG_DESCR_PROPS_HID & 0xff) /* HID descriptor */
Line 176... Line 172...
176 USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH, 0, /* total length of report descriptor */ 172 USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH, 0, /* total length of report descriptor */
177 #endif 173 #endif
178 #if USB_CFG_HAVE_INTRIN_ENDPOINT /* endpoint descriptor for endpoint 1 */ 174 #if USB_CFG_HAVE_INTRIN_ENDPOINT /* endpoint descriptor for endpoint 1 */
179 7, /* sizeof(usbDescrEndpoint) */ 175 7, /* sizeof(usbDescrEndpoint) */
180 USBDESCR_ENDPOINT, /* descriptor type = endpoint */ 176 USBDESCR_ENDPOINT, /* descriptor type = endpoint */
181 0x81, /* IN endpoint number 1 */ 177 (char)0x81, /* IN endpoint number 1 */
-   178 0x03, /* attrib: Interrupt endpoint */
-   179 8, 0, /* maximum packet size */
-   180 USB_CFG_INTR_POLL_INTERVAL, /* in ms */
-   181 #endif
-   182 #if USB_CFG_HAVE_INTRIN_ENDPOINT3 /* endpoint descriptor for endpoint 3 */
-   183 7, /* sizeof(usbDescrEndpoint) */
-   184 USBDESCR_ENDPOINT, /* descriptor type = endpoint */
-   185 (char)(0x80 | USB_CFG_EP3_NUMBER), /* IN endpoint number 3 */
182 0x03, /* attrib: Interrupt endpoint */ 186 0x03, /* attrib: Interrupt endpoint */
183 8, 0, /* maximum packet size */ 187 8, 0, /* maximum packet size */
184 USB_CFG_INTR_POLL_INTERVAL, /* in ms */ 188 USB_CFG_INTR_POLL_INTERVAL, /* in ms */
185 #endif 189 #endif
186 }; 190 };
187 #endif 191 #endif
188   192  
189 /* We don't use prog_int or prog_int16_t for compatibility with various libc 193 /* ------------------------------------------------------------------------- */
-   194  
190 * versions. Here's an other compatibility hack: 195 static inline void usbResetDataToggling(void)
191 */ 196 {
192 #ifndef PRG_RDB 197 #if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
-   198 USB_SET_DATATOKEN1(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */
193 #define PRG_RDB(addr) pgm_read_byte(addr) 199 # if USB_CFG_HAVE_INTRIN_ENDPOINT3
-   200 USB_SET_DATATOKEN3(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */
-   201 # endif
194 #endif 202 #endif
-   203 }
195   204  
196 typedef union{ 205 static inline void usbResetStall(void)
-   206 {
-   207 #if USB_CFG_IMPLEMENT_HALT && USB_CFG_HAVE_INTRIN_ENDPOINT
197 unsigned word; 208 usbTxLen1 = USBPID_NAK;
198 uchar *ptr; 209 #if USB_CFG_HAVE_INTRIN_ENDPOINT3
199 uchar bytes[2]; 210 usbTxLen3 = USBPID_NAK;
200 }converter_t; 211 #endif
201 /* We use this union to do type conversions. This is better optimized than -  
202 * type casts in gcc 3.4.3 and much better than using bit shifts to build -  
203 * ints from chars. Byte ordering is not a problem on an 8 bit platform. -  
-   212 #endif
204 */ 213 }
205   214  
206 /* ------------------------------------------------------------------------- */ 215 /* ------------------------------------------------------------------------- */
207   216  
-   217 #if !USB_CFG_SUPPRESS_INTR_CODE
208 #if USB_CFG_HAVE_INTRIN_ENDPOINT 218 #if USB_CFG_HAVE_INTRIN_ENDPOINT
209 void usbSetInterrupt(uchar *data, uchar len) 219 static void usbGenericSetInterrupt(uchar *data, uchar len, usbTxStatus_t *txStatus)
210 { 220 {
211 uchar *p, i; 221 uchar *p;
-   222 char i;
212   223  
213 #if USB_CFG_IMPLEMENT_HALT 224 #if USB_CFG_IMPLEMENT_HALT
214 if(usbTxLen1 == USBPID_STALL) 225 if(usbTxLen1 == USBPID_STALL)
215 return; 226 return;
216 #endif 227 #endif
217 #if 0 /* No runtime checks! Caller is responsible for valid data! */ -  
218 if(len > 8) /* interrupt transfers are limited to 8 bytes */ -  
219 len = 8; -  
220 #endif -  
221 if(usbTxLen1 & 0x10){ /* packet buffer was empty */ 228 if(txStatus->len & 0x10){ /* packet buffer was empty */
222 usbTxBuf1[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* toggle token */ 229 txStatus->buffer[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* toggle token */
223 }else{ 230 }else{
224 usbTxLen1 = USBPID_NAK; /* avoid sending outdated (overwritten) interrupt data */ 231 txStatus->len = USBPID_NAK; /* avoid sending outdated (overwritten) interrupt data */
225 } 232 }
226 p = usbTxBuf1 + 1; 233 p = txStatus->buffer + 1;
227 for(i=len;i--;) 234 i = len;
-   235 do{ /* if len == 0, we still copy 1 byte, but that's no problem */
228 *p++ = *data++; 236 *p++ = *data++;
-   237 }while(--i > 0); /* loop control at the end is 2 bytes shorter than at beginning */
229 usbCrc16Append(&usbTxBuf1[1], len); 238 usbCrc16Append(&txStatus->buffer[1], len);
230 usbTxLen1 = len + 4; /* len must be given including sync byte */ 239 txStatus->len = len + 4; /* len must be given including sync byte */
231 DBG2(0x21, usbTxBuf1, len + 3); 240 DBG2(0x21 + (((int)txStatus >> 3) & 3), txStatus->buffer, len + 3);
-   241 }
-   242  
-   243 USB_PUBLIC void usbSetInterrupt(uchar *data, uchar len)
-   244 {
-   245 usbGenericSetInterrupt(data, len, &usbTxStatus1);
232 } 246 }
233 #endif 247 #endif
234   248  
235 #if USB_CFG_HAVE_INTRIN_ENDPOINT3 249 #if USB_CFG_HAVE_INTRIN_ENDPOINT3
236 void usbSetInterrupt3(uchar *data, uchar len) 250 USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len)
237 { 251 {
238 uchar *p, i; -  
239   -  
240 if(usbTxLen3 & 0x10){ /* packet buffer was empty */ -  
241 usbTxBuf3[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* toggle token */ -  
242 }else{ -  
243 usbTxLen3 = USBPID_NAK; /* avoid sending outdated (overwritten) interrupt data */ -  
244 } -  
245 p = usbTxBuf3 + 1; -  
246 for(i=len;i--;) -  
247 *p++ = *data++; -  
248 usbCrc16Append(&usbTxBuf3[1], len); 252 usbGenericSetInterrupt(data, len, &usbTxStatus3);
249 usbTxLen3 = len + 4; /* len must be given including sync byte */ -  
250 DBG2(0x23, usbTxBuf3, len + 3); -  
251 } 253 }
252 #endif 254 #endif
-   255 #endif /* USB_CFG_SUPPRESS_INTR_CODE */
253   256  
-   257 /* ------------------ utilities for code following below ------------------- */
254   258  
255 static uchar usbRead(uchar *data, uchar len) 259 /* Use defines for the switch statement so that we can choose between an
-   260 * if()else if() and a switch/case based implementation. switch() is more
-   261 * efficient for a LARGE set of sequential choices, if() is better in all other
-   262 * cases.
256 { 263 */
257 #if USB_CFG_IMPLEMENT_FN_READ 264 #if USB_CFG_USE_SWITCH_STATEMENT
258 if(usbMsgFlags & USB_FLG_USE_DEFAULT_RW){ 265 # define SWITCH_START(cmd) switch(cmd){{
-   266 # define SWITCH_CASE(value) }break; case (value):{
-   267 # define SWITCH_CASE2(v1,v2) }break; case (v1): case(v2):{
-   268 # define SWITCH_CASE3(v1,v2,v3) }break; case (v1): case(v2): case(v3):{
-   269 # define SWITCH_DEFAULT }break; default:{
-   270 # define SWITCH_END }}
-   271 #else
-   272 # define SWITCH_START(cmd) {uchar _cmd = cmd; if(0){
-   273 # define SWITCH_CASE(value) }else if(_cmd == (value)){
-   274 # define SWITCH_CASE2(v1,v2) }else if(_cmd == (v1) || _cmd == (v2)){
-   275 # define SWITCH_CASE3(v1,v2,v3) }else if(_cmd == (v1) || _cmd == (v2) || (_cmd == v3)){
-   276 # define SWITCH_DEFAULT }else{
-   277 # define SWITCH_END }}
259 #endif 278 #endif
260 uchar i = len, *r = usbMsgPtr; -  
261 if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */ -  
262 while(i--){ -  
263 uchar c = PRG_RDB(r); /* assign to char size variable to enforce byte ops */ -  
264 *data++ = c; -  
265 r++; -  
266 } 279  
267 }else{ /* RAM data */ -  
268 while(i--) 280 #ifndef USB_RX_USER_HOOK
269 *data++ = *r++; 281 #define USB_RX_USER_HOOK(data, len)
270 } 282 #endif
271 usbMsgPtr = r; 283 #ifndef USB_SET_ADDRESS_HOOK
272 return len; -  
273 #if USB_CFG_IMPLEMENT_FN_READ 284 #define USB_SET_ADDRESS_HOOK()
274 }else{ -  
275 if(len != 0) /* don't bother app with 0 sized reads */ -  
276 return usbFunctionRead(data, len); -  
277 return 0; -  
278 } -  
279 #endif 285 #endif
280 } -  
281   286  
-   287 /* ------------------------------------------------------------------------- */
282   288  
-   289 /* We use if() instead of #if in the macro below because #if can't be used
-   290 * in macros and the compiler optimizes constant conditions anyway.
-   291 * This may cause problems with undefined symbols if compiled without
-   292 * optimizing!
-   293 */
283 #define GET_DESCRIPTOR(cfgProp, staticName) \ 294 #define GET_DESCRIPTOR(cfgProp, staticName) \
284 if(cfgProp){ \ 295 if(cfgProp){ \
285 if((cfgProp) & USB_PROP_IS_RAM) \ 296 if((cfgProp) & USB_PROP_IS_RAM) \
286 flags &= ~USB_FLG_MSGPTR_IS_ROM; \ 297 flags = 0; \
287 if((cfgProp) & USB_PROP_IS_DYNAMIC){ \ 298 if((cfgProp) & USB_PROP_IS_DYNAMIC){ \
288 replyLen = usbFunctionDescriptor(rq); \ 299 len = usbFunctionDescriptor(rq); \
289 }else{ \ 300 }else{ \
290 replyData = (uchar *)(staticName); \ 301 len = USB_PROP_LENGTH(cfgProp); \
291 SET_REPLY_LEN((cfgProp) & 0xff); \ 302 usbMsgPtr = (usbMsgPtr_t)(staticName); \
292 } \ 303 } \
293 } 304 }
294 /* We use if() instead of #if in the macro above because #if can't be used -  
295 * in macros and the compiler optimizes constant conditions anyway. -  
296 */ -  
297   305  
298   -  
299 /* Don't make this function static to avoid inlining. -  
300 * The entire function would become too large and exceed the range of -  
301 * relative jumps. -  
302 * 2006-02-25: Either gcc 3.4.3 is better than the gcc used when the comment -  
303 * above was written, or other parts of the code have changed. We now get 306 /* usbDriverDescriptor() is similar to usbFunctionDescriptor(), but used
304 * better results with an inlined function. Test condition: PowerSwitch code. 307 * internally for all types of descriptors.
305 */ 308 */
306 static void usbProcessRx(uchar *data, uchar len) 309 static inline usbMsgLen_t usbDriverDescriptor(usbRequest_t *rq)
307 { 310 {
308 usbRequest_t *rq = (void *)data; 311 usbMsgLen_t len = 0;
309 uchar replyLen = 0, flags = USB_FLG_USE_DEFAULT_RW; 312 uchar flags = USB_FLG_MSGPTR_IS_ROM;
310 /* We use if() cascades because the compare is done byte-wise while switch() -  
311 * is int-based. The if() cascades are therefore more efficient. -  
312 */ 313  
313 /* usbRxToken can be: -  
314 * 0x2d 00101101 (USBPID_SETUP for endpoint 0) -  
315 * 0xe1 11100001 (USBPID_OUT for endpoint 0) -  
316 * 0xff 11111111 (USBPID_OUT for endpoint 1) -  
317 */ -  
318 DBG2(0x10 + ((usbRxToken >> 1) & 3), data, len); /* SETUP0=12; OUT0=10; OUT1=13 */ -  
319 #if USB_CFG_IMPLEMENT_FN_WRITEOUT -  
320 if(usbRxToken == 0xff){ -  
321 usbFunctionWriteOut(data, len); -  
322 return; /* no reply expected, hence no usbMsgPtr, usbMsgFlags, usbMsgLen set */ -  
323 } -  
324 #endif -  
325 if(usbRxToken == (uchar)USBPID_SETUP){ -  
326 usbTxLen = USBPID_NAK; /* abort pending transmit */ -  
327 if(len == 8){ /* Setup size must be always 8 bytes. Ignore otherwise. */ -  
328 uchar type = rq->bmRequestType & USBRQ_TYPE_MASK; -  
329 if(type == USBRQ_TYPE_STANDARD){ -  
330 #define SET_REPLY_LEN(len) replyLen = (len); usbMsgPtr = replyData -  
331 /* This macro ensures that replyLen and usbMsgPtr are always set in the same way. -  
332 * That allows optimization of common code in if() branches */ -  
333 uchar *replyData = usbTxBuf + 9; /* there is 3 bytes free space at the end of the buffer */ -  
334 replyData[0] = 0; /* common to USBRQ_GET_STATUS and USBRQ_GET_INTERFACE */ -  
335 if(rq->bRequest == USBRQ_GET_STATUS){ /* 0 */ -  
336 uchar __attribute__((__unused__)) recipient = rq->bmRequestType & USBRQ_RCPT_MASK; /* assign arith ops to variables to enforce byte size */ -  
337 #if USB_CFG_IS_SELF_POWERED -  
338 if(recipient == USBRQ_RCPT_DEVICE) -  
339 replyData[0] = USB_CFG_IS_SELF_POWERED; -  
340 #endif -  
341 #if USB_CFG_HAVE_INTRIN_ENDPOINT && USB_CFG_IMPLEMENT_HALT -  
342 if(recipient == USBRQ_RCPT_ENDPOINT && rq->wIndex.bytes[0] == 0x81) /* request status for endpoint 1 */ -  
343 replyData[0] = usbTxLen1 == USBPID_STALL; -  
344 #endif -  
345 replyData[1] = 0; -  
346 SET_REPLY_LEN(2); -  
347 }else if(rq->bRequest == USBRQ_SET_ADDRESS){ /* 5 */ -  
348 usbNewDeviceAddr = rq->wValue.bytes[0]; 314 SWITCH_START(rq->wValue.bytes[1])
349 }else if(rq->bRequest == USBRQ_GET_DESCRIPTOR){ /* 6 */ -  
350 flags = USB_FLG_MSGPTR_IS_ROM | USB_FLG_USE_DEFAULT_RW; -  
351 if(rq->wValue.bytes[1] == USBDESCR_DEVICE){ /* 1 */ 315 SWITCH_CASE(USBDESCR_DEVICE) /* 1 */
352 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_DEVICE, usbDescriptorDevice) 316 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_DEVICE, usbDescriptorDevice)
353 }else if(rq->wValue.bytes[1] == USBDESCR_CONFIG){ /* 2 */ 317 SWITCH_CASE(USBDESCR_CONFIG) /* 2 */
354 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_CONFIGURATION, usbDescriptorConfiguration) 318 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_CONFIGURATION, usbDescriptorConfiguration)
355 }else if(rq->wValue.bytes[1] == USBDESCR_STRING){ /* 3 */ 319 SWITCH_CASE(USBDESCR_STRING) /* 3 */
356 #if USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC 320 #if USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC
357 if(USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_RAM) 321 if(USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_RAM)
358 flags &= ~USB_FLG_MSGPTR_IS_ROM; 322 flags = 0;
359 replyLen = usbFunctionDescriptor(rq); 323 len = usbFunctionDescriptor(rq);
360 #else /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */ 324 #else /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */
361 if(rq->wValue.bytes[0] == 0){ /* descriptor index */ 325 SWITCH_START(rq->wValue.bytes[0])
-   326 SWITCH_CASE(0)
362 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_0, usbDescriptorString0) 327 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_0, usbDescriptorString0)
363 }else if(rq->wValue.bytes[0] == 1){ 328 SWITCH_CASE(1)
364 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_VENDOR, usbDescriptorStringVendor) 329 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_VENDOR, usbDescriptorStringVendor)
365 }else if(rq->wValue.bytes[0] == 2){ 330 SWITCH_CASE(2)
366 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_DEVICE, usbDescriptorStringDevice) 331 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_PRODUCT, usbDescriptorStringDevice)
367 }else if(rq->wValue.bytes[0] == 3){ 332 SWITCH_CASE(3)
368 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER, usbDescriptorStringSerialNumber) 333 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER, usbDescriptorStringSerialNumber)
-   334 SWITCH_DEFAULT
369 }else if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){ 335 if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){
370 replyLen = usbFunctionDescriptor(rq); 336 len = usbFunctionDescriptor(rq);
371 } 337 }
-   338 SWITCH_END
372 #endif /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */ 339 #endif /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */
-   340 #if USB_CFG_DESCR_PROPS_HID_REPORT /* only support HID descriptors if enabled */
373 }else if(rq->wValue.bytes[1] == USBDESCR_HID){ /* 0x21 */ 341 SWITCH_CASE(USBDESCR_HID) /* 0x21 */
374 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID, usbDescriptorConfiguration + 18) 342 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID, usbDescriptorConfiguration + 18)
375 }else if(rq->wValue.bytes[1] == USBDESCR_HID_REPORT){ /* 0x22 */ 343 SWITCH_CASE(USBDESCR_HID_REPORT)/* 0x22 */
376 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID_REPORT, usbDescriptorHidReport) 344 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID_REPORT, usbDescriptorHidReport)
-   345 #endif
-   346 SWITCH_DEFAULT
377 }else if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){ 347 if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){
378 replyLen = usbFunctionDescriptor(rq); 348 len = usbFunctionDescriptor(rq);
-   349 }
-   350 SWITCH_END
-   351 usbMsgFlags = flags;
-   352 return len;
379 } 353 }
-   354  
380 }else if(rq->bRequest == USBRQ_GET_CONFIGURATION){ /* 8 */ 355 /* ------------------------------------------------------------------------- */
-   356  
381 replyData = &usbConfiguration; /* send current configuration value */ 357 /* usbDriverSetup() is similar to usbFunctionSetup(), but it's used for
382 SET_REPLY_LEN(1); 358 * standard requests instead of class and custom requests.
-   359 */
-   360 static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq)
-   361 {
-   362 usbMsgLen_t len = 0;
383 }else if(rq->bRequest == USBRQ_SET_CONFIGURATION){ /* 9 */ 363 uchar *dataPtr = usbTxBuf + 9; /* there are 2 bytes free space at the end of the buffer */
384 usbConfiguration = rq->wValue.bytes[0]; 364 uchar value = rq->wValue.bytes[0];
385 #if USB_CFG_IMPLEMENT_HALT 365 #if USB_CFG_IMPLEMENT_HALT
386 usbTxLen1 = USBPID_NAK; 366 uchar index = rq->wIndex.bytes[0];
387 #endif 367 #endif
-   368  
388 }else if(rq->bRequest == USBRQ_GET_INTERFACE){ /* 10 */ 369 dataPtr[0] = 0; /* default reply common to USBRQ_GET_STATUS and USBRQ_GET_INTERFACE */
389 SET_REPLY_LEN(1); 370 SWITCH_START(rq->bRequest)
390 #if USB_CFG_HAVE_INTRIN_ENDPOINT 371 SWITCH_CASE(USBRQ_GET_STATUS) /* 0 */
391 }else if(rq->bRequest == USBRQ_SET_INTERFACE){ /* 11 */ 372 uchar recipient = rq->bmRequestType & USBRQ_RCPT_MASK; /* assign arith ops to variables to enforce byte size */
392 USB_SET_DATATOKEN1(USBPID_DATA0); /* reset data toggling for interrupt endpoint */ 373 if(USB_CFG_IS_SELF_POWERED && recipient == USBRQ_RCPT_DEVICE)
-   374 dataPtr[0] = USB_CFG_IS_SELF_POWERED;
393 # if USB_CFG_HAVE_INTRIN_ENDPOINT3 375 #if USB_CFG_IMPLEMENT_HALT
394 USB_SET_DATATOKEN3(USBPID_DATA0); /* reset data toggling for interrupt endpoint */ 376 if(recipient == USBRQ_RCPT_ENDPOINT && index == 0x81) /* request status for endpoint 1 */
-   377 dataPtr[0] = usbTxLen1 == USBPID_STALL;
395 # endif 378 #endif
-   379 dataPtr[1] = 0;
-   380 len = 2;
396 # if USB_CFG_IMPLEMENT_HALT 381 #if USB_CFG_IMPLEMENT_HALT
397 usbTxLen1 = USBPID_NAK; -  
398 }else if(rq->bRequest == USBRQ_CLEAR_FEATURE || rq->bRequest == USBRQ_SET_FEATURE){ /* 1|3 */ 382 SWITCH_CASE2(USBRQ_CLEAR_FEATURE, USBRQ_SET_FEATURE) /* 1, 3 */
399 if(rq->wValue.bytes[0] == 0 && rq->wIndex.bytes[0] == 0x81){ /* feature 0 == HALT for endpoint == 1 */ 383 if(value == 0 && index == 0x81){ /* feature 0 == HALT for endpoint == 1 */
400 usbTxLen1 = rq->bRequest == USBRQ_CLEAR_FEATURE ? USBPID_NAK : USBPID_STALL; 384 usbTxLen1 = rq->bRequest == USBRQ_CLEAR_FEATURE ? USBPID_NAK : USBPID_STALL;
401 USB_SET_DATATOKEN1(USBPID_DATA0); /* reset data toggling for interrupt endpoint */ -  
402 # if USB_CFG_HAVE_INTRIN_ENDPOINT3 385 usbResetDataToggling();
403 USB_SET_DATATOKEN3(USBPID_DATA0); /* reset data toggling for interrupt endpoint */ -  
404 # endif -  
405 } 386 }
406 # endif 387 #endif
-   388 SWITCH_CASE(USBRQ_SET_ADDRESS) /* 5 */
-   389 usbNewDeviceAddr = value;
-   390 USB_SET_ADDRESS_HOOK();
-   391 SWITCH_CASE(USBRQ_GET_DESCRIPTOR) /* 6 */
-   392 len = usbDriverDescriptor(rq);
-   393 goto skipMsgPtrAssignment;
-   394 SWITCH_CASE(USBRQ_GET_CONFIGURATION) /* 8 */
-   395 dataPtr = &usbConfiguration; /* send current configuration value */
-   396 len = 1;
-   397 SWITCH_CASE(USBRQ_SET_CONFIGURATION) /* 9 */
-   398 usbConfiguration = value;
-   399 usbResetStall();
-   400 SWITCH_CASE(USBRQ_GET_INTERFACE) /* 10 */
-   401 len = 1;
-   402 #if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
-   403 SWITCH_CASE(USBRQ_SET_INTERFACE) /* 11 */
-   404 usbResetDataToggling();
-   405 usbResetStall();
407 #endif 406 #endif
-   407 SWITCH_DEFAULT /* 7=SET_DESCRIPTOR, 12=SYNC_FRAME */
-   408 /* Should we add an optional hook here? */
-   409 SWITCH_END
-   410 usbMsgPtr = (usbMsgPtr_t)dataPtr;
-   411 skipMsgPtrAssignment:
408 }else{ 412 return len;
-   413 }
-   414  
-   415 /* ------------------------------------------------------------------------- */
-   416  
-   417 /* usbProcessRx() is called for every message received by the interrupt
-   418 * routine. It distinguishes between SETUP and DATA packets and processes
-   419 * them accordingly.
-   420 */
-   421 static inline void usbProcessRx(uchar *data, uchar len)
-   422 {
-   423 usbRequest_t *rq = (void *)data;
-   424  
-   425 /* usbRxToken can be:
-   426 * 0x2d 00101101 (USBPID_SETUP for setup data)
-   427 * 0xe1 11100001 (USBPID_OUT: data phase of setup transfer)
-   428 * 0...0x0f for OUT on endpoint X
-   429 */
409 /* the following requests can be ignored, send default reply */ 430 DBG2(0x10 + (usbRxToken & 0xf), data, len + 2); /* SETUP=1d, SETUP-DATA=11, OUTx=1x */
-   431 USB_RX_USER_HOOK(data, len)
-   432 #if USB_CFG_IMPLEMENT_FN_WRITEOUT
410 /* 1: CLEAR_FEATURE, 3: SET_FEATURE, 7: SET_DESCRIPTOR */ 433 if(usbRxToken < 0x10){ /* OUT to endpoint != 0: endpoint number in usbRxToken */
411 /* 12: SYNCH_FRAME */ 434 usbFunctionWriteOut(data, len);
-   435 return;
412 } 436 }
-   437 #endif
-   438 if(usbRxToken == (uchar)USBPID_SETUP){
-   439 if(len != 8) /* Setup size must be always 8 bytes. Ignore otherwise. */
-   440 return;
413 #undef SET_REPLY_LEN 441 usbMsgLen_t replyLen;
-   442 usbTxBuf[0] = USBPID_DATA0; /* initialize data toggling */
-   443 usbTxLen = USBPID_NAK; /* abort pending transmit */
-   444 usbMsgFlags = 0;
-   445 uchar type = rq->bmRequestType & USBRQ_TYPE_MASK;
414 }else{ /* not a standard request -- must be vendor or class request */ 446 if(type != USBRQ_TYPE_STANDARD){ /* standard requests are handled by driver */
415 replyLen = usbFunctionSetup(data); 447 replyLen = usbFunctionSetup(data);
-   448 }else{
-   449 replyLen = usbDriverSetup(rq);
416 } 450 }
417 #if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE 451 #if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE
418 if(replyLen == 0xff){ /* use user-supplied read/write function */ 452 if(replyLen == USB_NO_MSG){ /* use user-supplied read/write function */
-   453 /* do some conditioning on replyLen, but on IN transfers only */
419 if((rq->bmRequestType & USBRQ_DIR_MASK) == USBRQ_DIR_DEVICE_TO_HOST){ 454 if((rq->bmRequestType & USBRQ_DIR_MASK) != USBRQ_DIR_HOST_TO_DEVICE){
-   455 if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */
420 replyLen = rq->wLength.bytes[0]; /* IN transfers only */ 456 replyLen = rq->wLength.bytes[0];
-   457 }else{
-   458 replyLen = rq->wLength.word;
-   459 }
421 } 460 }
422 flags &= ~USB_FLG_USE_DEFAULT_RW; /* we have no valid msg, use user supplied read/write functions */ 461 usbMsgFlags = USB_FLG_USE_USER_RW;
423 }else /* The 'else' prevents that we limit a replyLen of 0xff to the maximum transfer len. */ 462 }else /* The 'else' prevents that we limit a replyLen of USB_NO_MSG to the maximum transfer len. */
424 #endif 463 #endif
-   464 if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */
425 if(!rq->wLength.bytes[1] && replyLen > rq->wLength.bytes[0]) /* limit length to max */ 465 if(!rq->wLength.bytes[1] && replyLen > rq->wLength.bytes[0]) /* limit length to max */
426 replyLen = rq->wLength.bytes[0]; 466 replyLen = rq->wLength.bytes[0];
-   467 }else{
-   468 if(replyLen > rq->wLength.word) /* limit length to max */
-   469 replyLen = rq->wLength.word;
427 } 470 }
428 /* make sure that data packets which are sent as ACK to an OUT transfer are always zero sized */ 471 usbMsgLen = replyLen;
429 }else{ /* DATA packet from out request */ 472 }else{ /* usbRxToken must be USBPID_OUT, which means data phase of setup (control-out) */
430 #if USB_CFG_IMPLEMENT_FN_WRITE 473 #if USB_CFG_IMPLEMENT_FN_WRITE
431 if(!(usbMsgFlags & USB_FLG_USE_DEFAULT_RW)){ 474 if(usbMsgFlags & USB_FLG_USE_USER_RW){
432 uchar rval = usbFunctionWrite(data, len); 475 uchar rval = usbFunctionWrite(data, len);
433 replyLen = 0xff; -  
434 if(rval == 0xff){ /* an error occurred */ 476 if(rval == 0xff){ /* an error occurred */
435 usbMsgLen = 0xff; /* cancel potentially pending data packet for ACK */ -  
436 usbTxLen = USBPID_STALL; 477 usbTxLen = USBPID_STALL;
437 }else if(rval != 0){ /* This was the final package */ 478 }else if(rval != 0){ /* This was the final package */
438 replyLen = 0; /* answer with a zero-sized data packet */ 479 usbMsgLen = 0; /* answer with a zero-sized data packet */
439 } 480 }
440 flags = 0; /* start with a DATA1 package, stay with user supplied write() function */ -  
441 } 481 }
442 #endif 482 #endif
443 } 483 }
444 usbMsgFlags = flags; -  
445 usbMsgLen = replyLen; -  
446 } 484 }
447   485  
448 /* ------------------------------------------------------------------------- */ 486 /* ------------------------------------------------------------------------- */
449   487  
-   488 /* This function is similar to usbFunctionRead(), but it's also called for
-   489 * data handled automatically by the driver (e.g. descriptor reads).
-   490 */
-   491 static uchar usbDeviceRead(uchar *data, uchar len)
-   492 {
-   493 if(len > 0){ /* don't bother app with 0 sized reads */
-   494 #if USB_CFG_IMPLEMENT_FN_READ
-   495 if(usbMsgFlags & USB_FLG_USE_USER_RW){
-   496 len = usbFunctionRead(data, len);
-   497 }else
-   498 #endif
-   499 {
-   500 uchar i = len;
-   501 usbMsgPtr_t r = usbMsgPtr;
-   502 if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */
-   503 do{
-   504 uchar c = USB_READ_FLASH(r); /* assign to char size variable to enforce byte ops */
-   505 *data++ = c;
-   506 r++;
-   507 }while(--i);
-   508 }else{ /* RAM data */
-   509 do{
-   510 *data++ = *((uchar *)r);
-   511 r++;
-   512 }while(--i);
-   513 }
-   514 usbMsgPtr = r;
-   515 }
-   516 }
-   517 return len;
-   518 }
-   519  
-   520 /* ------------------------------------------------------------------------- */
-   521  
-   522 /* usbBuildTxBlock() is called when we have data to transmit and the
-   523 * interrupt routine's transmit buffer is empty.
-   524 */
450 static void usbBuildTxBlock(void) 525 static inline void usbBuildTxBlock(void)
451 { 526 {
-   527 usbMsgLen_t wantLen;
452 uchar wantLen, len, txLen, token; 528 uchar len;
453   529  
454 wantLen = usbMsgLen; 530 wantLen = usbMsgLen;
455 if(wantLen > 8) 531 if(wantLen > 8)
456 wantLen = 8; 532 wantLen = 8;
457 usbMsgLen -= wantLen; 533 usbMsgLen -= wantLen;
458 token = USBPID_DATA1; -  
459 if(usbMsgFlags & USB_FLG_TX_PACKET) -  
460 token = USBPID_DATA0; 534 usbTxBuf[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* DATA toggling */
461 usbMsgFlags++; -  
462 len = usbRead(usbTxBuf + 1, wantLen); 535 len = usbDeviceRead(usbTxBuf + 1, wantLen);
463 if(len <= 8){ /* valid data packet */ 536 if(len <= 8){ /* valid data packet */
464 usbCrc16Append(&usbTxBuf[1], len); 537 usbCrc16Append(&usbTxBuf[1], len);
465 txLen = len + 4; /* length including sync byte */ 538 len += 4; /* length including sync byte */
466 if(len < 8) /* a partial package identifies end of message */ 539 if(len < 12) /* a partial package identifies end of message */
467 usbMsgLen = 0xff; 540 usbMsgLen = USB_NO_MSG;
468 }else{ 541 }else{
469 txLen = USBPID_STALL; /* stall the endpoint */ 542 len = USBPID_STALL; /* stall the endpoint */
470 usbMsgLen = 0xff; 543 usbMsgLen = USB_NO_MSG;
471 } 544 }
472 usbTxBuf[0] = token; -  
473 usbTxLen = txLen; 545 usbTxLen = len;
474 DBG2(0x20, usbTxBuf, txLen-1); 546 DBG2(0x20, usbTxBuf, len-1);
475 } 547 }
476   548  
-   549 /* ------------------------------------------------------------------------- */
-   550  
477 static inline uchar isNotSE0(void) 551 static inline void usbHandleResetHook(uchar notResetState)
478 { 552 {
-   553 #ifdef USB_RESET_HOOK
479 uchar rval; 554 static uchar wasReset;
480 /* We want to do 555 uchar isReset = !notResetState;
-   556  
481 * return (USBIN & USBMASK); 557 if(wasReset != isReset){
482 * here, but the compiler does int-expansion acrobatics. 558 USB_RESET_HOOK(isReset);
483 * We can avoid this by assigning to a char-sized variable. 559 wasReset = isReset;
484 */ 560 }
-   561 #else
485 rval = USBIN & USBMASK; 562 notResetState = notResetState; // avoid compiler warning
486 return rval; 563 #endif
487 } 564 }
488   565  
489 /* ------------------------------------------------------------------------- */ 566 /* ------------------------------------------------------------------------- */
490   567  
491 void usbPoll(void) 568 USB_PUBLIC void usbPoll(void)
492 { 569 {
493 uchar len, i; 570 schar len;
-   571 uchar i;
494   572  
495 if((len = usbRxLen) > 0){ 573 len = usbRxLen - 3;
-   574 if(len >= 0){
496 /* We could check CRC16 here -- but ACK has already been sent anyway. If you 575 /* We could check CRC16 here -- but ACK has already been sent anyway. If you
497 * need data integrity checks with this driver, check the CRC in your app 576 * need data integrity checks with this driver, check the CRC in your app
498 * code and report errors back to the host. Since the ACK was already sent, 577 * code and report errors back to the host. Since the ACK was already sent,
499 * retries must be handled on application level. 578 * retries must be handled on application level.
500 * unsigned crc = usbCrc16(buffer + 1, usbRxLen - 3); 579 * unsigned crc = usbCrc16(buffer + 1, usbRxLen - 3);
501 */ 580 */
502 usbProcessRx(usbRxBuf + USB_BUFSIZE + 1 - usbInputBufOffset, len - 3); 581 usbProcessRx(usbRxBuf + USB_BUFSIZE + 1 - usbInputBufOffset, len);
503 #if USB_CFG_HAVE_FLOWCONTROL 582 #if USB_CFG_HAVE_FLOWCONTROL
504 if(usbRxLen > 0) /* only mark as available if not inactivated */ 583 if(usbRxLen > 0) /* only mark as available if not inactivated */
505 usbRxLen = 0; 584 usbRxLen = 0;
506 #else 585 #else
507 usbRxLen = 0; /* mark rx buffer as available */ 586 usbRxLen = 0; /* mark rx buffer as available */
508 #endif 587 #endif
509 } 588 }
510 if(usbTxLen & 0x10){ /* transmit system idle */ 589 if(usbTxLen & 0x10){ /* transmit system idle */
511 if(usbMsgLen != 0xff){ /* transmit data pending? */ 590 if(usbMsgLen != USB_NO_MSG){ /* transmit data pending? */
512 usbBuildTxBlock(); 591 usbBuildTxBlock();
513 } 592 }
514 } 593 }
515 for(i = 10; i > 0; i--){ 594 for(i = 20; i > 0; i--){
-   595 uchar usbLineStatus = USBIN & USBMASK;
516 if(isNotSE0()) 596 if(usbLineStatus != 0) /* SE0 has ended */
517 break; 597 goto isNotReset;
518 } 598 }
519 if(i == 0){ /* RESET condition, called multiple times during reset */ 599 /* RESET condition, called multiple times during reset */
520 usbNewDeviceAddr = 0; 600 usbNewDeviceAddr = 0;
521 usbDeviceAddr = 0; 601 usbDeviceAddr = 0;
522 #if USB_CFG_IMPLEMENT_HALT -  
523 usbTxLen1 = USBPID_NAK; -  
524 #if USB_CFG_HAVE_INTRIN_ENDPOINT3 -  
525 usbTxLen3 = USBPID_NAK; 602 usbResetStall();
526 #endif -  
527 #endif -  
528 DBG1(0xff, 0, 0); 603 DBG1(0xff, 0, 0);
529 } 604 isNotReset:
-   605 usbHandleResetHook(i);
530 } 606 }
531   607  
532 /* ------------------------------------------------------------------------- */ 608 /* ------------------------------------------------------------------------- */
533   609  
534 void usbInit(void) 610 USB_PUBLIC void usbInit(void)
535 { 611 {
536 #if USB_INTR_CFG_SET != 0 612 #if USB_INTR_CFG_SET != 0
537 USB_INTR_CFG |= USB_INTR_CFG_SET; 613 USB_INTR_CFG |= USB_INTR_CFG_SET;
538 #endif 614 #endif
539 #if USB_INTR_CFG_CLR != 0 615 #if USB_INTR_CFG_CLR != 0
540 USB_INTR_CFG &= ~(USB_INTR_CFG_CLR); 616 USB_INTR_CFG &= ~(USB_INTR_CFG_CLR);
541 #endif 617 #endif
542 USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT); 618 USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
-   619 usbResetDataToggling();
543 #if USB_CFG_HAVE_INTRIN_ENDPOINT 620 #if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
544 USB_SET_DATATOKEN1(USBPID_DATA0); /* reset data toggling for interrupt endpoint */ 621 usbTxLen1 = USBPID_NAK;
545 # if USB_CFG_HAVE_INTRIN_ENDPOINT3 622 #if USB_CFG_HAVE_INTRIN_ENDPOINT3
546 USB_SET_DATATOKEN3(USBPID_DATA0); /* reset data toggling for interrupt endpoint */ 623 usbTxLen3 = USBPID_NAK;
547 # endif 624 #endif
548 #endif 625 #endif
549 } 626 }
550   627  
551 /* ------------------------------------------------------------------------- */ 628 /* ------------------------------------------------------------------------- */