diff --git a/USBHost_t36.h b/USBHost_t36.h index 500b4c6..6e03b83 100644 --- a/USBHost_t36.h +++ b/USBHost_t36.h @@ -909,14 +909,18 @@ class USBSerial: public USBDriver, public Stream { // FIXME: need different USBSerial, with bigger buffers for 480 Mbit & faster speed enum { BUFFER_SIZE = 648 }; // must hold at least 6 max size packets, plus 2 extra bytes + enum { DEFAULT_WRITE_TIMEOUT = 3500}; USBSerial(USBHost &host) : txtimer(this) { init(); } void begin(uint32_t baud, uint32_t format=USBHOST_SERIAL_8N1); void end(void); + uint32_t writeTimeout() {return write_timeout_;} + void writeTimeOut(uint32_t write_timeout) {write_timeout_ = write_timeout;} // Will not impact current ones. virtual int available(void); virtual int peek(void); virtual int read(void); virtual int availableForWrite(); virtual size_t write(uint8_t c); + virtual void flush(void); using Print::write; protected: @@ -944,6 +948,7 @@ private: uint8_t setupdata[16]; // uint32_t baudrate; uint32_t format_; + uint32_t write_timeout_ = DEFAULT_WRITE_TIMEOUT; Pipe_t *rxpipe; Pipe_t *txpipe; uint8_t *rx1; // location for first incoming packet diff --git a/examples/SerialTest/SerialTest.ino b/examples/SerialTest/SerialTest.ino index 2b6ae6a..45189b0 100644 --- a/examples/SerialTest/SerialTest.ino +++ b/examples/SerialTest/SerialTest.ino @@ -289,7 +289,7 @@ int ax12ReadPacket(int length) { while ((ch = userial.read()) == -1) { if ((millis() - ulStart) > 10) { //if (!--ulCounter) { - // Serial.println("Timeout"); + Serial.println("Timeout"); return 0; // Timeout } } diff --git a/serial.cpp b/serial.cpp index 1ef2bc6..dd53639 100644 --- a/serial.cpp +++ b/serial.cpp @@ -29,6 +29,16 @@ #define print USBHost::print_ #define println USBHost::println_ +//#define ENABLE_DEBUG_PINS + +#ifdef ENABLE_DEBUG_PINS +#define debugDigitalToggle(pin) {digitalWriteFast(pin, !digitalReadFast(pin));} +#define debugDigitalWrite(pin, state) {digitalWriteFast(pin, state);} +#else +#define debugDigitalToggle(pin) {;} +#define debugDigitalWrite(pin, state) {;} +#endif + /************************************************************/ // Define mapping VID/PID - to Serial Device type. /************************************************************/ @@ -168,6 +178,8 @@ bool USBSerial::claim(Device_t *dev, int type, const uint8_t *descriptors, uint3 println(", tx:", tx_ep); if (!rx_ep || !tx_ep) return false; // did not get our two end points if (!init_buffers(rx_size, tx_size)) return false; + println(" rx buffer size:", rxsize); + println(" tx buffer size:", txsize); rxpipe = new_Pipe(dev, 2, rx_ep & 15, 1, rx_size); if (!rxpipe) return false; txpipe = new_Pipe(dev, 2, tx_ep, 0, tx_size); @@ -205,47 +217,74 @@ bool USBSerial::claim(Device_t *dev, int type, const uint8_t *descriptors, uint3 break; } } + if (sertype == UNKNOWN) return false; // not one of ours + + // Lets try to locate the end points. Code is common across these devices + println("len = ", len); + uint8_t count_end_points = descriptors[4]; + if (count_end_points < 2) return false; // not enough end points + if (len < 23) return false; + if (descriptors[0] != 9) return false; // length 9 + + // Lets walk through end points and see if we + // can find an RX and TX bulk transfer end point. + //Example vid=67B, pid=2303 + // 0 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 20 1 2 3 4 5 6 7 8 9 + //09 04 00 00 03 FF 00 00 00 07 05 81 03 0A 00 01 07 05 02 02 40 00 00 07 05 83 02 40 00 00 + uint32_t rxep = 0; + uint32_t txep = 0; + uint16_t rx_size = 0; + uint16_t tx_size = 0; + uint32_t descriptor_index = 9; + while (count_end_points-- && ((rxep == 0) || txep == 0)) { + if (descriptors[descriptor_index] != 7) return false; // length 7 + if (descriptors[descriptor_index+1] != 5) return false; // ep desc + if ((descriptors[descriptor_index+3] == 2) + && (descriptors[descriptor_index+4] <= 64) + && (descriptors[descriptor_index+5] == 0)) { + // have a bulk EP size + if (descriptors[descriptor_index+2] & 0x80 ) { + rxep = descriptors[descriptor_index+2]; + rx_size = descriptors[descriptor_index+4]; + } else { + txep = descriptors[descriptor_index+2]; + tx_size = descriptors[descriptor_index+4]; + } + } + descriptor_index += 7; // setup to look at next one... + } + // Try to verify the end points. + if (!check_rxtx_ep(rxep, txep)) return false; + print("USBSerial, rxep=", rxep & 15); + print("(", rx_size); + print("), txep=", txep); + print("(", tx_size); + println(")"); + + if (!init_buffers(rx_size, tx_size)) return false; + println(" rx buffer size:", rxsize); + println(" tx buffer size:", txsize); + + rxpipe = new_Pipe(dev, 2, rxep & 15, 1, rx_size); + if (!rxpipe) return false; + txpipe = new_Pipe(dev, 2, txep, 0, tx_size); + if (!txpipe) { + //free_Pipe(rxpipe); + return false; + } + rxpipe->callback_function = rx_callback; + queue_Data_Transfer(rxpipe, rx1, rx_size, this); + rxstate = 1; + txstate = 0; + txpipe->callback_function = tx_callback; + baudrate = 115200; + + // Now do specific setup per type switch (sertype) { //--------------------------------------------------------------------- // FTDI case FTDI: { - // FTDI FT232 - println("len = ", len); - if (len < 23) return false; - if (descriptors[0] != 9) return false; // length 9 - if (descriptors[9] != 7) return false; // length 7 - if (descriptors[10] != 5) return false; // ep desc - uint32_t rxep = descriptors[11]; - if (descriptors[12] != 2) return false; // bulk type - if (descriptors[13] != 64) return false; // size 64 - if (descriptors[14] != 0) return false; - if (descriptors[16] != 7) return false; // length 7 - if (descriptors[17] != 5) return false; // ep desc - uint32_t txep = descriptors[18]; - if (descriptors[19] != 2) return false; // bulk type - if (descriptors[20] != 64) return false; // size 64 - if (descriptors[21] != 0) return false; - if (!check_rxtx_ep(rxep, txep)) return false; - print("FTDI, rxep=", rxep & 15); - println(", txep=", txep); - if (!init_buffers(64, 64)) return false; - rxpipe = new_Pipe(dev, 2, rxep & 15, 1, 64); - if (!rxpipe) return false; - txpipe = new_Pipe(dev, 2, txep, 0, 64); - if (!txpipe) { - // TODO: free rxpipe - return false; - } - sertype = FTDI; - rxpipe->callback_function = rx_callback; - rxsize = 64; - queue_Data_Transfer(rxpipe, rx1, 64, this); - rxstate = 1; - txsize = 64; - txstate = 0; - txpipe->callback_function = tx_callback; - baudrate = 115200; pending_control = 0x0F; mk_setup(setup, 0x40, 0, 0, 0, 0); // reset port queue_Control_Transfer(dev, &setup, NULL, this); @@ -257,59 +296,6 @@ bool USBSerial::claim(Device_t *dev, int type, const uint8_t *descriptors, uint3 // TODO: Note: there are probably more vendor/product pairs.. Maybe should create table of them case PL2303: { - // Prolific Technology, Inc. PL2303 Serial Port - println("len = ", len); - uint8_t count_end_points = descriptors[4]; - if (count_end_points < 2) return false; // not enough end points - if (len < 23) return false; - if (descriptors[0] != 9) return false; // length 9 - - // Lets walk through end points and see if we - // can find an RX and TX bulk transfer end point. - //vid=67B, pid=2303 - // 0 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 20 1 2 3 4 5 6 7 8 9 - //09 04 00 00 03 FF 00 00 00 07 05 81 03 0A 00 01 07 05 02 02 40 00 00 07 05 83 02 40 00 00 - uint32_t rxep = 0; - uint32_t txep = 0; - uint32_t descriptor_index = 9; - while (count_end_points-- && ((rxep == 0) || txep == 0)) { - if (descriptors[descriptor_index] != 7) return false; // length 7 - if (descriptors[descriptor_index+1] != 5) return false; // ep desc - if ((descriptors[descriptor_index+3] == 2) - && (descriptors[descriptor_index+4] == 64) - && (descriptors[descriptor_index+5] == 0)) { - // have a bulk EP size - if (descriptors[descriptor_index+2] & 0x80 ) { - rxep = descriptors[descriptor_index+2]; - rxsize = descriptors[descriptor_index+4]; - } else { - txep = descriptors[descriptor_index+2]; - txsize = descriptors[descriptor_index+4]; - } - } - descriptor_index += 7; // setup to look at next one... - } - // Try to verify the end points. - if (!check_rxtx_ep(rxep, txep)) return false; - print("PL2303, rxep=", rxep & 15); - println(", txep=", txep); - if (!init_buffers(64, 64)) return false; - rxpipe = new_Pipe(dev, 2, rxep & 15, 1, 64); - if (!rxpipe) return false; - txpipe = new_Pipe(dev, 2, txep, 0, 64); - if (!txpipe) { - // TODO: free rxpipe - return false; - } - - sertype = PL2303; - rxpipe->callback_function = rx_callback; - queue_Data_Transfer(rxpipe, rx1, 64, this); - rxstate = 1; - txstate = 0; - txpipe->callback_function = tx_callback; - baudrate = 115200; - // First attempt keep it simple... println("PL2303: readRegister(0x04)"); // Need to setup the data the line coding data @@ -324,57 +310,6 @@ bool USBSerial::claim(Device_t *dev, int type, const uint8_t *descriptors, uint3 // CH341 case CH341: { - println("len = ", len); - uint8_t count_end_points = descriptors[4]; - if (count_end_points < 2) return false; // not enough end points - if (len < 23) return false; - if (descriptors[0] != 9) return false; // length 9 - - // Lets walk through end points and see if we - // can find an RX and TX bulk transfer end point. - // vid=1A86, pid=7523, bDeviceClass = 255, bDeviceSubClass = 0, bDeviceProtocol = 0 - // 0 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 20 1 2 3 4 5 6 7 8 9 - //09 04 00 00 03 FF 01 02 00 07 05 82 02 20 00 00 07 05 02 02 20 00 00 07 05 81 03 08 00 01 - uint32_t rxep = 0; - uint32_t txep = 0; - uint32_t descriptor_index = 9; - while (count_end_points-- && ((rxep == 0) || txep == 0)) { - if (descriptors[descriptor_index] != 7) return false; // length 7 - if (descriptors[descriptor_index+1] != 5) return false; // ep desc - if ((descriptors[descriptor_index+3] == 2) - && (descriptors[descriptor_index+4] <= 64) - && (descriptors[descriptor_index+5] == 0)) { - // have a bulk EP size - if (descriptors[descriptor_index+2] & 0x80 ) { - rxep = descriptors[descriptor_index+2]; - rxsize = descriptors[descriptor_index+4]; - } else { - txep = descriptors[descriptor_index+2]; - txsize = descriptors[descriptor_index+4]; - } - } - descriptor_index += 7; // setup to look at next one... - } - // Try to verify the end points. - if (!check_rxtx_ep(rxep, txep)) return false; - print("ch341, rxep=", rxep & 15); - println(", txep=", txep); - if (!init_buffers(rxsize, txsize)) return false; - rxpipe = new_Pipe(dev, 2, rxep & 15, 1, rxsize); - if (!rxpipe) return false; - txpipe = new_Pipe(dev, 2, txep, 0, txsize); - if (!txpipe) { - // TODO: free rxpipe - return false; - } - - rxpipe->callback_function = rx_callback; - queue_Data_Transfer(rxpipe, rx1, rxsize, this); - rxstate = 1; - txstate = 0; - txpipe->callback_function = tx_callback; - baudrate = 115200; - println("CH341: 0xC0, 0x5f, 0, 0, 8"); // Need to setup the data the line coding data mk_setup(setup, 0xC0, 0x5f, 0, 0, sizeof(setupdata)); @@ -388,58 +323,6 @@ bool USBSerial::claim(Device_t *dev, int type, const uint8_t *descriptors, uint3 // CP210X case CP210X: { - println("len = ", len); - uint8_t count_end_points = descriptors[4]; - if (count_end_points < 2) return false; // not enough end points - if (len < 23) return false; - if (descriptors[0] != 9) return false; // length 9 - - // Lets walk through end points and see if we - // can find an RX and TX bulk transfer end point. - // BUGBUG: should factor out this code as duplicated... - // vid=10C4, pid=EA60, bDeviceClass = 0, bDeviceSubClass = 0, bDeviceProtocol = 0 - // 0 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 20 1 2 3 4 5 6 7 8 9 - //09 04 00 00 02 FF 00 00 02 07 05 81 02 40 00 00 07 05 01 02 40 00 00 - uint32_t rxep = 0; - uint32_t txep = 0; - uint32_t descriptor_index = 9; - while (count_end_points-- && ((rxep == 0) || txep == 0)) { - if (descriptors[descriptor_index] != 7) return false; // length 7 - if (descriptors[descriptor_index+1] != 5) return false; // ep desc - if ((descriptors[descriptor_index+3] == 2) - && (descriptors[descriptor_index+4] <= 64) - && (descriptors[descriptor_index+5] == 0)) { - // have a bulk EP size - if (descriptors[descriptor_index+2] & 0x80 ) { - rxep = descriptors[descriptor_index+2]; - rxsize = descriptors[descriptor_index+4]; - } else { - txep = descriptors[descriptor_index+2]; - txsize = descriptors[descriptor_index+4]; - } - } - descriptor_index += 7; // setup to look at next one... - } - // Try to verify the end points. - if (!check_rxtx_ep(rxep, txep)) return false; - print("CP210X, rxep=", rxep & 15); - println(", txep=", txep); - if (!init_buffers(rxsize, txsize)) return false; - rxpipe = new_Pipe(dev, 2, rxep & 15, 1, rxsize); - if (!rxpipe) return false; - txpipe = new_Pipe(dev, 2, txep, 0, txsize); - if (!txpipe) { - // TODO: free rxpipe - return false; - } - - rxpipe->callback_function = rx_callback; - queue_Data_Transfer(rxpipe, rx1, rxsize, this); - rxstate = 1; - txstate = 0; - txpipe->callback_function = tx_callback; - baudrate = 115200; - println("CP210X: 0x41, 0x11, 0, 0, 0 - reset port"); // Need to setup the data the line coding data mk_setup(setup, 0x41, 0x11, 0, 0, 0); @@ -1102,6 +985,7 @@ void USBSerial::rx_data(const Transfer_t *transfer) { uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF); + debugDigitalToggle(6); // first update rxstate bitmask, since buffer is no longer queued if (transfer->buffer == rx1) { rxstate &= 0xFE; @@ -1119,6 +1003,11 @@ void USBSerial::rx_data(const Transfer_t *transfer) } } if (len > 0) { + print("rx token: ", transfer->qtd.token, HEX); + print(" transfer length: ", transfer->length, DEC); + print(" len:", len, DEC); + print(" - ", *p, HEX); + println(" ", *(p+1), HEX); print("rx: "); print_hexbytes(p, len); } @@ -1185,6 +1074,7 @@ void USBSerial::tx_data(const Transfer_t *transfer) { uint32_t mask; uint8_t *p = (uint8_t *)transfer->buffer; + debugDigitalWrite(5, HIGH); if (p == tx1) { println("tx1:"); mask = 1; @@ -1194,6 +1084,7 @@ void USBSerial::tx_data(const Transfer_t *transfer) mask = 2; //txstate &= 0xFD; } else { + debugDigitalWrite(5, LOW); return; // should never happen } // check how much more data remains in the transmit buffer @@ -1206,50 +1097,72 @@ void USBSerial::tx_data(const Transfer_t *transfer) count = txsize + head - tail; } uint32_t packetsize = tx2 - tx1; - if (count < packetsize) { + // Only output full packets unless the flush bit was set. + if ((count == 0) || ((count < packetsize) && ((txstate & 0x4) == 0) )) { // not enough data in buffer to fill a full packet - txstate &= ~mask; + txstate &= ~(mask | 4); // turn off that transfer and make sure the flush bit is not set + debugDigitalWrite(5, LOW); return; } // immediately transmit another full packet, if we have enough data + if (count >= packetsize) count = packetsize; + else txstate &= ~(mask | 4); // This packet will complete any outstanding flush + println("TX:moar data!!!!"); if (++tail >= txsize) tail = 0; uint32_t n = txsize - tail; - if (n > packetsize) n = packetsize; + if (n > count) n = count; memcpy(p, txbuf + tail, n); - if (n >= packetsize) { + if (n >= count) { tail += n - 1; if (tail >= txsize) tail = 0; } else { - uint32_t len = packetsize - n; + uint32_t len = count - n; memcpy(p + n, txbuf, len); tail = len - 1; } txtail = tail; - queue_Data_Transfer(txpipe, p, packetsize, this); + queue_Data_Transfer(txpipe, p, count, this); + debugDigitalWrite(5, LOW); } +void USBSerial::flush() +{ + print("USBSerial::flush"); + if (txhead == txtail) { + println(" - Empty"); + return; // empty. + } + debugDigitalWrite(32, HIGH); + NVIC_DISABLE_IRQ(IRQ_USBHS); + txtimer.stop(); // Stop longer timer. + txtimer.start(100); // Start a mimimal timeout +// timer_event(nullptr); // Try calling direct - fails to work + NVIC_ENABLE_IRQ(IRQ_USBHS); + while (txstate & 3) ; // wait for all of the USB packets to be sent. + println(" completed"); + debugDigitalWrite(32, LOW); +} + + void USBSerial::timer_event(USBDriverTimer *whichTimer) { + debugDigitalWrite(7, HIGH); println("txtimer"); uint32_t count; uint32_t head = txhead; uint32_t tail = txtail; - if (pending_control) { - // We are still doing setup postpone for awhile.. - txtimer.start(1200); - println(" Postpone: setup pending_control"); - return; // no outgoing buffers available, try again later - } if (head == tail) { println(" *** Empty ***"); + debugDigitalWrite(7, LOW); return; // nothing to transmit } else if (head > tail) { count = head - tail; } else { count = txsize + head - tail; } + uint8_t *p; if ((txstate & 0x01) == 0) { p = tx1; @@ -1258,10 +1171,20 @@ void USBSerial::timer_event(USBDriverTimer *whichTimer) p = tx2; txstate |= 0x02; } else { - txtimer.start(1200); + txstate |= 4; // Tell the TX code to do flush code. println(" *** No buffers ***"); + debugDigitalWrite(7, LOW); return; // no outgoing buffers available, try again later } + + uint32_t packetsize = tx2 - tx1; + + // Possible for remaining ? packet size and not have both? + if (count > packetsize) { + txstate |= 4; // One of the active transfers will handle the remaining parts + count = packetsize; + } + if (++tail >= txsize) tail = 0; uint32_t n = txsize - tail; if (n > count) n = count; @@ -1279,6 +1202,7 @@ void USBSerial::timer_event(USBDriverTimer *whichTimer) print(") "); print_hexbytes(p, count); queue_Data_Transfer(txpipe, p, count, this); + debugDigitalWrite(7, LOW); } @@ -1427,14 +1351,16 @@ size_t USBSerial::write(uint8_t c) } txtail = tail; //println("queue tx packet, newtail=", tail); + debugDigitalWrite(7, HIGH); queue_Data_Transfer(txpipe, p, packetsize, this); + debugDigitalWrite(7, LOW); NVIC_ENABLE_IRQ(IRQ_USBHS); return 1; } } // otherwise, set a latency timer to later transmit partial packet txtimer.stop(); - txtimer.start(3500); + txtimer.start(write_timeout_); NVIC_ENABLE_IRQ(IRQ_USBHS); return 1; }