linux usb gadgets traffic monitoring - linux

I am using a BeagleBone Black board (kernel 4.14.108-ti-r104) to create USB gadget using configfs/functionfs. I compose my gadget (using gadgettool) providing details about device configuration (function, vendor id, product id and ton of other params), run my userspace program that writes descriptors and strings to ep0 and connect the device to host. All works fine, I get BIND (when binding device to UDC) and ENABLE (when actually host is connected) events and my device can read from ep2 and write to ep1. Using wireshark I see the communication looks good, device and configuration descriptors as well as strings are exchanged.
The problem starts when I connect the device to another host. Unfortunately I have almost no control over that host, in particular I cannot run wireshark there, I don't even know the OS. The only thing I can do is to plug/unplug device, optionally see a message that device was detected and optionally a restart. What I see on the gadget side is that following BIND and ENABLE events I immediately get SUSPEND event and read on ep2 fails with 108 (ESHUTDOWN). Now the question is how to track the problem down.
I tried usbmon, but it seems it does not listen to traffic when device is in gadget mode. I have also seen https://github.com/torvalds/linux/blob/master/drivers/usb/gadget/udc/trace.h file which seems to define some udc trace points, but I am not really sure how they can be used.
So the final question is simple: how do I get any information about traffic on USB bus having access only to gadget side? I don't need full trace, but al least some information which packets were exchanged would be super useful. Did it fail while exchanging device descriptors, configuration/interface/endpoint descriptors or strings or something totally different?
Small update:
The whole thing is about Android Open Accessory Protocol and I am trying to write a gadget that would connect to this accessory.
I have changed my gadget composition somewhat and now I know the gadget is being identified by host (it displays manufacturer/model) so I suppose the issue is not in device descriptor and strings. I have used two additional flags in descriptors (FUNCTIONFS_ALL_CTRL_RECIP | FUNCTIONFS_CONFIG0_SETUP) and when connecting to my computer I get setup event (request 51 as expected), but when connecting to my accessory I still get SUSPEND/ESHUTDOWN. This time though it looks like the time between ENABLE and SUSPEND is much greater (over 10 seconds) which looks to me as if the host send some message, but this message was not processed by my gadget and then the host timeout out and disabled usb device. Still don't know how to find out if the accessory sent anything to gadget and what it was...

Related

BlueZ modify LE CONNECT_REQ Timeout

I'm trying to connect to a BTLE device from Linux from C++ with BlueZ.
Connecting to most devices works fine, but there is a special device which times out with 90% probability. From a standard Android smartphone the connection to this particular device works as intended.
For #Emil's advice in my other question (thanks!) I've setup a Link Layer sniffer tool for further investigation.
During the sniff period I tried connecting to the device(Destination) from both device(Good) and device(Bad).
Device(Good) is working perfectly - it connected
Device(Bad) is not working - timed out
Now I have a Link Layer data of both device connection trials and there is one significant difference between their trials:
Device(Good)'s LL Data for its CONNECT_REQ uses 500 for Timeout value (which is 625ms) while Device(Bad)'s LL Data in CONNECT_REQ uses 42 (which is 52.5ms).
I think Device(Destination)'s response is normally (mostly) arriving between those two, ie after 52.5ms and below 625ms, but sometimes it arrives in less than 52.5ms, and then also BlueZ can connect to it finally.
Is there any possibility to change this Timeout property for CONNECT_REQ in BlueZ? Maybe with setsockopt by any chance?
Or this is something hardcoded into kernel, even for bluetooth adapters attached to USB?

Is there anyway through which USB device know that the Data is read from endpoint buffer?

I'm trying to emulate a USB Keyboard with help of STM32 USB Device Library. The host here is not a Computer/ laptop, but a custom device to which a HID keyboard can be connected. I send data using API USBD_HID_SendReport(); but the host doesn't seem to recognize or read it by the time I write new data via same API. If I send same data for say 7 times the host reads it for 4 times only.
So is there anyway to know that the data is being read by USB Host from the EP Buffer?
Shall I change the bInterval in endpoint descriptor, what is the standard interval used in case of all keyboards?
P.S. The same data when sent to Computer or Laptop does gets read quickly by the host.
USBD_HID_SendReport only prepares the data for the next transmition when host requires one. It does not matter how many times you call this function. It will be send only as many times as host requested. The moment when it is send depends on the host only.
Device does not transmit anything without the host request

Roving Networks RN240 Bluetooth Adapter - AT Command Get Connection Status (GK) Returning "4"

