USB Host Mouse Driver

Status
Not open for further replies.
I did a little experimenting with some of the extra keys on some of the keyboards. They generate different top level collections and the like.
So I create a couple hid input classes:
KeyboardPowerController - Power button(s)
KeyboardConsumerController - Some of the controller keys like Calculator,

Just experimenting: I have the Power one set an available where you can get a Buttons field that cooresponds to all of the buttons...

Have the Consumer one work like main keyboard, where you can register a callback (actually two). It is interesting that some of the keyboards generate a push and release and others do not. I have an issue that I am assuming push/release as first keyboard had it...

Also ran into issue with Logitech - that these HID top level reports are on the Interface for the Mouse. The Hid code right now calls hid_input_end for all top level report handlers for that interface regardless if it had anything to do with that top level report. So I was setting available on all three top level reports... Now each of them set a bit in their hid_input_begin method and only set available state in the hid_input_end if the begin was called...

Again sort of experiment/WIP. But pushed up the current stuff in a new branch (based off of master) https://github.com/KurtE/USBHost_t36/tree/Keyboard-Power_and_other_special_keys
 
@Kurt - can you remind me of what features (other than the vendor/product/serial strings) are on your HID-Device-API-Additions branch that I haven't yet merged?
 
@Paul - I think that is mainly it. I have not tried everything yet, but I am... There were some differences in our Test program Mouse.ino, I added a few of them to my own new branch. Things like the keyboard callback printing out the OEM character and modifiers, so we can see what did not translate...

Also there was a difference in checking to see if a device is connected or not to one of our objects. I had something like if (keyboard1.connected())... You have if (keyboard1) ...
I would update mine to yours, but now working on different branch...

I am having better luck with the keyboard - HID extras - Classes I mentioned in #126, I am now able to process a lot of the multimedia keys and power key... Again current stuff up in the branch I mentioned, but I now want to merge those two new classes into one... Maybe keyboardHIDExtras or some such name. At this point I prefer going with two classes in the user code versus trying to merge this new class with the Keyboard class and need something like multiple inheritance.

