28 #define min(a,b) ((a)<(b)?(a):(b)) 29 #define max(a,b) ((a)>(b)?(a):(b)) 31 #if defined(ARDUINO_LEONARDO) || defined(ARDUINO_PRO_MICRO) 32 #define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0) 33 #define TX_LED_OFF PORTD |= (1<<5) 34 #define TX_LED_ON PORTD &= ~(1<<5) 35 #define RX_LED_OFF PORTB |= (1<<0) 36 #define RX_LED_ON PORTB &= ~(1<<0) 38 #define TX_RX_LED_INIT {} 45 #define EP_TYPE_CONTROL 0x00 46 #define EP_TYPE_BULK_IN 0x81 47 #define EP_TYPE_BULK_OUT 0x80 48 #define EP_TYPE_INTERRUPT_IN 0xC1 49 #define EP_TYPE_INTERRUPT_OUT 0xC0 50 #define EP_TYPE_ISOCHRONOUS_IN 0x41 51 #define EP_TYPE_ISOCHRONOUS_OUT 0x40 57 #define TX_RX_LED_PULSE_MS 100 58 volatile uint8_t TxLEDPulse;
59 volatile uint8_t RxLEDPulse;
61 extern const uint16_t STRING_LANGUAGE[] PROGMEM;
62 extern const uint16_t STRING_IPRODUCT[] PROGMEM;
63 extern const uint16_t STRING_IMANUFACTURER[] PROGMEM;
67 const uint16_t STRING_LANGUAGE[2] = {
72 const uint16_t STRING_IPRODUCT[17] = {
75 'A',
'r',
'd',
'u',
'i',
'n',
'o',
' ',
'L',
'e',
'o',
'n',
'a',
'r',
'd',
'o' 76 #elif USB_PID == 0x8037 77 'A',
'r',
'd',
'u',
'i',
'n',
'o',
' ',
'M',
'i',
'c',
'r',
'o',
' ',
' ',
' ' 78 #elif USB_PID == 0x803C 79 'A',
'r',
'd',
'u',
'i',
'n',
'o',
' ',
'E',
's',
'p',
'l',
'o',
'r',
'a',
' ' 80 #elif USB_PID == 0x9208 81 'L',
'i',
'l',
'y',
'P',
'a',
'd',
'U',
'S',
'B',
' ',
' ',
' ',
' ',
' ',
' ' 82 #elif USB_PID == 0x0483 83 'U',
'S',
'B',
' ',
'S',
'e',
'r',
'i',
'a',
'l',
' ',
' ',
' ',
' ',
' ',
' ' 85 'U',
'S',
'B',
' ',
'I',
'O',
' ',
'B',
'o',
'a',
'r',
'd',
' ',
' ',
' ',
' ' 89 const uint16_t STRING_IMANUFACTURER[12] = {
92 'A',
'r',
'd',
'u',
'i',
'n',
'o',
' ',
'L',
'L',
'C' 93 #elif USB_VID == 0x1b4f 94 'S',
'p',
'a',
'r',
'k',
'F',
'u',
'n',
' ',
' ',
' ' 95 #elif USB_VID == 0x16C0 96 'T',
'e',
'e',
'n',
's',
'y',
'd',
'u',
'i',
'n',
'o' 98 'U',
'n',
'k',
'n',
'o',
'w',
'n',
' ',
' ',
' ',
' ' 103 #define DEVICE_CLASS 0x02 105 #define DEVICE_CLASS 0x00 110 D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,
IMANUFACTURER,
IPRODUCT,0,1);
113 D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID,USB_PID,0x100,
IMANUFACTURER,
IPRODUCT,0,1);
115 volatile uint8_t _usbConfiguration = 0;
120 while (!(UEINTX & (1<<TXINI)))
127 UEINTX = ~(1<<TXINI);
133 while (!(UEINTX & (1<<RXOUTI)))
137 static inline uint8_t
140 while (!(UEINTX & ((1<<TXINI)|(1<<RXOUTI))))
142 return (UEINTX & (1<<RXOUTI)) == 0;
148 UEINTX = ~(1<<RXOUTI);
152 Recv(
volatile uint8_t* data, uint8_t count)
154 while (count--) *data++ = UEDATX;
156 RxLEDPulse = TX_RX_LED_PULSE_MS;
159 static inline uint8_t
163 RxLEDPulse = TX_RX_LED_PULSE_MS;
179 static inline uint8_t
185 static inline uint8_t
188 return (UEINTX & (1<<RXSTPI));
194 UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
200 UECONX = (1<<STALLRQ) | (1<<EPEN);
203 static inline uint8_t
206 return (UEINTX & (1<<RWAL));
209 static inline uint8_t
212 return (UEINTX & (1<<STALLEDI));
215 static inline uint8_t
218 return (UEINTX & (1<<FIFOCON));
235 static inline uint8_t
241 uint8_t USBGetConfiguration(
void)
243 return (_usbConfiguration);
246 #define USB_RECV_TIMEOUT 251 LockEP(uint8_t ep) : _sreg(SREG)
263 USB_Available(uint8_t ep)
266 return (FifoByteCount());
270 USB_Recv(uint8_t ep,
void* d,
int len)
272 if (!_usbConfiguration || len < 0)
return (-1);
275 uint8_t n = FifoByteCount();
278 uint8_t* dst = (uint8_t*)d;
281 if (len && !FifoByteCount())
290 if (USB_Recv(ep, &c, 1) == 1)
296 USB_SendSpace(uint8_t ep)
299 if (!ReadWriteAllowed())
return (0);
300 return (64 - 1 - FifoByteCount());
304 USB_Send(uint8_t ep,
const void* d,
int len)
306 if (!_usbConfiguration)
return (-1);
309 const uint8_t* data = (
const uint8_t*)d;
310 uint8_t timeout = 250;
312 uint8_t n = USB_SendSpace(ep);
314 if (!(--timeout))
return (-1);
318 if (n > len) n = len;
321 if (!ReadWriteAllowed())
continue;
323 if (ep & TRANSFER_ZERO) {
324 while (n--) Send8(0);
326 else if (ep & TRANSFER_PGM) {
327 while (n--) Send8(pgm_read_byte(data++));
330 while (n--) Send8(*data++);
332 if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE)))
337 TxLEDPulse = TX_RX_LED_PULSE_MS;
341 extern const uint8_t _initEndpoints[] PROGMEM;
342 const uint8_t _initEndpoints[] =
347 EP_TYPE_INTERRUPT_IN,
357 #define EP_SINGLE_64 0x32 358 #define EP_DOUBLE_64 0x36 361 InitEP(uint8_t index, uint8_t type, uint8_t size)
372 for (uint8_t i = 1; i <
sizeof(_initEndpoints); i++) {
375 UECFG0X = pgm_read_byte(_initEndpoints+i);
376 UECFG1X = EP_DOUBLE_64;
383 ClassInterfaceRequest(Setup& setup)
385 uint8_t i = setup.wIndex;
410 SendControl(uint8_t d)
412 if (_cmark < _cend) {
413 if (!WaitForINOrOUT())
return (
false);
415 if (!((_cmark + 1) & 0x3F)) ClearIN();
422 USB_SendControl(uint8_t flags,
const void* d,
int len)
425 const uint8_t* data = (
const uint8_t*)d;
426 bool pgm = flags & TRANSFER_PGM;
428 uint8_t c = pgm ? pgm_read_byte(data++) : *data++;
429 if (!SendControl(c))
return (-1);
435 USB_RecvControl(
void* d,
int len)
441 auto recvLength = length;
448 Recv((uint8_t*)d + len - length, recvLength);
450 length -= recvLength;
455 Recv((uint8_t*)d,len);
465 uint8_t interfaces = 0;
468 total = CDC_GetInterface(&interfaces);
472 total += HID_GetInterface(&interfaces);
479 SendConfiguration(
int maxlen)
482 uint8_t interfaces = SendInterfaces();
491 static uint8_t _cdcComposite = 0;
494 SendDescriptor(Setup& setup)
496 uint8_t t = setup.wValueH;
498 return (SendConfiguration(setup.wLength));
500 InitControl(setup.wLength);
503 return (HID_GetDescriptor(t));
506 uint8_t desc_length = 0;
507 const uint8_t* desc_addr = 0;
509 if (setup.wLength == 8)
511 desc_addr = _cdcComposite ? (
const uint8_t*)&USB_DeviceDescriptorA : (
const uint8_t*)&USB_DeviceDescriptor;
514 if (setup.wValueL == 0)
515 desc_addr = (
const uint8_t*)&STRING_LANGUAGE;
517 desc_addr = (
const uint8_t*)&STRING_IPRODUCT;
519 desc_addr = (
const uint8_t*)&STRING_IMANUFACTURER;
524 if (desc_addr == 0)
return (
false);
525 if (desc_length == 0)
526 desc_length = pgm_read_byte(desc_addr);
528 USB_SendControl(TRANSFER_PGM,desc_addr,desc_length);
536 if (!ReceivedSetupInt())
return;
539 Recv((uint8_t*)&setup,8);
542 uint8_t requestType = setup.bmRequestType;
550 uint8_t r = setup.bRequest;
558 UDADDR = setup.wValueL | (1<<ADDEN);
561 ok = SendDescriptor(setup);
572 _usbConfiguration = setup.wValueL;
584 InitControl(setup.wLength);
585 ok = ClassInterfaceRequest(setup);
603 while (_usbConfiguration)
608 USB_Flush(uint8_t ep)
617 uint8_t udint = UDINT;
621 if (udint & (1<<EORSTI)) {
622 InitEP(0,EP_TYPE_CONTROL,EP_SINGLE_64);
623 _usbConfiguration = 0;
624 UEIENX = 1 << RXSTPE;
629 if (udint & (1<<SOFI)) {
632 if (USB_Available(
CDC_RX))
637 if (TxLEDPulse && !(--TxLEDPulse))
639 if (RxLEDPulse && !(--RxLEDPulse))
649 return (f != UDFNUML);
652 USBDevice_ USBDevice;
654 USBDevice_::USBDevice_()
658 #if defined(__AVR_AT90USB162__) 660 #define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0))) 661 #define USB_CONFIG() (USBCON = (1<<USBE)) 662 #define USB_UNCONFIG() (USBCON ^= (1<<USBE)) 663 #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) 664 #elif defined(__AVR_ATmega32U4__) 665 #define HW_CONFIG() (UHWCON = 0x01) 666 #define PLL_CONFIG() (PLLCSR = ((I_CPU == 16) ? 0x10 : 0x0) | 0x2) 667 #define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) 668 #define USB_UNCONFIG() (USBCON ^= (1<<USBE)) 669 #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) 670 #elif defined(__AVR_AT90USB646__) 671 #define HW_CONFIG() (UHWCON = 0x81) 672 #define PLL_CONFIG() (PLLCSR = 0x1A) 673 #define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) 674 #define USB_UNCONFIG() (USBCON ^= (1<<USBE)) 675 #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) 676 #elif defined(__AVR_AT90USB1286__) 677 #define HW_CONFIG() (UHWCON = 0x81) 678 #define PLL_CONFIG() (PLLCSR = 0x16) 679 #define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) 680 #define USB_UNCONFIG() (USBCON ^= (1<<USBE)) 681 #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) 688 _usbConfiguration = 0;
694 loop_until_bit_is_set(PLLCSR, PLOCK);
703 UDIEN = _BV(EORSTE) | _BV(SOFE) | _BV(SUSPE);
707 for (uint8_t timeout=10;timeout;timeout--) {
708 if (_usbConfiguration)
726 USBDevice_::configured()
728 return (_usbConfiguration);
#define HID_REPORT_DESCRIPTOR_TYPE
#define CDC_ACM_INTERFACE
#define USB_DEVICE_DESCRIPTOR_TYPE
#define D_DEVICE(_class, _subClass, _proto, _packetSize0, _vid, _pid, _version, _im, _ip, _is, _configs)
void(* delay)(uint32_t ms)
#define USB_CONFIGURATION_DESCRIPTOR_TYPE
#define REQUEST_RECIPIENT
#define USB_STRING_DESCRIPTOR_TYPE
#define D_CONFIG(_totalLength, _interfaces)
#define GET_CONFIGURATION
#define SET_CONFIGURATION
#define REQUEST_DEVICETOHOST