USB 2 way data, without virtual serial COM ports?

Post here first, or if you can't find a relevant section!
Post Reply
User avatar
Mangy_Dog
Posts: 97
Joined: Sat May 02, 2020 11:45 pm
Answers: 1

USB 2 way data, without virtual serial COM ports?

Post by Mangy_Dog »

Using the USBComposite library with rogers core. Whats the best way to get 2 way data over USB?
Is it rawHID?

Im making a windows app to connect to some of my hardware, but I want it to connect via the USBs name or IDs... Rather than setting up and manually selecting a COM port.

Whats my options?
Just a dogs body developer, mostly making props and stuff...
ag123
Posts: 1657
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: USB 2 way data, without virtual serial COM ports?

Post by ag123 »

Code: Select all

loop() {
  int16_t in_char;
  if(Serial.available()) 
    in_char = Serial.read();
  Serial.println("hello world");
}
?

anything other than Serial, could mean having to deal with a different protocol e.g. HID
User avatar
Mangy_Dog
Posts: 97
Joined: Sat May 02, 2020 11:45 pm
Answers: 1

Re: USB 2 way data, without virtual serial COM ports?

Post by Mangy_Dog »

Well ideally i want to do hid, I dont want to have to use com ports on my software. Or have the com port exposed to the PC. IE like a closed USB device.
So Some kind of HID....
Just a dogs body developer, mostly making props and stuff...
ag123
Posts: 1657
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: USB 2 way data, without virtual serial COM ports?

Post by ag123 »

HID is less than easy. I think USB composite can do HID.
However, note that it mimics a keyboard, so your desktop would likely get 'confused' and simply treat that as a keyboard.
In addition, to 'send data' to the device, you'd need a self defined HID report descriptor
https://eleccelerator.com/usbdescreqparser/
https://eleccelerator.com/tutorial-abou ... scriptors/
https://www.usb.org/hid

that descriptor is an initial effort to define a fixed structure, normally once done, simply compile it and 'hard code' it in the source.
then in your HID 'driver' on the stm32, you would need to handle the messages as is declared in your descriptor.

for anything more than the simplest, even including HID, e.g. mimic a keyboard, it means creating a custom app on the host.

USB Serial is kind of 'driverless', and I think a desktop app can get a list of com: / VCP ports from some api calls on the host.
my usual way is get the list of serial ports and start probing, e.g. send a common such as "ID" or something and on the stm32 code it so that it respond with a unique ID. that would help your app determine that it is talking to a valid device.
User avatar
Mangy_Dog
Posts: 97
Joined: Sat May 02, 2020 11:45 pm
Answers: 1

Re: USB 2 way data, without virtual serial COM ports?

Post by Mangy_Dog »

ag123 wrote: Thu Apr 07, 2022 11:10 am HID is less than easy. I think USB composite can do HID.
Isnt USBComposite your library?

Im trying to use your rawhid implementation. But I'm having trouble getting the correct endpoints to come up on the USB Device viewer.

Code: Select all

#define RAWHID_USAGE_PAGE	0xFFC0 // recommended: 0xFF00 to 0xFFFF
#define RAWHID_USAGE		0x0C00 // recommended: 0x0100 to 0xFFFF
    
#define LSB(x) ((x) & 0xFF)    
#define MSB(x) (((x) & 0xFF00) >> 8)    
// TODO: make this work for txSize > 255
#define HID_RAW_REPORT_DESCRIPTOR(txSize, rxSize) \
	0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), \
	0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), \
	0xA1, 0x01,				                /*  Collection 0x01 */ \
    0x85, 1,				        	    /*	REPORT_ID (1) */ \
	0x75, 0x08,				                /*  report size = 8 bits */ \
	0x15, 0x00,				                /*  logical minimum = 0 */ \
	0x26, 0xFF, 0x00,		                /*  logical maximum = 255 */ \
\
	0x96, LSB(txSize), MSB(txSize),			/*  report count TX */ \
	0x09, 0x01,				                /*  usage */ \
	0x81, 0x02,				                /*  Input (array) */ \
\
	0x75, 0x08,				                /*  report size = 8 bits */ \
	0x15, 0x00,				                /*  logical minimum = 0 */ \
	0x26, 0xFF, 0x00,		                /*  logical maximum = 255 */ \