So far I am processing top level collections (C0001 and 10080), Not sure yet if it would make sense to try some of the vendor specific ones like: (FF000001), which I think some keyboards support...
Also currently Power comes back as you can check for connected, and then call for what buttons were pressed versus, the other keyboard stuff with callback... I want to unify. Not sure in this new call back if the call backs should be passed two variables (Top level usage #, button #) or should do like other places where we pass it as 32 bits with Usage as high word...

I am also going to play with maybe adding the special keys mapping (F1-F12, HOME, END... ) to match the Arduino keyboard library... To see how well that would work.
 
I personally want to work on serial devices next (cdc, ftdi, pl2303, ch340). There's also a contribution for ant wireless that I've been neglecting. That code is structured as a stand-alone project, so that one will involve substantial work on my part to integrate, which is the reason it's still sitting unmerged.

Really, just wanted to make sure I didn't miss anything major before starting work on other stuff.

While I'd really like a single easy-to-understand keyboard class, I agree the multiple inheritance stuff is probably a nightmare.

On the strings, I want to explore packing them into a small, fixed-size buffer added to the device struct. They're already being read during the enumeration. I had planned to do this all along, but honestly just getting EHCI and the bare-bones enumeration working kinda burned me out for a while. This is one of many things I left undone.
 
On the connected function, I really want to try to follow Arduino's API conventions, at least where we can. I believe I mentioned using the bool operator like usb serial does earlier on this thread, or maybe one of the others. Yeah, it's probably buried back in a ton of messages now.
 
@Paul - Let me know what things I can help with.

I agree with the connected vs the bool. Although I think it is more extended than if(Serial) in that the Serial is more like a one shot (I think) once set it stays set (at least used to...)

I agree having some of the Serial devices like FTDI and cdc would be great. Which wireless?

I will continue to play some with the Mouse/Keyboard/Joystick.... Would be nice to support XBox as well...

As for Strings, I assumed that might be an option, that would make it a lot easier to use than having to have query functions that than have to wait for the USB transaction to happen...
Was not sure if you would want to build it into each Device to always use or if you wanted maybe a constructor buffer parameter and/or a addBuffer() call that allowed you specify one. The issue would be timing... As you would have to have the buffer before the connection/claim code runs.

Also not sure if my hack was sufficient to convert the Unicode to Ascii... Or if it needs to be more generic.
 
@Paul (and others) - I updated the new branch https://github.com/KurtE/USBHost_t36/tree/Keyboard-Power_and_other_special_keys

Right now it is one extra HID class... I added the top usage value as first parameter for callback. Appears to be working fine on most keyboards. Need to figure out a little more with MS combined keyboard I have.

I also added maping of the keys like arrow/Fn/Home/end/Insert/Delete - to new defines. My new defines are in this library header file KEYD_UP, which has the same value as the KEY_UP_ARROW key for the Arduino keyboard library. I did not use their names as they have things like: KEY_F1, which is what they use for mapping. Where are cores3/keylayouts.h has this define of the actual keyboard scan values.

Again may have to make small mods to handle MS keyboard correctly. Might be interesting to see how it works with other keyboards. I have tried it so far on the 5 different keyboards I have.

May also extend to other reports if needed, like a Dell multimedia keyboard many of the extra keys work, but not a knob...
 
@paul (and everyone) - Put in a simple fix that appears to make my MS keyboard work better with the special keys.

Also I updated the test program (Mouse - probably should rename) - that on normal keyboard characters and likewise for the Special HID class call back, I look up some of the Key codes and print out the logical name for the Key event:

Example output for one of my Dell wired keyboards:
Code:
USB Host Testing
key 'a'  97 MOD: 0 OEM: 4 LEDS: 0
key 'b'  98 MOD: 0 OEM: 5 LEDS: 0
key 'c'  99 MOD: 0 OEM: 6 LEDS: 0
key 'd'  100 MOD: 0 OEM: 7 LEDS: 0
key 'e'  101 MOD: 0 OEM: 8 LEDS: 0
key 'f'  102 MOD: 0 OEM: 9 LEDS: 0
key 'g'  103 MOD: 0 OEM: A LEDS: 0
key 'A'  65 MOD: 0 OEM: 4 LEDS: 2
key 'B'  66 MOD: 0 OEM: 5 LEDS: 2
key 'C'  67 MOD: 0 OEM: 6 LEDS: 2
key 'D'  68 MOD: 0 OEM: 7 LEDS: 2
key 'F1'  194 MOD: 0 OEM: 3A LEDS: 0
key 'F2'  195 MOD: 0 OEM: 3B LEDS: 0
key 'F3'  196 MOD: 0 OEM: 3C LEDS: 0
key 'F4'  197 MOD: 0 OEM: 3D LEDS: 0
key 'F5'  198 MOD: 0 OEM: 3E LEDS: 0
key 'F6'  199 MOD: 0 OEM: 3F LEDS: 0
key 'F7'  200 MOD: 0 OEM: 40 LEDS: 0
key 'F8'  201 MOD: 0 OEM: 41 LEDS: 0
key 'F9'  202 MOD: 0 OEM: 42 LEDS: 0
key 'F10'  203 MOD: 0 OEM: 43 LEDS: 0
key 'F11'  204 MOD: 0 OEM: 44 LEDS: 0
key 'F12'  205 MOD: 0 OEM: 45 LEDS: 0
key 'HOME'  210 MOD: 0 OEM: 4A LEDS: 0
key 'END'  213 MOD: 0 OEM: 4D LEDS: 0
key 'Ins'  209 MOD: 0 OEM: 49 LEDS: 0
key 'PUP'  211 MOD: 0 OEM: 4B LEDS: 0
key 'Del'  212 MOD: 0 OEM: 4C LEDS: 0
key 'PDN'  214 MOD: 0 OEM: 4E LEDS: 0
key 'Del'  212 MOD: 0 OEM: 4C LEDS: 0
key 'PDN'  214 MOD: 0 OEM: 4E LEDS: 0
key 'UP'  218 MOD: 0 OEM: 52 LEDS: 0
key 'LEFT'  216 MOD: 0 OEM: 50 LEDS: 0
key 'DN'  217 MOD: 0 OEM: 51 LEDS: 0
key 'RIGHT'  215 MOD: 0 OEM: 4F LEDS: 0
HID (C0000) key press:223 - AC Home
HID (C0000) key release:223
HID (C0000) key press:18A - AL Email Reader
HID (C0000) key release:18A
HID (C0000) key press:194 - AL Local Machine Browser
HID (C0000) key release:194
HID (C0000) key press:192 - AL Calculator
HID (C0000) key release:192
HID (C0000) key press:CD - Pause/Continue
HID (C0000) key release:CD
HID (C0000) key press:B7 - Stop
HID (C0000) key release:B7
HID (C0000) key press:E2 - Mute
HID (C0000) key release:E2
HID (C0000) key press:EA - Volume Down
HID (C0000) key release:EA
HID (C0000) key press:E9 - Volume Up
HID (C0000) key release:E9
HID (C0000) key press:B6 - Scan Previous Track
HID (C0000) key release:B6
HID (C0000) key press:B5 - Scan Next Track
HID (C0000) key release:B5
HID (C0000) key press:183 - AL Consumer Control Configuration
HID (C0000) key release:183
HID (C0000) key press:183 - AL Consumer Control Configuration
HID (C0000) key release:183
 
@Paul -

I was thinking of re-implementing the string code for Vendor, Product, Serial using the data retrieved by the enumeration code. But trying to figure out good place to store it.

The most obvious place would maybe add a buffer to the Device_struct structure. My guessing is you would probably want to reserve maybe 64 bytes?

Using my HID branch, that prints out some of the information, I see strings like:
Code:
Keyboard 1 Manufacturer: Lite-On Technology Corp.
Keyboard 1 Product: USB Multimedia Keyboard
Keyboard 1 no Serial number string
...
Keyboard 1 Manufacturer: Teensyduino
Keyboard 1 Product: Serial/Keyboard/Mouse/Joystick
Keyboard 1 serial: 457240
...
Keyboard 1 Manufacturer: Logitech
Keyboard 1 Product: USB Receiver
Keyboard 1 no Serial number string
...
Keyboard 1 Manufacturer: Dell
Keyboard 1 Product: Dell USB Keyboard Hub
Keyboard 1 no Serial number string

*** Keyboard 1 0461:4e67 Connected ***
Keyboard 1 no Manufacturer string
Keyboard 1 Product: HP USB Multimedia Keyboard
Keyboard 1 no Serial number string
*** Joystick 054c:05c4 Connected ***
Joystick Manufacturer: Sony Computer Entertainment
Joystick Product: Wireless Controller
Joystick no Serial number string
Might get away with some less.

But if I understand correctly the Device objects are part of the HUBS and currently each HUB has 7 of these structures. SO for example with our Test app Mouse.ino we have:
Code:
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
...
So if I am reading this right our test app has 21 Device_t objects, so that 64 bytes would add 64*21=1344 bytes... Obviously we could cut out a HUB from the example.

Alternatively we could add the data to the USBDriver class. There are probably fewer of these. Like maybe 10 in our example program... Most apps would have less...

Alternatively could do something completely different, like maybe have one buffer, part of the enumeration code. Could have some optional callback to app code, that says new object created, and either pass pointers to the strings or allow user to query them... And let the app decide what to do with the strings...

Thoughts.
 
@Kurt - I'd like to merge whatever HID stuff you have in progress. Soon I'll need to change the print() and println() names that appear throughout the code, because they conflict with inheritance from Stream needed in the serial driver. Let's get your progress merged before this change creates a ton of merge conflicts.

In other news, today I got the serial driver mostly working with FTDI. Will add the others soon. CDC-ACM is going to need more work in the enumeration code (for IAD), so please let me know if you have any changes enumeration.cpp?
 
@Paul - I created a Pull request with my current stuff... Some of the stuff in this and also things I am still looking at include:

a) Keyboard handles many of the Multimedia keys and power keys - Handles two different reports. Currently I have this like keyboard where there is a Press and Release method... But there is an issue with one of my keyboards that has a Knob for volume. Currently does not work properly. Should probably have callback have another parameter with the value... Not sure if it should replace both Press/Release.