We have a custom embedded device that uses Roving Networks' RN240 bluetooth adapter on an RS232 port to communicate with another device via bluetooth. It is working well, but I am attempting to "bulletproof" the management of the bluetooth connection as there is an occasional hiccup and I need to handle these circumstances.
In the flow I'm working on, I put the adapter into Command mode and get back the proper response:
> CMD
< $$$
I am then able to issue commands to it to Get or Set information. One of the things we do is specify which bluetooth device to pair to using these commands. The device may already have a valid pairing, and is set to Auto Master mode. When the device powers up, it may automatically connect to our other bluetooth device (as designed). I need to know if the dongle has paired when I am attempting to perform certain functions.
The command set specification specifically says that when the Get command
> GK
< 1
is sent to the device (to obtain current connection status), it will respond with a "0" for "Not Connected" or "1" for "Connected"
I am occasionally getting a "4" when the device is either connecting or connected, and I've been unable to isolate why. Once I start getting a "4", I keep getting a "4" every time I inquire after that. I have to power down the dongle (ie: reset my test scenario) to get a different behavior.
I've poked through other Advanced User Guides on Roving Networks' website, and googled as many variations as I can think of to find what this status means. It seems when I get back "4", I can no longer control the Bluetooth Adapter as I need to. I would like to know what "4" means, and what I can do to recover the device so I can make it do what I want to!
Thanks! I appreciate any help.
(For reference, here's the page for this adapter, along with links for downloading the command set: Roving Networks RN240 Bluetooth Adapter)
EDIT: I have heard back from Microchip Engineering Support. Their answer was that "4" is an undocumented state, as it shouldn't be visible to the user. "4" means the chip in in a connecting state, and that if the module is getting into this state, it is recommended that the module be rebooted (with the "R,1" command).

How create a virtual io device in Linux that proxies data to real device?

I have an interesting problem. I am working on an embedded box with multiple instances of Linux running each on an ARM processor. They are connected over internal 1GBps network. I have a serial port device node attached to processor A (Lets say Linux-A running on it). I have a program running on processor B (Lets say on Linux-B) access the serial port device as if it is attached to Linux-B locally.
My program invokes term i/o type api calls on device node to control tty echo, character mode input. What I am wondering is if there is a way to create a virtual serial device that is available on Linux-B somehow talking to real serial device on Linux-A over internal network.
I am thinking something along the lines of:
Linux-B has /dev/ttyvirtual. Anything that gets written to it gets transported over network socket to Linux-A serialserver. The serial server exrcises the api calls on real device lets say /dev/ttys0.
Any data waiting on ttys0 gets transported back to /dev/ttyvirtual.
What are all the things involved to get this done fast?
Thanks
Videoguy
Update:
I found a discussion at
http://fixunix.com/bsd/261068-network-socket-serial-port-question.html with great pointers.
Another useful link is http://blog.philippklaus.de/2011/08/make-rs232-serial-devices-accessible-via-ethernet/
Take a look at openpty(3). This lets you create a pseudo-TTY (like /dev/pts/0, the sort that ssh connections use), which will respond as a normal TTY would, but give you direct programmatic control over the connections.
This way you can host a serial device (eg. /dev/pts/5) that you forward data between a network connection, and then other apps can perform serial operations on it without knowing about the underlying network bridge.
I ended up using socat
Examples can be found here: socat examples
You socat back to back on both the machines. One listens on a tcp port and forwards data to local virtual port or pty. The socat on other box uses real device as input and forwards any data to tcp port.

Linux user space L2 control protocols

I have a network device where a port of an Ethernet switch chip is connected to a CPU's network controller. The switch chip forwards packets from other ports to the CPU port with special header added (before MAC header) containing such information as ingress port etc.
I can strip the header when receiving the packets in the network controller driver, so the Linux network stack can communicate with the switch in a normal way. My goal, however, is to pass some information in the special headers to a user space Layer 2 control protocol suite.
In my case, a Layer 2 control protocol would normally use a raw socket to receive its control frames. For example, the Spanning Tree Protocol must be able to tell from which switch port did the packet come from.
Also, services such as http, telnet server etc should be able to use the same network interface.
Are there any Linux built-in means for delivering such information from a driver to the user space network server / client?
If not, any suggestions on implementing this?
I could implement a simple ioctl call to query the driver about the header information of the last packet that was read. However, there is no guarantee that the device was not used by other processes between recv() and ioctl().
I think the best way to implement this would be to add a field in sk_buff to store your special L2 header. If I understand correctly, headers should be preserved when passing sk_buffs from one layer to another, albeit, you might need to add some code to skb_clone.
If you reach this point, sending this value to user-space is only limited by your imagination. For example, you could
store the value in the socket structure sock and return it later using an ioctl;
return the value in recvfrom's src_addr directly
Hope this help.

Resources