Rev Author Line No. Line
3331 kaklik 1 // ======================================================================
2 // USB driver
3 //
4 // Entry points:
5 // usb_init() - enable the USB interrupt
6 // usb_poll() - poll for incoming packets and process them
7 //
8 // This code communicates with the interrupt handler through a number of
9 // global variables, including two input buffers and one output buffer.
10 // Packets are queued for transmission by copying them into the output
11 // buffer. The interrupt handler will transmit such a packet on the
12 // reception of an IN packet.
13 //
14 // Standard SETUP packets are handled here. Non-standard SETUP packets
15 // are forwarded to the application code by calling usb_setup(). The
16 // macros USBTINY_CALLBACK_IN and USBTINY_CALLBACK_OUT control whether
17 // the callback functions usb_in() and usb_out() will be called for IN
18 // and OUT transfers.
19 //
3333 kaklik 20 // Maximum stack usage (gcc 4.1.0 & 4.3.4) of usb_poll(): 5 bytes plus
3331 kaklik 21 // possible additional stack usage in usb_setup(), usb_in() or usb_out().
22 //
3333 kaklik 23 // Copyright 2006-2010 Dick Streefland
3331 kaklik 24 //
25 // This is free software, licensed under the terms of the GNU General
26 // Public License as published by the Free Software Foundation.
27 // ======================================================================
28  
29 #include <avr/pgmspace.h>
30 #include <avr/interrupt.h>
31 #include "def.h"
32 #include "usb.h"
33  
34 #define LE(word) (word) & 0xff, (word) >> 8
35  
36 // ----------------------------------------------------------------------
37 // USB constants
38 // ----------------------------------------------------------------------
39  
40 enum
41 {
42 DESCRIPTOR_TYPE_DEVICE = 1,
43 DESCRIPTOR_TYPE_CONFIGURATION,
44 DESCRIPTOR_TYPE_STRING,
45 DESCRIPTOR_TYPE_INTERFACE,
46 DESCRIPTOR_TYPE_ENDPOINT,
47 };
48  
49 // ----------------------------------------------------------------------
50 // Interrupt handler interface
51 // ----------------------------------------------------------------------
52  
53 byte_t usb_rx_buf[2*USB_BUFSIZE]; // two input buffers
54 byte_t usb_rx_off; // buffer offset: 0 or USB_BUFSIZE
55 byte_t usb_rx_len; // buffer size, 0 means empty
56 byte_t usb_rx_token; // PID of token packet: SETUP or OUT
57  
58 byte_t usb_tx_buf[USB_BUFSIZE]; // output buffer
59 byte_t usb_tx_len; // output buffer size, 0 means empty
60  
3333 kaklik 61 byte_t usb_address; // assigned device address
62 byte_t usb_new_address; // new device address
3331 kaklik 63  
64 // ----------------------------------------------------------------------
65 // Local data
66 // ----------------------------------------------------------------------
67  
68 enum
69 {
70 TX_STATE_IDLE = 0, // transmitter idle
71 TX_STATE_RAM, // usb_tx_data is a RAM address
72 TX_STATE_ROM, // usb_tx_data is a ROM address
73 TX_STATE_CALLBACK, // call usb_in() to obtain transmit data
74 };
75  
76 static byte_t usb_tx_state; // TX_STATE_*, see enum above
77 static byte_t usb_tx_total; // total transmit size
78 static byte_t* usb_tx_data; // pointer to data to transmit
79  
80 #if defined USBTINY_VENDOR_NAME
81 struct
82 {
83 byte_t length;
84 byte_t type;
85 int string[sizeof(USBTINY_VENDOR_NAME)-1];
3333 kaklik 86 } const string_vendor PROGMEM =
3331 kaklik 87 {
88 2 * sizeof(USBTINY_VENDOR_NAME),
89 DESCRIPTOR_TYPE_STRING,
90 { CAT2(L, USBTINY_VENDOR_NAME) }
91 };
92 # define VENDOR_NAME_ID 1
93 #else
94 # define VENDOR_NAME_ID 0
95 #endif
96  
97 #if defined USBTINY_DEVICE_NAME
98 struct
99 {
100 byte_t length;
101 byte_t type;
102 int string[sizeof(USBTINY_DEVICE_NAME)-1];
3333 kaklik 103 } const string_device PROGMEM =
3331 kaklik 104 {
105 2 * sizeof(USBTINY_DEVICE_NAME),
106 DESCRIPTOR_TYPE_STRING,
107 { CAT2(L, USBTINY_DEVICE_NAME) }
108 };
109 # define DEVICE_NAME_ID 2
110 #else
111 # define DEVICE_NAME_ID 0
112 #endif
113  
114 #if defined USBTINY_SERIAL
115 struct
116 {
117 byte_t length;
118 byte_t type;
119 int string[sizeof(USBTINY_SERIAL)-1];
3333 kaklik 120 } const string_serial PROGMEM =
3331 kaklik 121 {
122 2 * sizeof(USBTINY_SERIAL),
123 DESCRIPTOR_TYPE_STRING,
124 { CAT2(L, USBTINY_SERIAL) }
125 };
126 # define SERIAL_ID 3
127 #else
128 # define SERIAL_ID 0
129 #endif
130  
131 #if VENDOR_NAME_ID || DEVICE_NAME_ID || SERIAL_ID
3333 kaklik 132 static byte_t const string_langid [] PROGMEM =
3331 kaklik 133 {
134 4, // bLength
135 DESCRIPTOR_TYPE_STRING, // bDescriptorType (string)
136 LE(0x0409), // wLANGID[0] (American English)
137 };
138 #endif
139  
140 // Device Descriptor
3333 kaklik 141 static byte_t const descr_device [18] PROGMEM =
3331 kaklik 142 {
143 18, // bLength
144 DESCRIPTOR_TYPE_DEVICE, // bDescriptorType
3333 kaklik 145 LE(0x0101), // bcdUSB
3331 kaklik 146 USBTINY_DEVICE_CLASS, // bDeviceClass
147 USBTINY_DEVICE_SUBCLASS, // bDeviceSubClass
148 USBTINY_DEVICE_PROTOCOL, // bDeviceProtocol
149 8, // bMaxPacketSize0
150 LE(USBTINY_VENDOR_ID), // idVendor
151 LE(USBTINY_DEVICE_ID), // idProduct
152 LE(USBTINY_DEVICE_VERSION), // bcdDevice
153 VENDOR_NAME_ID, // iManufacturer
154 DEVICE_NAME_ID, // iProduct
155 SERIAL_ID, // iSerialNumber
156 1, // bNumConfigurations
157 };
158  
159 // Configuration Descriptor
3333 kaklik 160 static byte_t const descr_config [] PROGMEM =
3331 kaklik 161 {
162 9, // bLength
163 DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
164 LE(9+9+7*USBTINY_ENDPOINT), // wTotalLength
165 1, // bNumInterfaces
166 1, // bConfigurationValue
167 0, // iConfiguration
168 (USBTINY_MAX_POWER ? 0x80 : 0xc0), // bmAttributes
169 (USBTINY_MAX_POWER + 1) / 2, // MaxPower
170  
171 // Standard Interface Descriptor
172 9, // bLength
173 DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
174 0, // bInterfaceNumber
175 0, // bAlternateSetting
176 USBTINY_ENDPOINT, // bNumEndpoints
177 USBTINY_INTERFACE_CLASS, // bInterfaceClass
178 USBTINY_INTERFACE_SUBCLASS, // bInterfaceSubClass
179 USBTINY_INTERFACE_PROTOCOL, // bInterfaceProtocol
180 0, // iInterface
181  
182 #if USBTINY_ENDPOINT
183 // Additional Endpoint
184 7, // bLength
185 DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
186 USBTINY_ENDPOINT_ADDRESS, // bEndpointAddress
187 USBTINY_ENDPOINT_TYPE, // bmAttributes
188 LE(8), // wMaxPacketSize
189 USBTINY_ENDPOINT_INTERVAL, // bInterval
190 #endif
191 };
192  
193 // ----------------------------------------------------------------------
194 // Inspect an incoming packet.
195 // ----------------------------------------------------------------------
196 static void usb_receive ( byte_t* data, byte_t rx_len )
197 {
198 byte_t len;
199 byte_t type;
200 byte_t limit;
201  
202 usb_tx_state = TX_STATE_RAM;
203 len = 0;
204 if ( usb_rx_token == USB_PID_SETUP )
205 {
206 limit = data[6];
207 if ( data[7] )
208 {
209 limit = 255;
210 }
211 type = data[0] & 0x60;
212 if ( type == 0x00 )
213 { // Standard request
214 if ( data[1] == 0 ) // GET_STATUS
215 {
216 len = 2;
217 #if USBTINY_MAX_POWER == 0
218 data[0] = (data[0] == 0x80);
219 #else
220 data[0] = 0;
221 #endif
222 data[1] = 0;
223 }
224 else if ( data[1] == 5 ) // SET_ADDRESS
225 {
3333 kaklik 226 usb_new_address = data[2];
227 #ifdef USBTINY_USB_OK_LED
228 SET(USBTINY_USB_OK_LED);// LED on
229 #endif
3331 kaklik 230 }
231 else if ( data[1] == 6 ) // GET_DESCRIPTOR
232 {
233 usb_tx_state = TX_STATE_ROM;
234 if ( data[3] == 1 )
235 { // DEVICE
236 data = (byte_t*) &descr_device;
237 len = sizeof(descr_device);
238 }
239 else if ( data[3] == 2 )
240 { // CONFIGURATION
241 data = (byte_t*) &descr_config;
242 len = sizeof(descr_config);
243 }
244 #if VENDOR_NAME_ID || DEVICE_NAME_ID || SERIAL_ID
245 else if ( data[3] == 3 )
246 { // STRING
247 if ( data[2] == 0 )
248 {
249 data = (byte_t*) &string_langid;
250 len = sizeof(string_langid);
251 }
252 #if VENDOR_NAME_ID
253 else if ( data[2] == VENDOR_NAME_ID )
254 {
255 data = (byte_t*) &string_vendor;
256 len = sizeof(string_vendor);
257 }
258 #endif
259 #if DEVICE_NAME_ID
260 else if ( data[2] == DEVICE_NAME_ID )
261 {
262 data = (byte_t*) &string_device;
263 len = sizeof(string_device);
264 }
265 #endif
266 #if SERIAL_ID
267 else if ( data[2] == SERIAL_ID )
268 {
269 data = (byte_t*) &string_serial;
270 len = sizeof(string_serial);
271 }
272 #endif
273 }
274 #endif
275 }
276 else if ( data[1] == 8 ) // GET_CONFIGURATION
277 {
278 data[0] = 1; // return bConfigurationValue
279 len = 1;
280 }
281 else if ( data[1] == 10 ) // GET_INTERFACE
282 {
283 data[0] = 0;
284 len = 1;
285 }
286 }
287 else
288 { // Class or Vendor request
289 len = usb_setup( data );
290 #if USBTINY_CALLBACK_IN
291 if ( len == 0xff )
292 {
293 usb_tx_state = TX_STATE_CALLBACK;
294 }
295 #endif
296 }
297 if ( len > limit )
298 {
299 len = limit;
300 }
301 usb_tx_data = data;
302 }
303 #if USBTINY_CALLBACK_OUT
304 else if ( rx_len > 0 )
305 { // usb_rx_token == USB_PID_OUT
306 usb_out( data, rx_len );
307 }
308 #endif
309 usb_tx_total = len;
310 usb_tx_buf[0] = USB_PID_DATA0; // next data packet will be DATA1
311 }
312  
313 // ----------------------------------------------------------------------
314 // Load the transmit buffer with the next packet.
315 // ----------------------------------------------------------------------
316 static void usb_transmit ( void )
317 {
318 byte_t len;
319 byte_t* src;
320 byte_t* dst;
321 byte_t i;
322 byte_t b;
323  
324 usb_tx_buf[0] ^= (USB_PID_DATA0 ^ USB_PID_DATA1);
325 len = usb_tx_total;
326 if ( len > 8 )
327 {
328 len = 8;
329 }
330 dst = usb_tx_buf + 1;
331 if ( len > 0 )
332 {
333 #if USBTINY_CALLBACK_IN
334 if ( usb_tx_state == TX_STATE_CALLBACK )
335 {
336 len = usb_in( dst, len );
337 }
338 else
339 #endif
340 {
341 src = usb_tx_data;
342 if ( usb_tx_state == TX_STATE_RAM )
343 {
344 for ( i = 0; i < len; i++ )
345 {
346 *dst++ = *src++;
347 }
348 }
349 else // usb_tx_state == TX_STATE_ROM
350 {
351 for ( i = 0; i < len; i++ )
352 {
353 b = pgm_read_byte( src );
354 src++;
355 *dst++ = b;
356 }
357 }
358 usb_tx_data = src;
359 }
360 usb_tx_total -= len;
361 }
362 crc( usb_tx_buf + 1, len );
363 usb_tx_len = len + 3;
364 if ( len < 8 )
365 { // this is the last packet
366 usb_tx_state = TX_STATE_IDLE;
367 }
368 }
369  
370 // ----------------------------------------------------------------------
371 // Initialize the low-level USB driver.
372 // ----------------------------------------------------------------------
373 extern void usb_init ( void )
374 {
375 USB_INT_CONFIG |= USB_INT_CONFIG_SET;
376 USB_INT_ENABLE |= (1 << USB_INT_ENABLE_BIT);
3333 kaklik 377 #ifdef USBTINY_USB_OK_LED
378 OUTPUT(USBTINY_USB_OK_LED);
379 #endif
380 #ifdef USBTINY_DMINUS_PULLUP
381 SET(USBTINY_DMINUS_PULLUP);
382 OUTPUT(USBTINY_DMINUS_PULLUP); // enable pullup on D-
383 #endif
3331 kaklik 384 sei();
385 }
386  
387 // ----------------------------------------------------------------------
388 // Poll USB driver:
389 // - check for incoming USB packets
390 // - refill an empty transmit buffer
391 // - check for USB bus reset
392 // ----------------------------------------------------------------------
393 extern void usb_poll ( void )
394 {
395 byte_t i;
396  
397 // check for incoming USB packets
398 if ( usb_rx_len != 0 )
399 {
400 usb_receive( usb_rx_buf + USB_BUFSIZE - usb_rx_off + 1, usb_rx_len - 3 );
401 usb_tx_len = 0; // abort pending transmission
402 usb_rx_len = 0; // accept next packet
403 }
404 // refill an empty transmit buffer, when the transmitter is active
3333 kaklik 405 if ( usb_tx_len == 0 && usb_tx_state != TX_STATE_IDLE )
3331 kaklik 406 {
3333 kaklik 407 usb_transmit();
3331 kaklik 408 }
409 // check for USB bus reset
410 for ( i = 10; i > 0 && ! (USB_IN & USB_MASK_DMINUS); i-- )
411 {
412 }
413 if ( i == 0 )
414 { // SE0 for more than 2.5uS is a reset
3333 kaklik 415 usb_new_address = 0;
416 usb_address = 0;
417 #ifdef USBTINY_USB_OK_LED
418 CLR(USBTINY_USB_OK_LED); // LED off
419 #endif
3331 kaklik 420 }
421 }