b) Keyboard - I map many of the extra keyts Fn, Arrow, Home/end/Pgup/Pgdn into the same values that Arduino Keyboard library does. Which are values > 0x80.

c) Test app(Mouse.ino) - now displays these new values. I also have it case out these new values as well as multimedia keys and print out the name of the key.

d) Test app - detects when devices are connected and not connected and prints out connect (with PID/VID) and disconnect.

e) Yesterday - Added methods again to get the Vendor string, Product String, Serial # string... WIP - I added 48 byte buffer to every Device_t structure plus 3 bytes for start index for the strings... I don't like this usage of memory. With 3 hubs I think it adds 21 Device_t objects... I am thinking of 2 other ways. Add it to the buffer to the USBHost class. Probably a lot fewer of these so less memory.
Or maybe add it as a new memory buffer, where different classes can contribute some... Or maybe a way to add them to specific Objects...

Example not sure if something like:
Code:
uint8_t keyboard_string_buffer[48]
KeyboardController keyboard1(myusb, keyboard_String_buffer, sizeof(keyboard_string_buffer));
Would work and if that would be a desirable way to do it... Nice thing about this is the user can control which objects that they may be interested in...
An interesting thing about this would be with ones like Mice/Joystick as the actual object is the USBHidParser... But probably would not be too hard. Could have one static buffer that we use in the enumeration, and then when it calls off to the claim function, the claim can then move the data into the user buffer...