\
	0x96, LSB(rxSize), MSB(rxSize),		    /*  report count RX */ \
	0x09, 0x02,				                /*  usage */ \
	0x91, 0x02,				                /*  OUTPUT (0x91) */ \
	0xC0					                /*  end collection */\
    
Using that descriptor from the rawhid.
Even though 0x91 is listed, I dont get a out endpoint in the list.

The device endpoint list is...

Code: Select all

[Port2]  :  USB Input Device


Is Port User Connectable:         yes
Is Port Debug Capable:            no
Companion Port Number:            2
Companion Hub Symbolic Link Name: USB#VID_05E3&PID_0626#6&1abbe2eb&0&8#{f18a0e88-c30c-11d0-8815-00a0c906bed8}
Protocols Supported:
 USB 1.1:                         yes
 USB 2.0:                         yes
 USB 3.0:                         no

Device Power State:               PowerDeviceD0

       ---===>Device Information<===---
English product name: "HARDWARE MONITOR"

ConnectionStatus:                  
Current Config Value:              0x01  -> Device Bus Speed: Full (is not SuperSpeed or higher capable)
Device Address:                    0x0D
Open Pipes:                           1

          ===>Device Descriptor<===
bLength:                           0x12
bDescriptorType:                   0x01
bcdUSB:                          0x0200
bDeviceClass:                      0x00  -> This is an Interface Class Defined Device
bDeviceSubClass:                   0x00
bDeviceProtocol:                   0x01
*!*ERROR:  bDeviceProtocol of 1 is invalid
bMaxPacketSize0:                   0x40 = (64) Bytes
idVendor:                        0xD055 = Vendor ID not listed with USB.org
idProduct:                       0xD055
bcdDevice:                       0x0200
iManufacturer:                     0x01
     English (United States)  "MANGY INDUSTRIES"
iProduct:                          0x02
     English (United States)  "HARDWARE MONITOR"
iSerialNumber:                     0x03
     English (United States)  "DOGPOWER"
bNumConfigurations:                0x01

          ---===>Open Pipes<===---

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x81  -> Direction: IN - EndpointID: 1
bmAttributes:                      0x03  -> Interrupt Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x0A

       ---===>Full Configuration Descriptor<===---

          ===>Configuration Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x02
wTotalLength:                    0x0022  -> Validated
bNumInterfaces:                    0x01
bConfigurationValue:               0x01
iConfiguration:                    0x00
bmAttributes:                      0xC0  -> Self Powered
MaxPower:                          0x32 = 100 mA

          ===>Interface Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x04
bInterfaceNumber:                  0x00
bAlternateSetting:                 0x00
bNumEndpoints:                     0x01
bInterfaceClass:                   0x03  -> HID Interface Class
bInterfaceSubClass:                0x01
bInterfaceProtocol:                0x00
iInterface:                        0x00

          ===>HID Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x21
bcdHID:                          0x0110
bCountryCode:                      0x00
bNumDescriptors:                   0x01
bDescriptorType:                   0x22 (Report Descriptor)
wDescriptorLength:               0x0027

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x81  -> Direction: IN - EndpointID: 1
bmAttributes:                      0x03  -> Interrupt Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x0A
not sure whats going wrong with the descriptor... Any ideas?
Just a dogs body developer, mostly making props and stuff...
ag123
Posts: 1657
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: USB 2 way data, without virtual serial COM ports?

Post by ag123 »

i'm not the author of USB composite, and I had not used it myself. Hence, I won't really know.
But lets just say you are using the 'keyboard' as an interface, normally in the 'IN' direction (to host) would be the key codes of key presses.
then in the 'OUT' direction (to stm32), it would normally be things like the keyboard leds e.g. numlock, capslock and scrolllock.
The host may not support any other arbitrary output.
i.e. you may need a custom HID driver or app on the host side if you need anything other than a standard keyboard or mouse.

it is for such reasons that USB Serial is apparently an easier interface on the host side to make a custom app or driver.
I think there are standard api to work with serial (virtual com ports) on linux, windows.
there are quite a number of apps working that way, e.g. the SUMP protocol based logic analyzers.
http://dangerousprototypes.com/docs/Ove ... le_clients
the others that come to mind are devices that present a serial interface, e.g. GPS dongles, modems etc
note that apparently USB serial works as fast as a multiplexed usb does, usb is completely managed by the host as it is a master/slave protocol i.e. polling. i.e. 12Mbps, but it is multiplexed. It isn't limited by the serial baud rates we'd normally use for uarts.

