@All - To properly support this or similar devices, is a little more complicated.
That is the current branch as I have pushed up for the previous post is a somewhat minimal change. It simply allows for the larger buffer. By moving the "BigBuffer" into the sub classes, where the TX and RX buffers than grab their space from. So the subclass constructor passes in pointer, plus size and also constraints on how big or small the RX or TX can be... My test case appeared to be able to talk to the first Serial object of the device.
BUT - A couple of issues.
a) I am not an FTDI expert and know if there are any differences in the messages and the like needed to properly internally configure the device and how different it is or isn't to our run of the mill FTDI device, especially since for example Window 10 will complain that it has no driver for it... Have not tried yet to see if Linux knows much about it.
b) Something that I have started to address and if anyone wishes to help test... - In most cases, the USB Host Serial code currently claims the device at the device level. So once it sees the VID
ID of the device, it then verifies that it understands the first interface and then it claims it.... So it never looks at the 2nd interface and as such we don't do anything with that 2nd interface.
There was an earlier case where we had composite device with Serial, that is code to handle. I believe an example was Teensy that did lets say Serial and Midi....
So: I now have a version of the code which I push up that rearranges a lot of the code in the USBSerialBase::claim code where I now updated the VID
ID mapping table to have an additional field, to say when to try to claim (0=Device, 1=interface), it still has some hard coded testing device class 2 SubClass 0 at the start and only process on type==0...
But in addition, I tried to fold in the code that if we were on the Interface level, there was another duplication of code to see if we have that composite device and the Interface was of the proper format.... Then bind at the interface into the main part of the code, that when it does not find the device in the table and we are at interface level than check interface for proper CDCACM stuff...
With these current updates, My hacked up test case did appear to bind to both Interfaces. I had 2 BigBuffer Serial objects and they claimed both.
So far I can talk to first. The 2nd one went through the initialization phase, but not sure if any data is going through...
But then not sure what to expect as this device is named a Serial/JTAG device. So not sure if there is some internal configuration of device...
Code:
USB Host Testing - Serial
USB2 PLL running
reset waited 6
USBHS_ASYNCLISTADDR = 0
USBHS_PERIODICLISTBASE = 20008000
periodictable = 20008000
port change: 10001803
connect
begin reset
port change: 18001205
port enabled
end recovery
new_Device: 480 Mbit/sec
new_Pipe
enumeration:
enumeration:
enumeration:
Device Descriptor:
12 01 00 02 00 00 00 40 03 04 88 80 00 07 01 02 03 01
VendorID = 0403, ProductID = 8088, Version = 0700
Class/Subclass/Protocol = 0 / 0 / 0
Number of Configurations = 1
enumeration:
enumeration:
Manufacturer: EPT
enumeration:
Product: EPT USB <-> Serial&JTAG Cable
enumeration:
Serial Number: EPT53HOOF
enumeration:
Config data length = 55
enumeration:
Configuration Descriptor:
09 02 37 00 02 01 00 A0 FA
NumInterfaces = 2
ConfigurationValue = 1
09 04 00 00 02 FF FF FF 02
Interface = 0
Number of endpoints = 2
Class/Subclass/Protocol = 255 / 255 / 255
07 05 81 02 00 02 00
Endpoint = 1 IN
Type = Bulk
Max Size = 512
Polling Interval = 0
07 05 02 02 00 02 00
Endpoint = 2 OUT
Type = Bulk
Max Size = 512
Polling Interval = 0
09 04 01 00 02 FF FF FF 02
Interface = 1
Number of endpoints = 2
Class/Subclass/Protocol = 255 / 255 / 255
07 05 83 02 00 02 00
Endpoint = 3 IN
Type = Bulk
Max Size = 512
Polling Interval = 0
07 05 04 02 00 02 00
Endpoint = 4 OUT
Type = Bulk
Max Size = 512
Polling Interval = 0
enumeration:
USBHub memory usage = 960
USBHub claim_device this=20005960
USBHub memory usage = 960
USBHub claim_device this=20005D20
HIDParser claim this=20004700
HIDParser claim this=20004D20
HIDParser claim this=20005340
USBSerial(64)claim this=200040A0
vid=403, pid=8088, bDeviceClass = 0, bDeviceSubClass = 0, bDeviceProtocol = 0
09 04 00 00 02 FF FF FF 02 07 05 81 02 00 02 00 07 05 02 02 00 02 00 09 04 01 00 02 FF FF FF 02 07 05 83 02 00 02 00 07 05 04 02 00 02 00
Serial device wants to map at interface level
USBSerial(512)claim this=20002CE0
vid=403, pid=8088, bDeviceClass = 0, bDeviceSubClass = 0, bDeviceProtocol = 0
09 04 00 00 02 FF FF FF 02 07 05 81 02 00 02 00 07 05 02 02 00 02 00 09 04 01 00 02 FF FF FF 02 07 05 83 02 00 02 00 07 05 04 02 00 02 00
Serial device wants to map at interface level
USBSerial(512)claim this=20006100
vid=403, pid=8088, bDeviceClass = 0, bDeviceSubClass = 0, bDeviceProtocol = 0
09 04 00 00 02 FF FF FF 02 07 05 81 02 00 02 00 07 05 02 02 00 02 00 09 04 01 00 02 FF FF FF 02 07 05 83 02 00 02 00 07 05 04 02 00 02 00
Serial device wants to map at interface level
Descriptor 4 = INTERFACE
HIDParser claim this=20004700
HIDParser claim this=20004D20
HIDParser claim this=20005340
USBSerial(64)claim this=200040A0
vid=403, pid=8088, bDeviceClass = 0, bDeviceSubClass = 0, bDeviceProtocol = 0
09 04 00 00 02 FF FF FF 02 07 05 81 02 00 02 00 07 05 02 02 00 02 00 09 04 01 00 02 FF FF FF 02 07 05 83 02 00 02 00 07 05 04 02 00 02 00
len = 46
USBSerial(512)claim this=20002CE0
vid=403, pid=8088, bDeviceClass = 0, bDeviceSubClass = 0, bDeviceProtocol = 0
09 04 00 00 02 FF FF FF 02 07 05 81 02 00 02 00 07 05 02 02 00 02 00 09 04 01 00 02 FF FF FF 02 07 05 83 02 00 02 00 07 05 04 02 00 02 00
len = 46
USBSerial, rxep=1(512), txep=2(512)
rx buffer size:1024
tx buffer size:1024
new_Pipe
new_Pipe
Descriptor 5 = ENDPOINT
Descriptor 5 = ENDPOINT
Descriptor 4 = INTERFACE
HIDParser claim this=20004700
HIDParser claim this=20004D20
HIDParser claim this=20005340
USBSerial(64)claim this=200040A0
vid=403, pid=8088, bDeviceClass = 0, bDeviceSubClass = 0, bDeviceProtocol = 0
09 04 01 00 02 FF FF FF 02 07 05 83 02 00 02 00 07 05 04 02 00 02 00
len = 23
USBSerial(512)claim this=20006100
vid=403, pid=8088, bDeviceClass = 0, bDeviceSubClass = 0, bDeviceProtocol = 0
09 04 01 00 02 FF FF FF 02 07 05 83 02 00 02 00 07 05 04 02 00 02 00
len = 23
USBSerial, rxep=3(512), txep=4(512)
rx buffer size:1024
tx buffer size:1024
new_Pipe
new_Pipe
Descriptor 5 = ENDPOINT
Descriptor 5 = ENDPOINT
control callback (serial) F
*** Device USERIALB 403:8088 - connected ***
manufacturer: EPT
product: EPT USB <-> Serial&JTAG Cable
Serial: EPT53HOOF
control callback (serial) F
control callback (serial) E
control callback (serial) E
control callback (serial) C
control callback (serial) C
control callback (serial) 8
*** Device USERIALB2 403:8088 - connected ***
manufacturer: EPT
product: EPT USB <-> Serial&JTAG Cable
Serial: EPT53HOOF
control callback (serial) E
control callback (serial) 0
control callback (serial) C
control callback (serial) 8
control callback (serial) 0
Hacked up Test case:
Code:
// Simple test of USB Host Mouse/Keyboard
//
// This example is in the public domain
#include "USBHost_t36.h"
#define USBBAUD 115200
uint32_t baud = USBBAUD;
uint32_t format = USBHOST_SERIAL_8N1;
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHIDParser hid1(myusb);
USBHIDParser hid2(myusb);
USBHIDParser hid3(myusb);
USBSerial userial(myusb);
USBSerial_BigBuffer userialb(myusb);
USBSerial_BigBuffer userialb2(myusb);
USBDriver *drivers[] = {&hub1, &hub2, &hid1, &hid2, &hid3, &userial, &userialb, &userialb2};
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0]))
const char * driver_names[CNT_DEVICES] = {"Hub1", "Hub2", "HID1", "HID2", "HID3", "USERIAL1", "USERIALB", "USERIALB2" };
bool driver_active[CNT_DEVICES] = {false, false, false, false};
void setup()
{
pinMode(13, OUTPUT);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
for (int i = 0; i < 5; i++) {
digitalWrite(2, HIGH);
delayMicroseconds(50);
digitalWrite(2, LOW);
delayMicroseconds(50);
}
while (!Serial && (millis() < 5000)) ; // wait for Arduino Serial Monitor
Serial.println("\n\nUSB Host Testing - Serial");
myusb.begin();
Serial1.begin(115200); // We will echo stuff Through Serial1...
}
void loop()
{
digitalWrite(13, !digitalRead(13));
myusb.Task();
updateDeviceList();
if (Serial.available()) {
Serial.println("Serial Available");
while (Serial.available()) {
int ch = Serial.read();
if (ch == '#') {
// Lets see if we have a baud rate specified here...
uint32_t new_baud = 0;
for (;;) {
ch = Serial.read();
if ((ch < '0') || (ch > '9'))
break;
new_baud = new_baud * 10 + ch - '0';
}
// See if the user is specifying a format: 8n1, 7e1, 7e2, 8n2
// Note this is Quick and very dirty code...
//
if (ch == ',') {
char command_line[10];
ch = Serial.read();
while (ch == ' ') Serial.read(); // ignore any spaces.
uint8_t cb = 0;
while ((ch > ' ') && (cb < sizeof(command_line))) {
command_line[cb++] = ch;
ch = Serial.read();
}
command_line[cb] = '\0';
if (CompareStrings(command_line, "8N1")) format = USBHOST_SERIAL_8N1;
else if (CompareStrings(command_line, "8N2")) format = USBHOST_SERIAL_8N2;
else if (CompareStrings(command_line, "7E1")) format = USBHOST_SERIAL_7E1;
else if (CompareStrings(command_line, "7O1")) format = USBHOST_SERIAL_7O1;
}
Serial.println("\n*** Set new Baud command ***\n do userial.end()");
digitalWriteFast(2, HIGH);
userial.end(); // Do the end statement;
digitalWriteFast(2, LOW);
if (new_baud) {
baud = new_baud;
Serial.print(" New Baud: ");
Serial.println(baud);
Serial.print(" Format: ");
Serial.println(format, HEX);
digitalWriteFast(3, HIGH);
userial.begin(baud, format);
digitalWriteFast(3, LOW);
Serial.println(" Completed ");
Serial1.end();
Serial1.begin(baud, format);
} else if (ch == '$') {
while (Serial.read() != -1) ;
while (Serial.read() == -1) {
if (userial)userial.write("USerial");
if (userialb)userialb.write("USerialB");
if (userialb2)userialb2.write("UserialB2");
delay(100);
}
} else {
Serial.println(" New Baud 0 - leave disabled");
}
while (Serial.read() != -1);
} else {
if (userial)userial.write(ch);
if (userialb)userialb.write(ch);
if (userialb2)userialb2.write(ch);
}
}
}
while (Serial1.available()) {
// Serial.println("Serial1 Available");
Serial1.write(Serial1.read());
}
while (userial.available()) {
// Serial.println("USerial Available");
Serial.write(userial.read());
}
if (userialb.available()) {
Serial.print("SB:");
while (userialb.available()) {
// Serial.println("USerialb Available");
Serial.write(userialb.read());
}
}
if (userialb2.available()) {
Serial.print("SB2:");
while (userialb2.available()) {
// Serial.println("USerialb Available");
Serial.write(userialb2.read());
}
}
}
void updateDeviceList() {
// Print out information about different devices.
for (uint8_t i = 0; i < CNT_DEVICES; i++) {
if (*drivers[i] != driver_active[i]) {
if (driver_active[i]) {
Serial.printf("*** Device %s - disconnected ***\n", driver_names[i]);
driver_active[i] = false;
} else {
Serial.printf("*** Device %s %x:%x - connected ***\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct());
driver_active[i] = true;
const uint8_t *psz = drivers[i]->manufacturer();
if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz);
psz = drivers[i]->product();
if (psz && *psz) Serial.printf(" product: %s\n", psz);
psz = drivers[i]->serialNumber();
if (psz && *psz) Serial.printf(" Serial: %s\n", psz);
// If this is a new Serial device.
if (drivers[i] == &userial) {
// Lets try first outputting something to our USerial to see if it will go out...
userial.begin(baud);
}
if (drivers[i] == &userialb) {
// Lets try first outputting something to our USerial to see if it will go out...
userialb.begin(baud);
}
if (drivers[i] == &userialb2) {
// Lets try first outputting something to our USerial to see if it will go out...
userialb2.begin(baud);
}
}
}
}
}
bool CompareStrings(const char *sz1, const char *sz2) {
while (*sz2 != 0) {
if (toupper(*sz1) != toupper(*sz2))
return false;
sz1++;
sz2++;
}
return true; // end of string so show as match
}
Not very special but just seeing if the basics are working... But again Not sure about how to test this 2nd port and not sure if can test if this case works.
But wondering about some other usage cases, that I/(WE?) should probably test before I fully cleanup and see about doing Pull Request. Note: This code is based off Master branch... Did not pull in any of the updated BlueTooth...
a) Need to pull out at least a few of the different USB to Serial devices like standard FTDI, PL2303, CH341... Probably don't need to test many as other than a little code ordering, the rest of code should not have changed.
b) Any device that shows up as a CDCACM device - Not sure any more which devices used for this. I am not sure if Simple Teensy did this, or some AVR 8 bit boards with built in USB like Leonardo...
c) Teensy - Could be interesting with different versions now.
1) Like T3.x - Simple Serial
2) T4.x - Probably did not work on released version as:
Code:
id=16C0, pid=483, bDeviceClass = 2, bDeviceSubClass = 0, bDeviceProtocol = 0
09 04 00 00 01 02 02 01 00 05 24 00 10 01 05 24 01 01 01 04 24 02 06 05 24 06 00 01 07 05 82 03 10 00 05 09 04 01 00 02 0A 00 00 00 07 05 03 02 00 02 00 07 05 84 02 00 02 00
Interface is Serial
CS_INTERFACE - subtype: 0 10 1 - Header Functional Descriptor
CS_INTERFACE - subtype: 1 1 1 - Call Management Functional
CS_INTERFACE - subtype: 2 6 - Abstract Control Management
CS_INTERFACE - subtype: 6 0 1 - union Functional
Interface: 1
Endpoint: 3
tx_size = 512
Endpoint: 84
rx_size = 512
exited loop rx:4, tx:3
rx buffer size:1024
tx buffer size:1024
new_Pipe
The released code does not support >64 bytes...
3) Composite Teensy -
4) Multi-Serial - Again maybe different for T4 vs T3...
...
Now to see how badly things are broken.. I did push up the WIP ...