Let me know if you want anything changed or removed before merging.
 
Ok, I merged it all. Not quite sure how I feel about the key codes and some other little bits, but at this point I'd rather like to avoid a mess of merge conflicts.

Later today I will rename all the print and println calls. Please pull that into your copy before starting more work, so we don't get too far out of sync.
 
Ok, I merged it all. Not quite sure how I feel about the key codes and some other little bits, but at this point I'd rather like to avoid a mess of merge conflicts.

Later today I will rename all the print and println calls. Please pull that into your copy before starting more work, so we don't get too far out of sync.

Sounds good - again let me know if you want the special key code stuff changed/removed... I just thought it would be nice to be able to easily receive them... So followed the Arduino library for values.

Also as I said not sure about best way to handle the Strings... As I mentioned there are a few different options... So if you have a preference let me know and I will converge over.

Edit: My master branch is now in sync... Will wait until you do the renames before doing anything.

Thanks - Also great work getting FTDI in place!
 
Ok, here's the big patch. Please sync this into your copy.

https://github.com/PaulStoffregen/USBHost_t36/commit/f1bb02028237b25781778925bb74f3dd0405dd60

Rather than changing "print" and "println" everywhere, I put in a couple #define lines at the top of most files, so this change isn't as disruptive as I had feared. The downside is you can't actually do stuff like "Serial.print" or "Serial1.print" within the files with those defines. Well, not unless you undefine them.
 
Thanks Paul,

I am now in sync. Again please let me know any parts that you would like different or not there...
 
@Paul and others -

Wondering about how to properly measure data usage in these programs/objects.

I am/was concerned about how much memory the objects were taking, when I added about 50 bytes to each of the Device_t objects. Looking at the code I see that the HUB objects I believe will include 7 of these objects that they contribute to the memory pool. So since the demo APP has 3 hubs defined in it, I wonder what changing from 3 to 2 hubs would do for the reported memory usage.

Note: In the test app, I have a few tables for many of the objects, such that I can loop asking if the Device is currently connected (bool operator). Plus an array of strings with printable names, plus an array of bools to know the previous state.

When I changed from 3 HUBS to 2 HUBS, the memory change difference reported was 8 bytes: From 18912 to 18904... I tried increasing to 4 and it reported 18920
Code:
 Not used: D:\arduino-1.8.5\hardware\teensy\avr\libraries\USBHost_t36
Using library USBHost_t36 at version 0.1 in folder: C:\Users\kurte\Documents\Arduino\libraries\USBHost_t36 
Sketch uses 55992 bytes (5%) of program storage space. Maximum is 1048576 bytes.
Global variables use 18920 bytes (7%) of dynamic memory, leaving 243224 bytes for local variables. Maximum is 262144 bytes.

So wondering why changes in these objects don't show any real change in Globals?

