| Line 15... |
Line 15... |
| 15 |
// are forwarded to the application code by calling usb_setup(). The |
15 |
// are forwarded to the application code by calling usb_setup(). The |
| 16 |
// macros USBTINY_CALLBACK_IN and USBTINY_CALLBACK_OUT control whether |
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 |
17 |
// the callback functions usb_in() and usb_out() will be called for IN |
| 18 |
// and OUT transfers. |
18 |
// and OUT transfers. |
| 19 |
// |
19 |
// |
| 20 |
// Maximum stack usage (gcc 3.4.3 & 4.1.0) of usb_poll(): 5 bytes plus |
20 |
// Maximum stack usage (gcc 4.1.0 & 4.3.4) of usb_poll(): 5 bytes plus |
| 21 |
// possible additional stack usage in usb_setup(), usb_in() or usb_out(). |
21 |
// possible additional stack usage in usb_setup(), usb_in() or usb_out(). |
| 22 |
// |
22 |
// |
| 23 |
// Copyright (C) 2006 Dick Streefland |
23 |
// Copyright 2006-2010 Dick Streefland |
| 24 |
// |
24 |
// |
| 25 |
// This is free software, licensed under the terms of the GNU General |
25 |
// This is free software, licensed under the terms of the GNU General |
| 26 |
// Public License as published by the Free Software Foundation. |
26 |
// Public License as published by the Free Software Foundation. |
| 27 |
// ====================================================================== |
27 |
// ====================================================================== |
| 28 |
|
28 |
|
| Line 56... |
Line 56... |
| 56 |
byte_t usb_rx_token; // PID of token packet: SETUP or OUT |
56 |
byte_t usb_rx_token; // PID of token packet: SETUP or OUT |
| 57 |
|
57 |
|
| 58 |
byte_t usb_tx_buf[USB_BUFSIZE]; // output buffer |
58 |
byte_t usb_tx_buf[USB_BUFSIZE]; // output buffer |
| 59 |
byte_t usb_tx_len; // output buffer size, 0 means empty |
59 |
byte_t usb_tx_len; // output buffer size, 0 means empty |
| 60 |
|
60 |
|
| 61 |
byte_t usb_address; // assigned USB address |
61 |
byte_t usb_address; // assigned device address |
| - |
|
62 |
byte_t usb_new_address; // new device address |
| 62 |
|
63 |
|
| 63 |
// ---------------------------------------------------------------------- |
64 |
// ---------------------------------------------------------------------- |
| 64 |
// Local data |
65 |
// Local data |
| 65 |
// ---------------------------------------------------------------------- |
66 |
// ---------------------------------------------------------------------- |
| 66 |
|
67 |
|
| Line 73... |
Line 74... |
| 73 |
}; |
74 |
}; |
| 74 |
|
75 |
|
| 75 |
static byte_t usb_tx_state; // TX_STATE_*, see enum above |
76 |
static byte_t usb_tx_state; // TX_STATE_*, see enum above |
| 76 |
static byte_t usb_tx_total; // total transmit size |
77 |
static byte_t usb_tx_total; // total transmit size |
| 77 |
static byte_t* usb_tx_data; // pointer to data to transmit |
78 |
static byte_t* usb_tx_data; // pointer to data to transmit |
| 78 |
static byte_t new_address; // new device address |
- |
|
| 79 |
|
79 |
|
| 80 |
#if defined USBTINY_VENDOR_NAME |
80 |
#if defined USBTINY_VENDOR_NAME |
| 81 |
struct |
81 |
struct |
| 82 |
{ |
82 |
{ |
| 83 |
byte_t length; |
83 |
byte_t length; |
| 84 |
byte_t type; |
84 |
byte_t type; |
| 85 |
int string[sizeof(USBTINY_VENDOR_NAME)-1]; |
85 |
int string[sizeof(USBTINY_VENDOR_NAME)-1]; |
| 86 |
} string_vendor PROGMEM = |
86 |
} const string_vendor PROGMEM = |
| 87 |
{ |
87 |
{ |
| 88 |
2 * sizeof(USBTINY_VENDOR_NAME), |
88 |
2 * sizeof(USBTINY_VENDOR_NAME), |
| 89 |
DESCRIPTOR_TYPE_STRING, |
89 |
DESCRIPTOR_TYPE_STRING, |
| 90 |
{ CAT2(L, USBTINY_VENDOR_NAME) } |
90 |
{ CAT2(L, USBTINY_VENDOR_NAME) } |
| 91 |
}; |
91 |
}; |
| Line 98... |
Line 98... |
| 98 |
struct |
98 |
struct |
| 99 |
{ |
99 |
{ |
| 100 |
byte_t length; |
100 |
byte_t length; |
| 101 |
byte_t type; |
101 |
byte_t type; |
| 102 |
int string[sizeof(USBTINY_DEVICE_NAME)-1]; |
102 |
int string[sizeof(USBTINY_DEVICE_NAME)-1]; |
| 103 |
} string_device PROGMEM = |
103 |
} const string_device PROGMEM = |
| 104 |
{ |
104 |
{ |
| 105 |
2 * sizeof(USBTINY_DEVICE_NAME), |
105 |
2 * sizeof(USBTINY_DEVICE_NAME), |
| 106 |
DESCRIPTOR_TYPE_STRING, |
106 |
DESCRIPTOR_TYPE_STRING, |
| 107 |
{ CAT2(L, USBTINY_DEVICE_NAME) } |
107 |
{ CAT2(L, USBTINY_DEVICE_NAME) } |
| 108 |
}; |
108 |
}; |
| Line 115... |
Line 115... |
| 115 |
struct |
115 |
struct |
| 116 |
{ |
116 |
{ |
| 117 |
byte_t length; |
117 |
byte_t length; |
| 118 |
byte_t type; |
118 |
byte_t type; |
| 119 |
int string[sizeof(USBTINY_SERIAL)-1]; |
119 |
int string[sizeof(USBTINY_SERIAL)-1]; |
| 120 |
} string_serial PROGMEM = |
120 |
} const string_serial PROGMEM = |
| 121 |
{ |
121 |
{ |
| 122 |
2 * sizeof(USBTINY_SERIAL), |
122 |
2 * sizeof(USBTINY_SERIAL), |
| 123 |
DESCRIPTOR_TYPE_STRING, |
123 |
DESCRIPTOR_TYPE_STRING, |
| 124 |
{ CAT2(L, USBTINY_SERIAL) } |
124 |
{ CAT2(L, USBTINY_SERIAL) } |
| 125 |
}; |
125 |
}; |
| Line 127... |
Line 127... |
| 127 |
#else |
127 |
#else |
| 128 |
# define SERIAL_ID 0 |
128 |
# define SERIAL_ID 0 |
| 129 |
#endif |
129 |
#endif |
| 130 |
|
130 |
|
| 131 |
#if VENDOR_NAME_ID || DEVICE_NAME_ID || SERIAL_ID |
131 |
#if VENDOR_NAME_ID || DEVICE_NAME_ID || SERIAL_ID |
| 132 |
static byte_t string_langid [] PROGMEM = |
132 |
static byte_t const string_langid [] PROGMEM = |
| 133 |
{ |
133 |
{ |
| 134 |
4, // bLength |
134 |
4, // bLength |
| 135 |
DESCRIPTOR_TYPE_STRING, // bDescriptorType (string) |
135 |
DESCRIPTOR_TYPE_STRING, // bDescriptorType (string) |
| 136 |
LE(0x0409), // wLANGID[0] (American English) |
136 |
LE(0x0409), // wLANGID[0] (American English) |
| 137 |
}; |
137 |
}; |
| 138 |
#endif |
138 |
#endif |
| 139 |
|
139 |
|
| 140 |
// Device Descriptor |
140 |
// Device Descriptor |
| 141 |
static byte_t descr_device [18] PROGMEM = |
141 |
static byte_t const descr_device [18] PROGMEM = |
| 142 |
{ |
142 |
{ |
| 143 |
18, // bLength |
143 |
18, // bLength |
| 144 |
DESCRIPTOR_TYPE_DEVICE, // bDescriptorType |
144 |
DESCRIPTOR_TYPE_DEVICE, // bDescriptorType |
| 145 |
LE(0x0110), // bcdUSB |
145 |
LE(0x0101), // bcdUSB |
| 146 |
USBTINY_DEVICE_CLASS, // bDeviceClass |
146 |
USBTINY_DEVICE_CLASS, // bDeviceClass |
| 147 |
USBTINY_DEVICE_SUBCLASS, // bDeviceSubClass |
147 |
USBTINY_DEVICE_SUBCLASS, // bDeviceSubClass |
| 148 |
USBTINY_DEVICE_PROTOCOL, // bDeviceProtocol |
148 |
USBTINY_DEVICE_PROTOCOL, // bDeviceProtocol |
| 149 |
8, // bMaxPacketSize0 |
149 |
8, // bMaxPacketSize0 |
| 150 |
LE(USBTINY_VENDOR_ID), // idVendor |
150 |
LE(USBTINY_VENDOR_ID), // idVendor |
| Line 155... |
Line 155... |
| 155 |
SERIAL_ID, // iSerialNumber |
155 |
SERIAL_ID, // iSerialNumber |
| 156 |
1, // bNumConfigurations |
156 |
1, // bNumConfigurations |
| 157 |
}; |
157 |
}; |
| 158 |
|
158 |
|
| 159 |
// Configuration Descriptor |
159 |
// Configuration Descriptor |
| 160 |
static byte_t descr_config [] PROGMEM = |
160 |
static byte_t const descr_config [] PROGMEM = |
| 161 |
{ |
161 |
{ |
| 162 |
9, // bLength |
162 |
9, // bLength |
| 163 |
DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType |
163 |
DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType |
| 164 |
LE(9+9+7*USBTINY_ENDPOINT), // wTotalLength |
164 |
LE(9+9+7*USBTINY_ENDPOINT), // wTotalLength |
| 165 |
1, // bNumInterfaces |
165 |
1, // bNumInterfaces |
| Line 221... |
Line 221... |
| 221 |
#endif |
221 |
#endif |
| 222 |
data[1] = 0; |
222 |
data[1] = 0; |
| 223 |
} |
223 |
} |
| 224 |
else if ( data[1] == 5 ) // SET_ADDRESS |
224 |
else if ( data[1] == 5 ) // SET_ADDRESS |
| 225 |
{ |
225 |
{ |
| 226 |
new_address = data[2]; |
226 |
usb_new_address = data[2]; |
| - |
|
227 |
#ifdef USBTINY_USB_OK_LED |
| - |
|
228 |
SET(USBTINY_USB_OK_LED);// LED on |
| - |
|
229 |
#endif |
| 227 |
} |
230 |
} |
| 228 |
else if ( data[1] == 6 ) // GET_DESCRIPTOR |
231 |
else if ( data[1] == 6 ) // GET_DESCRIPTOR |
| 229 |
{ |
232 |
{ |
| 230 |
usb_tx_state = TX_STATE_ROM; |
233 |
usb_tx_state = TX_STATE_ROM; |
| 231 |
if ( data[3] == 1 ) |
234 |
if ( data[3] == 1 ) |
| Line 369... |
Line 372... |
| 369 |
// ---------------------------------------------------------------------- |
372 |
// ---------------------------------------------------------------------- |
| 370 |
extern void usb_init ( void ) |
373 |
extern void usb_init ( void ) |
| 371 |
{ |
374 |
{ |
| 372 |
USB_INT_CONFIG |= USB_INT_CONFIG_SET; |
375 |
USB_INT_CONFIG |= USB_INT_CONFIG_SET; |
| 373 |
USB_INT_ENABLE |= (1 << USB_INT_ENABLE_BIT); |
376 |
USB_INT_ENABLE |= (1 << USB_INT_ENABLE_BIT); |
| - |
|
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 |
| 374 |
sei(); |
384 |
sei(); |
| 375 |
} |
385 |
} |
| 376 |
|
386 |
|
| 377 |
// ---------------------------------------------------------------------- |
387 |
// ---------------------------------------------------------------------- |
| 378 |
// Poll USB driver: |
388 |
// Poll USB driver: |
| Line 390... |
Line 400... |
| 390 |
usb_receive( usb_rx_buf + USB_BUFSIZE - usb_rx_off + 1, usb_rx_len - 3 ); |
400 |
usb_receive( usb_rx_buf + USB_BUFSIZE - usb_rx_off + 1, usb_rx_len - 3 ); |
| 391 |
usb_tx_len = 0; // abort pending transmission |
401 |
usb_tx_len = 0; // abort pending transmission |
| 392 |
usb_rx_len = 0; // accept next packet |
402 |
usb_rx_len = 0; // accept next packet |
| 393 |
} |
403 |
} |
| 394 |
// refill an empty transmit buffer, when the transmitter is active |
404 |
// refill an empty transmit buffer, when the transmitter is active |
| 395 |
if ( usb_tx_len == 0 ) |
405 |
if ( usb_tx_len == 0 && usb_tx_state != TX_STATE_IDLE ) |
| 396 |
{ |
406 |
{ |
| 397 |
if ( usb_tx_state != TX_STATE_IDLE ) |
- |
|
| 398 |
{ |
- |
|
| 399 |
usb_transmit(); |
407 |
usb_transmit(); |
| 400 |
} |
- |
|
| 401 |
else |
- |
|
| 402 |
{ // change the USB address at the end of a transfer |
- |
|
| 403 |
usb_address = new_address; |
- |
|
| 404 |
} |
- |
|
| 405 |
} |
408 |
} |
| 406 |
// check for USB bus reset |
409 |
// check for USB bus reset |
| 407 |
for ( i = 10; i > 0 && ! (USB_IN & USB_MASK_DMINUS); i-- ) |
410 |
for ( i = 10; i > 0 && ! (USB_IN & USB_MASK_DMINUS); i-- ) |
| 408 |
{ |
411 |
{ |
| 409 |
} |
412 |
} |
| 410 |
if ( i == 0 ) |
413 |
if ( i == 0 ) |
| 411 |
{ // SE0 for more than 2.5uS is a reset |
414 |
{ // SE0 for more than 2.5uS is a reset |
| 412 |
cli(); |
415 |
usb_new_address = 0; |
| 413 |
usb_tx_len=0; |
416 |
usb_address = 0; |
| 414 |
usb_rx_len=0; |
417 |
#ifdef USBTINY_USB_OK_LED |
| 415 |
new_address = 0; |
418 |
CLR(USBTINY_USB_OK_LED); // LED off |
| 416 |
sei(); |
419 |
#endif |
| 417 |
} |
420 |
} |
| 418 |
} |
421 |
} |