// Blocking Send of data to an endpoint int USB_Send(u8 ep, const void* d, int len) { if (!_usbConfiguration) return -1; if (_usbSuspendState & (1<<SUSPI)) { //send a remote wakeup UDCON |= (1 << RMWKUP); } int r = len; const u8* data = (const u8*)d; u8 timeout = 250; // 250ms timeout on send? TODO while (len) { u8 n = USB_SendSpace(ep); if (n == 0) { if (!(--timeout)) return -1; delay(1); continue; } if (n > len) n = len; { LockEP lock(ep); // Frame may have been released by the SOF interrupt handler if (!ReadWriteAllowed()) continue; len -= n; if (ep & TRANSFER_ZERO) { while (n--) Send8(0); } else if (ep & TRANSFER_PGM) { while (n--) Send8(pgm_read_byte(data++)); } else { while (n--) Send8(*data++); } if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE))) // Release full buffer ReleaseTX(); } } TXLED1; // light the TX LED TxLEDPulse = TX_RX_LED_PULSE_MS; return r; }
void USBSetupInterrupt() { SetEP(0); if (!ReceivedSetupInt()) return; Setup& setup = _setup; // global saves ~30 bytes Recv((u8*)&setup,8); ClearSetupInt(); if (setup.bmRequestType & DEVICETOHOST) WaitIN(); else ClearIN(); bool ok = true; u8 r = setup.bRequest; if (SET_ADDRESS == r) { WaitIN(); UDADDR = setup.wValueL | (1<<ADDEN); } else if (SET_CONFIGURATION == r) { _usbConfiguration = setup.wValueL; InitEndpoints(); } else if (GET_CONFIGURATION == r) { Send8(_usbConfiguration); } else if (GET_STATUS == r) { Send8(0); // All good as far as I know } else if (GET_DESCRIPTOR == r) { ok = SendDescriptor(); } else { ok = USBHook(); } if (ok) ClearIN(); else Stall(); }
// Blocking Send of data to an endpoint int USB_Send(u8 ep, const void* d, int len) { if (!_usbConfiguration) return -1; int r = len; const u8* data = (const u8*)d; u8 zero = ep & TRANSFER_ZERO; u8 timeout = 250; // 250ms timeout on send? TODO while (len) { u8 n = USB_SendSpace(ep); if (n == 0) { if (!(--timeout)) return -1; delay(1); continue; } { LockEP lock(ep); u8 n = USB_SendSpace(ep); if (n > len) n = len; len -= n; if (ep & TRANSFER_ZERO) { while (n--) Send8(0); } else if (ep & TRANSFER_PGM) { while (n--) Send8(pgm_read_byte(data++)); } else { while (n--) Send8(*data++); } if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE))) // Release full buffer ReleaseTX(); } } TXLED1; // light the TX LED TxLEDPulse = TX_RX_LED_PULSE_MS; return r; }
bool SendDescriptor() { Setup& setup = _setup; u8 desc_length = 0; const u8* desc_addr = 0; u8 t = setup.wValueH; if (0x22 == t) { desc_addr = _rawHID; desc_length = sizeof(desc_length); } else if (USB_DEVICE_DESCRIPTOR_TYPE == t) { if (setup.wLength == 8) _cdcComposite = 1; desc_addr = _cdcComposite ? (const u8*)&USB_DeviceDescriptorA : (const u8*)&USB_DeviceDescriptor; } else if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t) { desc_addr = (const u8*)&USB_ConfigDescriptor; desc_length = sizeof(USB_ConfigDescriptor); } else if (USB_STRING_DESCRIPTOR_TYPE == t) { if (setup.wValueL == 0) desc_addr = (const u8*)&STRING_LANGUAGE; else if (setup.wValueL == IPRODUCT) desc_addr = (const u8*)&STRING_IPRODUCT; else if (setup.wValueL == ISERIAL) desc_addr = (const u8*)&STRING_SERIAL; else if (setup.wValueL == IMANUFACTURER) desc_addr = (const u8*)&STRING_IMANUFACTURER; else return false; } else return false; if (desc_length == 0) desc_length = pgm_read_byte(desc_addr); if ((u8)setup.wLength < desc_length) // bit of a cheat limiting to 255 bytes TODO (saved 8 bytes) desc_length = (u8)setup.wLength; // Send descriptor // EP0 is 64 bytes long // RWAL and FIFOCON don't work on EP0 u8 n = 0; do { if (!WaitForINOrOUT()) return false; Send8(pgm_read_byte(&desc_addr[n++])); u8 clr = n & 0x3F; if (!clr) ClearIN(); // Fifo is full, release this packet } while (n < desc_length); return true; }
static bool SendControl(uint8_t d) { if (_cmark < _cend) { if (!WaitForINOrOUT()) return (false); Send8(d); if (!((_cmark + 1) & 0x3F)) ClearIN(); } _cmark++; return (true); };
static bool SendControl(u8 d) { if (_cmark < _cend) { if (!WaitForINOrOUT()) return false; Send8(d); if (!((_cmark + 1) & 0x3F)) ClearIN(); // Fifo is full, release this packet } _cmark++; return true; };
int USB_Send(uint8_t ep, const void* d, int len) { if (!_usbConfiguration) return (-1); int res = len; const uint8_t* data = (const uint8_t*)d; uint8_t timeout = 250; while (len) { uint8_t n = USB_SendSpace(ep); if (n == 0) { if (!(--timeout)) return (-1); delay(1); continue; } if (n > len) n = len; { LockEP lock(ep); if (!ReadWriteAllowed()) continue; len -= n; if (ep & TRANSFER_ZERO) { while (n--) Send8(0); } else if (ep & TRANSFER_PGM) { while (n--) Send8(pgm_read_byte(data++)); } else { while (n--) Send8(*data++); } if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE))) ReleaseTX(); } } TX_LED_ON; TxLEDPulse = TX_RX_LED_PULSE_MS; return (res); }
static bool SendControl(u8 d) { // if (_cmark < _cend) // { // if (!WaitForINOrOUT()) // return false; // Send8(d); // if (!((_cmark + 1) & 0x3F)) // ClearIN(); // Fifo is full, release this packet // } // _cmark++; Send8(d); // if( // POOBAH return true; };
// Transmit a packet to endpoint void Transfer(u8 ep, const u8* data, int len) { u8 zero = ep & TRANSFER_ZERO; SetEP(ep & 7); while (len--) { while (!ReadWriteAllowed()) ; // TODO Check for STALL etc u8 d = (ep & TRANSFER_PGM) ? pgm_read_byte(data) : data[0]; data++; if (zero) d = 0; Send8(d); if (!ReadWriteAllowed()) ReleaseTX(); } if (ep & TRANSFER_RELEASE) ReleaseTX(); }
// Blocking Send of data to an endpoint int USB_Send(u8 ep, const void* d, int len) { if (!_usbConfiguration) return -1; if (_usbSuspendState & (1<<SUSPI)) { //send a remote wakeup UDCON |= (1 << RMWKUP); } int r = len; const u8* data = (const u8*)d; u8 timeout = 250; // 250ms timeout on send? TODO bool sendZlp = false; while (len || sendZlp) { u8 n = USB_SendSpace(ep); if (n == 0) { if (!(--timeout)) return -1; delay(1); continue; } if (n > len) { n = len; } { LockEP lock(ep); // Frame may have been released by the SOF interrupt handler if (!ReadWriteAllowed()) continue; len -= n; if (ep & TRANSFER_ZERO) { while (n--) Send8(0); } else if (ep & TRANSFER_PGM) { while (n--) Send8(pgm_read_byte(data++)); } else { while (n--) Send8(*data++); } if (sendZlp) { ReleaseTX(); sendZlp = false; } else if (!ReadWriteAllowed()) { // ...release if buffer is full... ReleaseTX(); if (len == 0) sendZlp = true; } else if ((len == 0) && (ep & TRANSFER_RELEASE)) { // ...or if forced with TRANSFER_RELEASE // XXX: TRANSFER_RELEASE is never used can be removed? ReleaseTX(); } } } TXLED1; // light the TX LED TxLEDPulse = TX_RX_LED_PULSE_MS; return r; }