Setup USB Host to talk with hub with two FTDI serial devices

Status
Not open for further replies.

myhrmans

Member
Hey. Have a device with an usb port that, when connected to windows, shows up as two COM devices that are running on the FTDI driver. How would I setup a application to be able to talk to these serial devices though the USB Host on the Teensy 4.1?
Where do I start?

Best Regards
Martin
 
Last edited:
You would use the USBHost_t36 library. In Arduino, click File > Examples > USBHost_t36 > Test > SerialTest to get started.

At the beginning of your program, you create a list of the USB devices your program will be able to support. You would need to create at least 1 USBHub and at least 2 USBSerial instances.

Most USB hubs with more than 4 ports are internally made from multiple 4 port hubs, so plan on using more than 1 USBHub instance if you want to support larger hubs.
 
You would use the USBHost_t36 library. In Arduino, click File > Examples > USBHost_t36 > Test > SerialTest to get started.

At the beginning of your program, you create a list of the USB devices your program will be able to support. You would need to create at least 1 USBHub and at least 2 USBSerial instances.

Most USB hubs with more than 4 ports are internally made from multiple 4 port hubs, so plan on using more than 1 USBHub instance if you want to support larger hubs.

Cool. Yeah tried that but I believe our FTDI chip is not supported currently by the USBSerial class:
Vid=403 pid=6010
I believe it's the same as the current supported one. Where do I start when implementing this protocol?
Thanks.
 
If it does not work without it, you might simply try adding a line to serial.cpp in the usb host library:
Code:
USBSerial::product_vendor_mapping_t USBSerial::pid_vid_mapping[] = {
	// FTDI mappings. 
	{0x0403, 0x6001, USBSerial::FTDI},
[COLOR="#FF0000"]	{0x0403, 0x6010, USBSerial::FTDI},
[/COLOR]
	// PL2303
...
 
Yeah tried that. Also changed the rx and tx endpoints to match the maximum data from 64 to 512 bytes. It does connect now but the sending never flushes. I checked the code and for a composite device it looks like the implementation is very specific.
 
You might be able to uncomment the line: //#define USBHOST_PRINT_DEBUG

in the usbhost_t36.h file to get additional debug output.

May have to debug... Probably someone who has one will need to debug... Which device do you have?
 
Quick update,

I received one of the devices I mentioned, and first quick information from linux system about the device.
Code:
kurt@kurt-XPS-8300:~/Desktop/arduino-1.8.13$ lsusb
Bus 002 Device 003: ID 18e3:9106 Fitipower Integrated Technology Inc 
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 010: ID 413c:2006 Dell Computer Corp. 
Bus 001 Device 009: ID 413c:1004 Dell Computer Corp. 
Bus 001 Device 011: ID 0403:8088 Future Technology Devices International, Ltd 
Bus 001 Device 006: ID 05e3:0610 Genesys Logic, Inc. 4-port hub
Bus 001 Device 003: ID 045e:07a5 Microsoft Corp. Wireless Receiver 1461C
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
kurt@kurt-XPS-8300:~/Desktop/arduino-1.8.13$ lsusb -v -d 0403:8088

Bus 001 Device 011: ID 0403:8088 Future Technology Devices International, Ltd 
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x0403 Future Technology Devices International, Ltd
  idProduct          0x8088 
  bcdDevice            7.00
  iManufacturer           1 
  iProduct                2 
  iSerial                 3 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0037
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              500mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    255 Vendor Specific Subclass
      bInterfaceProtocol    255 Vendor Specific Protocol
      iInterface              2 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    255 Vendor Specific Subclass
      bInterfaceProtocol    255 Vendor Specific Protocol
      iInterface              2 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0

And details from dmesg
Code:
[  921.793325] usb 1-1.4.2: new high-speed USB device number 11 using ehci-pci
[  921.907610] usb 1-1.4.2: New USB device found, idVendor=0403, idProduct=8088, bcdDevice= 7.00
[  921.907614] usb 1-1.4.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  921.907616] usb 1-1.4.2: Product: EPT USB <-> Serial&JTAG Cable
[  921.907618] usb 1-1.4.2: Manufacturer: EPT
[  921.907619] usb 1-1.4.2: SerialNumber: EPT53HOOF
 
We'll probably need to add a "big buffer" version of serial to someday support this, like we do for MIDI.

Yes probably as a minimum as it shows:
Code:
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x [COLOR="#FF0000"]512 [/COLOR]bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x [COLOR="#FF0000"]512 [/COLOR]bytes
        bInterval               0

Current code bails if sizes > 64
 
@myhrmans - I am not sure if you are still interested or waching.

I have stated a branch: https://github.com/KurtE/USBHost_t36/tree/USBSerial_BigBuffer

Where I have the beginnings of a bigbuffer class. I am at least now able to echo stuff out on the first channel of it (J1 pin 7 to 10) and test sketch is getting the data back...

I still have debug turned on... Will now try to see if I have two of these objects if it gets both...

Test sketch so far... Nothing special.
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);

USBDriver *drivers[] = {&hub1, &hub2, &hid1, &hid2, &hid3, &userial, &userialb};
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0]))
const char * driver_names[CNT_DEVICES] = {"Hub1", "Hub2",  "HID1", "HID2", "HID3", "USERIAL1", "USERIALB" };
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 {
          Serial.println("  New Baud 0 - leave disabled");
        }

        while (Serial.read() != -1);
      } else {
        if (userial)userial.write(ch);
        if (userialb)userialb.write(ch);
      }
    }
  }

  while (Serial1.available()) {
    //    Serial.println("Serial1 Available");
    Serial1.write(Serial1.read());
  }

  while (userial.available()) {
    //    Serial.println("USerial Available");

    Serial.write(userial.read());
  }
  while (userialb.available()) {
    //    Serial.println("USerialb Available");

    Serial.write(userialb.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);
        }
      }
    }
  }

}


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


}
 
@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:pID 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:pID 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 ...
 
I may be mainly talking to myself ;)

For the heck of it to test with T4 with MultSerial, I created a version of the example sketch USBToSerial that allows you to build for
USBType of Serial, Dual Serial, Triple Serial
and for each of these setup to go to different HardwareSerial ports.

I have tried it with simple loop back on T4, using TyCommander.

Now to try it with connecting it to T4.1 through USB...
 

Attachments

  • USBtoSerialMulti-201016a.zip
    1.7 KB · Views: 74
...

At a minimum it also helps to support Two T4.x's talking to each other over USB with 512 byte transfers.
...
Nice work KurtE,
... wondering how fast lines per second test runs across the USBHost Serial ... will see if I can try it before you
 
Status
Not open for further replies.
Back
Top