Edit: I did a quick and dirty:
Serial.println(sizeof(USBHub), DEC);

And it prints out 1216
 
Last edited:
Many of the structures have align attributes, especially the array of pointers for the periodic schedule.

Perhaps small changes are tending to "fill in" the gaps left over because the linker was forced to align stuff?
 
I am not sure... As I mentioned in the Edit, the Sizeof(USBHub) prints out that the HUB structure is 1216 bytes. And when I dropped the buffer size down from 48 to 10.
It printed as 960 so difference of 256... My guess is it did not save the expected 266 bytes. probably due to the alignment

Again maybe experimenting at moving the String buffer out of the Device_t structure as we will have lot more of them than we need. Only need ones for actual devices the user app wants to talk to.
Like the Keyboard object. Like the Serial object...

Again may try three different solutions:
a) Have these objects contain the string buffer..
b) Have these ojbects contribute string buffers, that than when we have an object that is claimed, asks for buffer.
c) Maybe have the user specify buffer/length on constructor for objects that they wish to be able to query on.

Also looking at the code, wondering about, us passing in myusb to objects like:
Code:
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);
As far as I know, these references are not used in any way. That the USBHost object is all static. Maybe for future use?
 
Maybe for future use?

Yes, and also for some semblance of compatibility with the USB Host Shield library. But realistically, I'm not a big fan of many of their API decisions. Use of pointer & template syntax creeps into Arduino sketches.

Turns out version 2 and 3 uses different syntax. Early on I put both constructors into the drivers. This is one of many little API decisions I kinda put off fully making. Now that the library is really starting to mature, it'll soon be time to choose and then keep the API stable.
 
I use the same method, and wirless mouse loghitech and it works fine! it is very important for me to have a wireless mouse becaue i'm taking growth hormone because of health issues which is making it hard for me to even move a little bit.
 
Last edited:
Thanks Paul,

I thought I would have some fun and look at the USBSerial class and see how it works...
Do you have a test app for this? So far I have a simple one. Partially extracted from the Big MOUSE test.
Code:
// Simple test of USB Host Mouse/Keyboard
//
// This example is in the public domain

#include "USBHost_t36.h"

USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHIDParser hid1(myusb);
USBHIDParser hid2(myusb);
USBHIDParser hid3(myusb);
USBSerial userial(myusb);

USBDriver *drivers[] = {&hub1, &hub2, &hid1, &hid2, &hid3, &userial};
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0]))
const char * driver_names[CNT_DEVICES] = {"Hub1","Hub2",  "HID1", "HID2", "HID3","USERIAL1" };
bool driver_active[CNT_DEVICES] = {false, false, false, false};

void setup()
{
  while (!Serial) ; // 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()
{
  myusb.Task();
    // 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(115200);
          userial.println("abcdefghijklmnopqrstuvwxyz");
          userial.println("ABCDEFGHIJKLMNOPQURSTUVWYZ");
          userial.flush();  // force it out now. 
          userial.println("0123456789");
          userial.flush();
          delay(2);
          userial.println("abcdefghijklmnopqrstuvwxyz");
          userial.println("ABCDEFGHIJKLMNOPQURSTUVWYZ");
          delay(2);
          userial.println("!@#$%^&*()");
          userial.flush();
        }
      }
    }
  }

  while (Serial.available()) {
    userial.write(Serial.read());
  }

  while (Serial1.available()) {
    Serial1.write(Serial1.read());
  }

  while (userial.available()) {
    Serial.write(userial.read());
  }


}
Nothing special, but detects when new device is available an does some simple writes to it...
Then it Waits for any input on Serial and forwards that data to Serial1. If Serial1 receives anything it forwards it to the new USBSerial object, and if it receives any data it sends it back to Serial...

Probably some additional testing should in places like maybe before the while loops, it should have: if (!userial) return;
As to not try to write or read anything from the device that is not there...

Thought it might be interesting to experiment to see how hard it would be to support a prolific PL2303 as I had one sitting in my USB cables box, which I used to use to program Basic Atom Pros...
Obviously a different PID/VID test, plus this one has 3 end points (an Interrupt and 2 bulk...)
Code:
kurt@kurt-UP-CHT01:~$ lsusb -v -d  067b:2303