In addition, a USB sniffer/analyzer would help a lot with examining USB traffic, i think Wireshark does it (in Linux), i'm not sure about Windows. I'd guess google it to find out if Wireshark can work as a usb sniffer/analyzer in Windows and how to do that.
User avatar
Mangy_Dog
Posts: 97
Joined: Sat May 02, 2020 11:45 pm
Answers: 1

Re: USB 2 way data, without virtual serial COM ports?

Post by Mangy_Dog »

Im already making a custom app anyway, and as long as the data end point is there to for me to send data through that should work fine.

The trouble im having right now with the rawhid is the descriptor isnt giving me an OUT end point. Even though there is one listed in the descriptor.
Just a dogs body developer, mostly making props and stuff...
ag123
Posts: 1657
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: USB 2 way data, without virtual serial COM ports?

Post by ag123 »

saw this from usb1.1 specs, this is for a keyboard - the leds
https://www.usb.org/hid

Code: Select all

95 05 Report Count (5),
75 01 Report Size (1),
05 08 Usage Page (Page# for LEDs),
19 01 Usage Minimum (1),
29 05 Usage Maximum (5),
91 02 Output (Data, Variable, Absolute),
95 01 Report Count (1), // padding
75 03 Report Size (3),
91 01 Output (Constant),
I'm not sure if it helps. In addition, there may be os side dependencies, i.e. you would likely need to code the HID app on the host side to handle that.
If you want to do HID, you may even need to define your custom usage page and usages (codes) and to program that on the host side.

Serial is still simply simpler and the IN / OUT endpoints are predefined and already working Serial.read() read and Serial.write()
User avatar
Mangy_Dog
Posts: 97
Joined: Sat May 02, 2020 11:45 pm
Answers: 1

Re: USB 2 way data, without virtual serial COM ports?

Post by Mangy_Dog »

I just really dont want to be using COM ports.
Also from what i can tell the device descriptor is function build dynamically. And im struggling to follow the code on how it builds the descriptor. So I cant double check to see if its making a mistake by limiting the end points to 1 rather than 2.

The HID descriptor seems correct. IE whats listed in rawHID.

Once I have the IN and OUT endpoints working and broken out to connect to, I can start writing code to send my dada back and forth.
Just a dogs body developer, mostly making props and stuff...
ag123
Posts: 1657
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: USB 2 way data, without virtual serial COM ports?

Post by ag123 »

those are HID report descriptors, they are not device descriptors, they are (much) more complicated than simply IN/OUT endpoints.
HID works around usage pages and usage (codes), that is nested many levels deeper than just device descriptors and IN/OUT endpoints.

even for a com port, i think it is possible to determine the usb vid and pid. that way is possible if you have a single device using this vid/pid so that you can identify it. it'd take using some usb api at the OS level to do those i think. things like sending a get_descriptor command and parsing the response. libusb is one of those libraries that does that.

if you simply want IN / OUT channels, you can even ignore protocols and just use the IN/OUT channels.
but it would be 'custom' drivers on the host side, e.g. using libusb and the like for genneric usb access.

the other protocol you may want to look into if you prefer to stick to protocols is usb mass storage protocol. e.g. mass storage bulk transport.
i'm not familiar with that. they tend to get complicated involving scsi commands and all as os hs hooks that'd connect mass storage devices once it is plugged in. i.e. on stm32 u'd need to speak 'mass storage' if you want to use that.

for 'custom' stuff, i think on windows there is WinUSB
https://docs.microsoft.com/en-us/window ... sb-drivers
https://docs.microsoft.com/en-us/window ... usb-device
i think this would let you create a custom protocol if you only stick with the basic USB IN/OUT endpoints.

if you prefer to stick with a standard usb device class, i stumbled into this in a google search
https://docs.microsoft.com/en-us/window ... sb-classes
it seemed it is also possible to speak 'printer', it'd seemed the protocol is relatively simple.
but that on Windows end, you would access that using a 'print' stereotype

CDC (usb-serial) is always there and is probably a simplest
Post Reply

Return to “General discussion”