USBasp 2005.04.21.
[pub/USBasp.git] / firmware / usbdrv / usbdrv.c
1 /* Name: usbdrv.c
2 * Project: AVR USB driver
3 * Author: Christian Starkjohann
4 * Creation Date: 2004-12-29
5 * Tabsize: 4
6 * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
7 * License: Proprietary, free under certain conditions. See Documentation.
8 * This Revision: $Id: usbdrv.c 53 2005-04-12 17:11:29Z cs $
9 */
10
11 #include <avr/io.h>
12 #include <avr/pgmspace.h>
13 #include "usbdrv.h"
14 #include "oddebug.h"
15
16 /*
17 General Description:
18 This module implements the C-part of the USB driver. See usbdrv.h for a
19 documentation of the entire driver.
20 */
21
22 /* ------------------------------------------------------------------------- */
23
24 /* raw USB registers / interface to assembler code: */
25 /* usbRxBuf MUST be in 1 byte addressable range (because usbInputBuf is only 1 byte) */
26 static char usbRxBuf[2][USB_BUFSIZE];/* raw RX buffer: PID, 8 bytes data, 2 bytes CRC */
27 uchar usbDeviceId; /* assigned during enumeration, defaults to 0 */
28 uchar usbInputBuf; /* ptr to raw buffer used for receiving */
29 uchar usbAppBuf; /* ptr to raw buffer passed to app for processing */
30 volatile char usbRxLen; /* = 0; number of bytes in usbAppBuf; 0 means free */
31 uchar usbCurrentTok; /* last token received */
32 uchar usbRxToken; /* token for data we received */
33 uchar usbMsgLen = 0xff; /* remaining number of bytes, no msg to send if -1 (see usbMsgPtr) */
34 volatile char usbTxLen = -1; /* number of bytes to transmit with next IN token */
35 uchar usbTxBuf[USB_BUFSIZE];/* data to transmit with next IN, free if usbTxLen == -1 */
36 #if USB_CFG_HAVE_INTRIN_ENDPOINT
37 /* uchar usbRxEndp; endpoint which was addressed (1 bit in MSB) [not impl] */
38 volatile char usbTxLen1 = -1; /* TX count for endpoint 1 */
39 uchar usbTxBuf1[USB_BUFSIZE];/* TX data for endpoint 1 */
40 #endif
41 uchar usbAckBuf[1] = {USBPID_ACK}; /* transmit buffer for ack tokens */
42 uchar usbNakBuf[1] = {USBPID_NAK}; /* transmit buffer for nak tokens */
43
44 /* USB status registers / not shared with asm code */
45 uchar *usbMsgPtr; /* data to transmit next -- ROM or RAM address */
46 static uchar usbMsgFlags; /* flag values see below */
47 static uchar usbNewDeviceId; /* = 0; device ID which should be set after status phase */
48 static uchar usbIsReset; /* = 0; USB bus is in reset phase */
49
50 #define USB_FLG_TX_PACKET (1<<0)
51 /* Leave free 6 bits after TX_PACKET. This way we can increment usbMsgFlags to toggle TX_PACKET */
52 #define USB_FLG_MSGPTR_IS_ROM (1<<6)
53 #define USB_FLG_USE_DEFAULT_RW (1<<7)
54
55 /*
56 optimizing hints:
57 - do not post/pre inc/dec integer values in operations
58 - assign value of PRG_RDB() to register variables and don't use side effects in arg
59 - use narrow scope for variables which should be in X/Y/Z register
60 - assign char sized expressions to variables to force 8 bit arithmetics
61 */
62
63 /* ------------------------------------------------------------------------- */
64
65 static char usbDescrDevice[] PROGMEM = { /* USB device descriptor */
66 18, /* sizeof(usbDescrDevice): length of descriptor in bytes */
67 1, /* descriptor type */
68 0x01, 0x01, /* USB version supported */
69 USB_CFG_DEVICE_CLASS,
70 USB_CFG_DEVICE_SUBCLASS,
71 0, /* protocol */
72 8, /* max packet size */
73 USB_CFG_VENDOR_ID, /* 2 bytes */
74 USB_CFG_DEVICE_ID, /* 2 bytes */
75 USB_CFG_DEVICE_VERSION, /* 2 bytes */
76 #if USB_CFG_VENDOR_NAME_LEN
77 1, /* manufacturer string index */
78 #else
79 0, /* manufacturer string index */
80 #endif
81 #if USB_CFG_DEVICE_NAME_LEN
82 2, /* product string index */
83 #else
84 0, /* product string index */
85 #endif
86 0, /* serial number string index */
87 1, /* number of configurations */
88 };
89
90 static char usbDescrConfig[] PROGMEM = { /* USB configuration descriptor */
91 9, /* sizeof(usbDescrConfig): length of descriptor in bytes */
92 2, /* descriptor type */
93 (18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT), 0, /* total length of data returned (including inlined descriptors) */
94 1, /* number of interfaces in this configuration */
95 1, /* index of this configuration */
96 0, /* configuration name string index */
97 #if USB_CFG_IS_SELF_POWERED
98 USBATTR_SELFPOWER, /* attributes */
99 #else
100 USBATTR_BUSPOWER, /* attributes */
101 #endif
102 USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */
103 /* interface descriptor follows inline: */
104 9, /* sizeof(usbDescrInterface): length of descriptor in bytes */
105 4, /* descriptor type */
106 0, /* index of this interface */
107 0, /* alternate setting for this interface */
108 USB_CFG_HAVE_INTRIN_ENDPOINT, /* endpoints excl 0: number of endpoint descriptors to follow */
109 USB_CFG_INTERFACE_CLASS,
110 USB_CFG_INTERFACE_SUBCLASS,
111 USB_CFG_INTERFACE_PROTOCOL,
112 0, /* string index for interface */
113 #if USB_CFG_HAVE_INTRIN_ENDPOINT /* endpoint descriptor for endpoint 1 */
114 7, /* sizeof(usbDescrEndpoint) */
115 5, /* descriptor type = endpoint */
116 0x81, /* IN endpoint number 1 */
117 0x03, /* attrib: Interrupt endpoint */
118 8, 0, /* maximum packet size */
119 USB_CFG_INTR_POLL_INTERVAL, /* in ms */
120 #endif
121 };
122
123 static char usbDescrString0[] PROGMEM = { /* language descriptor */
124 4, /* sizeof(usbDescrString0): length of descriptor in bytes */
125 3, /* descriptor type */
126 0x09, 0x04, /* language index (0x0409 = US-English) */
127 };
128
129 #if USB_CFG_VENDOR_NAME_LEN
130 static int usbDescrString1[] PROGMEM = {
131 (2 * USB_CFG_VENDOR_NAME_LEN + 2) | (3<<8), /* length of descriptor in bytes | descriptor type */
132 USB_CFG_VENDOR_NAME
133 };
134 #endif
135 #if USB_CFG_DEVICE_NAME_LEN
136 static int usbDescrString2[] PROGMEM = {
137 (2 * USB_CFG_DEVICE_NAME_LEN + 2) | (3<<8), /* length of descriptor in bytes | descriptor type */
138 USB_CFG_DEVICE_NAME
139 };
140 #endif
141
142 /* We don't use prog_int or prog_int16_t for compatibility with various libc
143 * versions. Here's an other compatibility hack:
144 */
145 #ifndef PRG_RDB
146 #define PRG_RDB(addr) pgm_read_byte(addr)
147 #endif
148
149 typedef union{
150 unsigned word;
151 uchar *ptr;
152 uchar bytes[2];
153 }converter_t;
154 /* We use this union to do type conversions. This is better optimized than
155 * type casts in gcc 3.4.3 and much better than using bit shifts to build
156 * ints from chars. Byte ordering is not a problem on an 8 bit platform.
157 */
158
159 /* ------------------------------------------------------------------------- */
160
161 #if USB_CFG_HAVE_INTRIN_ENDPOINT
162 static uchar usbTxPacketCnt1;
163
164 void usbSetInterrupt(uchar *data, uchar len)
165 {
166 uchar *p, i;
167 converter_t crc;
168
169 if(len > 7)
170 len = 7;
171 i = USBPID_DATA1;
172 if(usbTxPacketCnt1 & 1)
173 i = USBPID_DATA0;
174 if(usbTxLen1 < 0){ /* packet buffer was empty */
175 usbTxPacketCnt1++;
176 }else{
177 usbTxLen1 = -1; /* avoid sending incomplete interrupt data */
178 }
179 p = usbTxBuf1;
180 *p++ = i;
181 for(i=len;i--;)
182 *p++ = *data++;
183 crc.word = usbCrc16(&usbTxBuf1[1], len);
184 usbTxBuf1[len + 1] = crc.bytes[0];
185 usbTxBuf1[len + 2] = crc.bytes[1];
186 usbTxLen1 = len + 4; /* len must be given including sync byte */
187 }
188 #endif
189
190 static void usbWrite(uchar *data, uchar len)
191 {
192 #if USB_CFG_IMPLEMENT_FN_WRITE
193 if(!(usbMsgFlags & USB_FLG_USE_DEFAULT_RW)){
194 if(usbFunctionWrite(data, len) == 0xff){ /* an error occurred */
195 /* usbMsgLen = 0xff; cancel potentially pending ACK [has been done by ASM module when OUT token arrived] */
196 usbTxBuf[0] = USBPID_STALL;
197 usbTxLen = 2; /* length including sync byte */
198 return;
199 }
200 }
201 #endif
202 usbMsgLen = 0; /* send zero-sized block as ACK */
203 usbMsgFlags = 0; /* start with a DATA1 package */
204 }
205
206 static uchar usbRead(uchar *data, uchar len)
207 {
208 #if USB_CFG_IMPLEMENT_FN_READ
209 if(usbMsgFlags & USB_FLG_USE_DEFAULT_RW){
210 #endif
211 uchar i = len, *r = usbMsgPtr;
212 if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */
213 while(i--){
214 char c = PRG_RDB(r); /* assign to char size variable to enforce byte ops */
215 *data++ = c;
216 r++;
217 }
218 }else{ /* RAM data */
219 while(i--)
220 *data++ = *r++;
221 }
222 usbMsgPtr = r;
223 return len;
224 #if USB_CFG_IMPLEMENT_FN_READ
225 }else{
226 if(len != 0) /* don't bother app with 0 sized reads */
227 return usbFunctionRead(data, len);
228 return 0;
229 }
230 #endif
231 }
232
233 /* Don't make this function static to avoid inlining.
234 * The entire function would become too large and exceed the range of
235 * relative jumps.
236 */
237 void usbProcessRx(uchar *data, uchar len)
238 {
239 /* We use if() cascades because the compare is done byte-wise while switch()
240 * is int-based. The if() cascades are therefore more efficient.
241 */
242 DBG2(0x10 + (usbRxToken == (uchar)USBPID_SETUP), data, len);
243 if(usbRxToken == (uchar)USBPID_SETUP){
244 uchar replyLen = 0, flags = USB_FLG_USE_DEFAULT_RW;
245 if(len == 8){ /* Setup size must be always 8 bytes. Ignore otherwise. */
246 uchar type = data[0] & (3 << 5);
247 if(type == USBRQ_TYPE_STANDARD << 5){
248 uchar *replyData = usbTxBuf + 9; /* there is 3 bytes free space at the end of the buffer */
249 replyData[0] = 0;
250 if(data[1] == 0){/* GET_STATUS */
251 #if USB_CFG_IS_SELF_POWERED
252 uchar recipient = data[0] & 0x1f; /* assign arith ops to variables to enforce byte size */
253 if(recipient == USBRQ_RCPT_DEVICE)
254 replyData[0] = USB_CFG_IS_SELF_POWERED;
255 #endif
256 replyData[1] = 0;
257 replyLen = 2;
258 }else if(data[1] == 5){ /* SET_ADDRESS */
259 usbNewDeviceId = data[2];
260 }else if(data[1] == 6){ /* GET_DESCRIPTOR */
261 flags = USB_FLG_MSGPTR_IS_ROM | USB_FLG_USE_DEFAULT_RW;
262 if(data[3] == 1){ /* descriptor type requested */
263 replyLen = sizeof(usbDescrDevice);
264 replyData = (uchar *)usbDescrDevice;
265 }else if(data[3] == 2){
266 replyLen = sizeof(usbDescrConfig);
267 replyData = (uchar *)usbDescrConfig;
268 }else if(data[3] == 3){ /* string descriptor */
269 if(data[2] == 0){ /* descriptor index */
270 replyLen = sizeof(usbDescrString0);
271 replyData = (uchar *)usbDescrString0;
272 #if USB_CFG_VENDOR_NAME_LEN
273 }else if(data[2] == 1){
274 replyLen = sizeof(usbDescrString1);
275 replyData = (uchar *)usbDescrString1;
276 #endif
277 #if USB_CFG_DEVICE_NAME_LEN
278 }else if(data[2] == 2){
279 replyLen = sizeof(usbDescrString2);
280 replyData = (uchar *)usbDescrString2;
281 #endif
282 }
283 }
284 }else if(data[1] == 8){ /* GET_CONFIGURATION */
285 replyLen = 1;
286 replyData[0] = 1; /* config is always 1, no setConfig required */
287 }else if(data[1] == 10){ /* GET_INTERFACE */
288 replyLen = 1;
289 #if USB_CFG_HAVE_INTRIN_ENDPOINT
290 }else if(data[1] == 11){ /* SET_INTERFACE */
291 usbTxPacketCnt1 = 0; /* reset data toggling for interrupt socket */
292 #endif
293 }else{
294 /* the following requests can be ignored, send default reply */
295 /* 1: CLEAR_FEATURE, 3: SET_FEATURE, 7: SET_DESCRIPTOR */
296 /* 9: SET_CONFIGURATION, 11: SET_INTERFACE, 12: SYNCH_FRAME */
297 }
298 usbMsgPtr = replyData;
299 if(!data[7] && replyLen > data[6]) /* max length is in data[7]:data[6] */
300 replyLen = data[6];
301 }else{ /* not a standard request -- must be vendor or class request */
302 #if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE
303 uchar len;
304 replyLen = data[6]; /* if this is an OUT operation, the next token will reset usbMsgLen */
305 if((len = usbFunctionSetup(data)) != 0xff){
306 replyLen = len;
307 }else{
308 flags = 0; /* we have no valid msg, use read/write functions */
309 }
310 #else
311 replyLen = usbFunctionSetup(data);
312 #endif
313 }
314 }
315 usbMsgLen = replyLen;
316 usbMsgFlags = flags;
317 }else{ /* out request */
318 usbWrite(data, len);
319 }
320 }
321
322 /* ------------------------------------------------------------------------- */
323
324 static void usbBuildTxBlock(void)
325 {
326 uchar wantLen, len, txLen, x;
327 converter_t crc;
328
329 x = USBPID_DATA1;
330 if(usbMsgFlags & USB_FLG_TX_PACKET)
331 x = USBPID_DATA0;
332 usbMsgFlags++;
333 usbTxBuf[0] = x;
334 wantLen = usbMsgLen;
335 if(wantLen > 8)
336 wantLen = 8;
337 usbMsgLen -= wantLen;
338 len = usbRead(usbTxBuf + 1, wantLen);
339 if(len <= 8){ /* valid data packet */
340 crc.word = usbCrc16(&usbTxBuf[1], len);
341 usbTxBuf[len + 1] = crc.bytes[0];
342 usbTxBuf[len + 2] = crc.bytes[1];
343 txLen = len + 4; /* length including sync byte */
344 if(len < 8) /* a partial package identifies end of message */
345 usbMsgLen = 0xff;
346 }else{
347 usbTxBuf[0] = USBPID_STALL;
348 txLen = 2; /* length including sync byte */
349 usbMsgLen = 0xff;
350 }
351 usbTxLen = txLen;
352 DBG2(0x20, usbTxBuf, txLen-1);
353 }
354
355 static inline uchar isNotSE0(void)
356 {
357 uchar rval;
358 /* We want to do
359 * return (USBIN & USBMASK);
360 * here, but the compiler does int-expansion acrobatics.
361 * We can avoid this by assigning to a char-sized variable.
362 */
363 rval = USBIN & USBMASK;
364 return rval;
365 }
366
367 /* ------------------------------------------------------------------------- */
368
369 void usbPoll(void)
370 {
371 uchar len;
372
373 if((len = usbRxLen) > 0){
374 /* We could check CRC16 here -- but ACK has already been sent anyway. If you
375 * need data integrity checks with this driver, check the CRC in your app
376 * code and report errors back to the host. Since the ACK was already sent,
377 * retries must be handled on application level.
378 * unsigned crc = usbCrc16((uchar *)(unsigned)(usbAppBuf + 1), usbRxLen - 3);
379 */
380 len -= 3; /* remove PID and CRC */
381 if(len < 128){
382 usbProcessRx((uchar *)(unsigned)(usbAppBuf + 1), len);
383 }
384 usbRxLen = 0; /* mark rx buffer as available */
385 }
386 if(usbTxLen < 0){ /* TX system is idle */
387 if(usbMsgLen != 0xff){
388 usbBuildTxBlock();
389 }else if(usbNewDeviceId){
390 usbDeviceId = usbNewDeviceId;
391 DBG1(1, &usbNewDeviceId, 1);
392 usbNewDeviceId = 0;
393 }
394 }
395 if(isNotSE0()){ /* SE0 state */
396 usbIsReset = 0;
397 }else{
398 /* check whether SE0 lasts for more than 2.5us (3.75 bit times) */
399 if(!usbIsReset){
400 uchar i;
401 for(i=100;i;i--){
402 if(isNotSE0())
403 goto notUsbReset;
404 }
405 usbIsReset = 1;
406 usbDeviceId = 0;
407 usbNewDeviceId = 0;
408 DBG1(0xff, 0, 0);
409 notUsbReset:;
410 }
411 }
412 }
413
414 /* ------------------------------------------------------------------------- */
415
416 void usbInit(void)
417 {
418 usbInputBuf = (uchar)usbRxBuf[0];
419 usbAppBuf = (uchar)usbRxBuf[1];
420 #if USB_INTR_CFG_SET != 0
421 USB_INTR_CFG |= USB_INTR_CFG_SET;
422 #endif
423 #if USB_INTR_CFG_CLR != 0
424 USB_INTR_CFG &= ~(USB_INTR_CFG_CLR);
425 #endif
426 USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
427 }
428
429 /* ------------------------------------------------------------------------- */