Bus 001 Device 006: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x067b Prolific Technology, Inc.
  idProduct          0x2303 PL2303 Serial Port
  bcdDevice            3.00
  iManufacturer           1
  iProduct                2
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           39
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           3
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x000a  1x 10 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
kurt@kurt-UP-CHT01:~$
Wondering if I can skip the interrupt endpoint and simply use the EP in and EP out ones... One way to find out ;)

Edit: Looks like a few more complications for this... That is if you look at the pl2303.c files (linux source) looks like you probably need to do some stuff with the first endpoint (interrupt)...
 
Last edited:
Again for the fun of it it thought I would also take a quick look at another device that on linux creates a device /device/ttyACMx... Whis is a USB2AX device by XEVEL Labs... It is actually an Atmega32u2 device...

It is probably above my USB pay grade :lol:

Looking at the data passed to the claims as well as the processing...

Code:
USB Host Testing - Serial
sizeof Device = 36
sizeof Pipe = 96
sizeof Transfer = 64
power up USBHS PHY
port change: 10001803
    connect
  begin reset
port change: 10001805
  port enabled
  end recovery
new_Device: 12 Mbit/sec
new_Pipe
enumeration:
enumeration:
enumeration:
enumeration:
enumeration:
enumeration:
enumeration:
enumeration:
Config data length = 62
enumeration:
bNumInterfaces = 2
bConfigurationValue = 1
enumeration:
USBHub memory usage = 960
USBHub claim_device this=1FFF3500
USBHub memory usage = 960
USBHub claim_device this=1FFF38C0
HIDParser claim this=1FFF2660
HIDParser claim this=1FFF2B40
HIDParser claim this=1FFF3020
USBSerial claim this=1FFF2020
vid=16D0, pid=6A7
09 04 00 00 01 02 02 01 00 05 24 00 10 01 04 24 02 06 05 24 06 00 01 07 05 82 03 08 00 FF 09 04 01 00 02 0A 00 00 00 07 05 04 02 10 00 01 07 05 83 02 10 00 01 
Descriptor 4 = INTERFACE
HIDParser claim this=1FFF2660
HIDParser claim this=1FFF2B40
HIDParser claim this=1FFF3020
USBSerial claim this=1FFF2020
vid=16D0, pid=6A7
09 04 00 00 01 02 02 01 00 05 24 00 10 01 04 24 02 06 05 24 06 00 01 07 05 82 03 08 00 FF 09 04 01 00 02 0A 00 00 00 07 05 04 02 10 00 01 07 05 83 02 10 00 01 
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 5 = ENDPOINT
Descriptor 4 = INTERFACE
HIDParser claim this=1FFF2660
HIDParser claim this=1FFF2B40
HIDParser claim this=1FFF3020
USBSerial claim this=1FFF2020
vid=16D0, pid=6A7
09 04 01 00 02 0A 00 00 00 07 05 04 02 10 00 01 07 05 83 02 10 00 01 
Descriptor 5 = ENDPOINT
Descriptor 5 = ENDPOINT
port change: 1C00100A
    disconnect
disconnect_Device:
USBDriver (available_drivers) list: 1FFF3500 -> 1FFF38C0 -> 1FFF2660 -> 1FFF2B40 -> 1FFF3020 -> 1FFF2020
USBDriver (dev->drivers) list: (empty
USBDriver (available_drivers) list: 1FFF3500 -> 1FFF38C0 -> 1FFF2660 -> 1FFF2B40 -> 1FFF3020 -> 1FFF2020
delete_Pipe 1FFF4300
  shut down async schedule
removed Device_t from devlist
  disable

Linux information:
Code:
kurt@kurt-UP-CHT01:~$ lsusb -v -d  16d0:06a7

Bus 001 Device 006: ID 16d0:06a7 MCS
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            2 Communications
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x16d0 MCS
  idProduct          0x06a7
  bcdDevice            0.01
  iManufacturer           1
  iProduct                2
  iSerial               220
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           62
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xc0
      Self Powered
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      1 AT-commands (v.25ter)
      iInterface              0
      CDC Header:
        bcdCDC               1.10
      CDC ACM:
        bmCapabilities       0x06
          sends break
          line coding and serial state
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval             255
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 Unused
      bInterfaceProtocol      0
      iInterface              0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0010  1x 16 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0010  1x 16 bytes
        bInterval               1
kurt@kurt-UP-CHT01:~$ ls /dev/tty*
/dev/tty    /dev/tty18  /dev/tty28  /dev/tty38  /dev/tty48  /dev/tty58    /dev/ttyprintk
/dev/tty0   /dev/tty19  /dev/tty29  /dev/tty39  /dev/tty49  /dev/tty59    /dev/ttyS0
/dev/tty1   /dev/tty2   /dev/tty3   /dev/tty4   /dev/tty5   /dev/tty6     /dev/ttyS1
/dev/tty10  /dev/tty20  /dev/tty30  /dev/tty40  /dev/tty50  /dev/tty60    /dev/ttyS2
/dev/tty11  /dev/tty21  /dev/tty31  /dev/tty41  /dev/tty51  /dev/tty61    /dev/ttyS3
/dev/tty12  /dev/tty22  /dev/tty32  /dev/tty42  /dev/tty52  /dev/tty62
/dev/tty13  /dev/tty23  /dev/tty33  /dev/tty43  /dev/tty53  /dev/tty63
/dev/tty14  /dev/tty24  /dev/tty34  /dev/tty44  /dev/tty54  /dev/tty7
/dev/tty15  /dev/tty25  /dev/tty35  /dev/tty45  /dev/tty55  /dev/tty8
/dev/tty16  /dev/tty26  /dev/tty36  /dev/tty46  /dev/tty56  /dev/tty9
/dev/tty17  /dev/tty27  /dev/tty37  /dev/tty47  /dev/tty57  /dev/ttyACM0
kurt@kurt-UP-CHT01:~$
With the parsing it is complaining about unknown descriptor 36 which is type 0x24... Which I believe from: https://stackoverflow.com/questions/24502113/what-does-it-means-for-bdescriptortype-is-0x24
Is a CDC descriptor... Not sure if this is the way you detect that it is an ACM device? May play a little with the Interface descriptor later in the list which has two end points and see if it responds at all...

But again I am just guessing!
 
This serial device type is on my todo list. :)

If you haven't sync'd recently, please pull in the latest before you start coding. I rearranged the main header file yesterday, mainly to just group all the HID stuff together. Make sure you have that new copy, since new work on the old header will cause merge conflicts down the road...
 
Thanks, I assumed it was on your list, but thought I would take a quick look to see if I could give you a head start... Also good learning experience! I also may have a few devices that I may want to try out...

I am in sync with your stuff as of a few hours ago and I rebased my changes to it... So far no changes to header file, just simple test app, and a few experiments in serial.cpp
 
Sure, if you want to work on that one, great. I need to focus on other stuff for a few days, so I probably won't be able to do much until next week (Oct 30th).

That descriptor looks like CDCACM. It should be the same as when Teensy uses with USB Type is set to Serial. I believe most of the serial host code should work with it, if you add a check in the claim function. When bDeviceClass is 2, you can just claim the whole device if you can parse the CDC descriptors and if you find the data interface with bulk IN & OUT endpoints. Other than claim, the control transfers to configure the baud rate and DTR need to be edited. The good news is it should be pretty simple, just one 7 byte message. I put an 8 byte setup data buffer in the object for this purpose.

When I tested FTDI, I just added a few trivial lines to the mouse example code. Basically just an elapseMillis to occasionally write, and the usual available & read to print anything arriving to the serial monitor. Then I wired the signals to another FTDI cable plugged into my PC and run an ordinary terminal emulator.

The other part of CDCACM is claiming at the multiple interface level when an IAD descriptor is seen. Teensy uses this in the modes where Serial is combined with other stuff. Arduino uses it too for their native USB boards like Leonardo/Micro. Probably best to get CDCACM working first with the simpler whole-device claim. I believe the same code ought to work for both, though perhaps the setup packets might need to have wIndex or bRequestType or some other field adjusted slightly.
 
Status
Not open for further replies.
Back
Top