USB dongle (non-storage device) not recognized after rebooted while plugged in - windows-ce

We have a programmable proprietary USB dongle (that is not a storage device) that we insert into a machine running Windows CE7. With the dongle there is an API we can use. One simple API function is the "checkIfDongleInserted" function.
The USB dongle is recognized when inserted on the running machine, i.e. it is listed in the Wince Registry under HKLM\Drivers\Active and we can find it with the checkIfDongleInserted function.
However if we restart the machine while the dongle stays inserted, the device is not recognized anymore, i.e. it doesn't show up in the registry and the API function fails. If we reinsert the dongle by hand then it is recognized again.
Funny enough other devices (USB sticks, USB keyboards, USB mouses) work and are recognized perfectly well after a reboot of the machine while said devices stay inserted.
Upon inspecting the USB dongle's driver I found that it implements the interface USBInstallDriver. Researching this interface led me to https://learn.microsoft.com/en-us/previous-versions/windows/embedded/ms923254(v=msdn.10), where in the remarks it says that
The USB driver module calls this function when an unrecognized
device is attached to the USB port
So my guess is that restarting this "USB driver module" (from a client application) while the machine is running could be an idea to recognize the USB dongle. Though I don't see this happening from a client application.
What could be the reason for this specific device not being detected upon boot while it is inserted?
Is there a way to recognize it without having to reinsert it manually?

Inspired by this post I found the solution.
I was right in the assumption that I had to restart the USB controller, I just didn't know how.
After further research I found that HCD (Host Controller Driver) is the driver that detects the inserted USB devices and that I need to reload again. Upon doing that it would detect my already inserted USB dongle again.
Use FindFirstDevice to find the device (in this case the Host controller), then unload the driver with DeactivateDevice() and soon after load the driver again with ActivateDeviceEx().
Here's the code without any error handling (I'm on a different PC and too lazy to copy everything over, so I just roughly wrote the above steps in C)
DeviceSearchType searchType = DeviceSearchByDeviceName;
DEVMGR_DEVICE_INFORMATION deviceInfo;
//Find HCD
handle = FindFirstDevice(searchType,L"HCD*",&deviceInfo);
//Save the deviceKey to later be able to ActivateDeviceEx()
WCHAR* deviceKey = deviceInfo.szDeviceKey;
DeactivateDevice(deviceInfo.hDevice);
Sleep(100); //to make sure
ActivateDeviceEx(deviceKey,NULL,0,NULL);

Related

Can a USB 3 Host machine be programmed as a USB 3 Peripheral (or a HID keyboard)?

What I want to do:
An AI program on a host machine, reading inputs from a camera sensing the screen of the target machine and outputting controls to the target machine via USB connection--programming the host machine's USB host as a USB peripheral connected to the target machine.
What I want to do step by step: (is it possible to implement the steps below?)
Have a host machine A and a target machine B.
Connect A and B with a USB 3.0 Type-A male-male cable.
The USB connection shows up as an HID keyboard device on B.
Write code to simulate key presses on A that sends to B.
(Eg. calling press('F') on a program running on A would type F to B's input)
It shouldn't require any program installed on B.
What I already searched:
USB 3.0 Host to host connection is possible:
https://superuser.com/questions/795053/how-do-i-connect-two-computers-using-usb-3-0
USB 2.0 Host to host connection is impossible:
https://superuser.com/questions/99274/how-to-connect-two-computers-with-usb
Similar questions asked without the assumption that USB 3.0 Host to Host connection is possible:
https://superuser.com/questions/1128365/simulate-usb-keyboard-from-machine
Setting up a computer to act as an HID device connected to another computer via ps/2,usb or another wired connection
https://superuser.com/questions/507921/computer-to-act-as-keyboard?rq=1
Suggestions in ascending order of feasibility:
USB Gadgets
You are using linux, so the default way would be to create/configure/load a gadget driver. Have a look at this tutorial, though for a raspberry, should work on your PC too. However, I could not find any information regarding the use of USB3 - the tutorial assumes your host is using one of it's OTG ports, which your PC most likely does not have. So whether this works with your USB3.1 Type-A-to-Type-A connection you'll need to test.
USBIP
The idea of sharing USB devices (not just keyboards) is not really new. With USBIP you can "export" any local USB device to the network, and your client will need the client-side USBIP driver to access the keyboard.
Dont bother with USB at all, just use Ethernet
I'd simply write two userland scripts/programs that send/receive+execute the keystrokes. Very easy to implement, you're probably familiar with python anyway.
If you absolutely cant have software installed on the client-PC and your Type-C-to-Type-C connection doesnt support USB Gadgets, there's another way. It basically involves the use of two USB-to-serial adapters (~15$) and a serial cable. While this wont be enumerated as a keyboard, but rather as serial port, it's the lowest-effort solution to transfer data without additional software on the client. Both computers will just do file I/O. If your computers still have COM-ports, you can even omit the serial converters!

Connecting to Serial USB device via WebUSB

I have hardware which is connected to the mac or windows via USB Serial Mode. Currently, I have a nodejs application which sends and receive messages to this hardware using "serial" node module.
I am trying to connect to the hardware from WebPage. I used WebUSB serial.js. I am able to see the device and guess it is connecting. But when I try to send/receive the message - it says unable to claim the interface.
I would like to know can I use the WebUSB for USB with serial support?
The claimInterface() call is failing because your operating system has already loaded the USB serial class driver for this device (or perhaps a vendor-specific one such as FTDI). USB interfaces can only be claimed by one thing at a time. The option to change the device firmware so that the interface is no longer recognized by the driver (modify the interface class or product IDs) then you will be able to claim the interface and use code like the Arduino WebUSB library's serial.js that you found.
The other option is to wait for Chrome to finish implementing the Serial API. Status on that can be tracked here.
What worked for me was to run sudo modprobe -r ftdi_sio in the console.
That way, it unloads the USB from the OS and makes it available for WebUSB to use it and claim the interface.

How can I prevent linux from initializing a USB HID device

I have a USB HID device that can work in two different modes. The selection of modes is based on the sequence of USB enumeration/initialization packets sent to it.
I am using a Raspberry Pi 3 running Raspbian, however I also see the same issue if I compile my code for my desktop Ubuntu distro.
The issue I have is that linux is recognizing the USB device as a HID device and then sending the sequence of commands that it deems necessary to start the device, and this works correctly and starts the device in "Mode 1".
However I need to start the device in "Mode 2" and to do this I need to send a slightly different set of enumeration/initialization commands.
I am new to linux but very experienced with LibUSB and LibUSBDotNet under windows and can get the behavior I desire under windows.
Windows has similar behaviour to linux in that it will enumerate, recognise the device as a USB HID device and then initialise it as it deems fit resulting in the device going into "Mode 1". To prevent windows doing this I can create a LibUSB filter driver for the device, which then replaces the default driver, so windows will now do the initial enumeration, realise that the VID and PID of the device are managed by the LibUSB filter driver (rather than the windows HID driver) and then stop enumeration/initialization - this allows my code to take over and complete the initialization into "Mode 2".
How can I stop Linux from fully enumerating/initializing this device (as I do with windows). Perhaps I need to do something with udev rules or something, but I would have no idea what as I am new to linux.
Any help greatly appreciated
you have right, you have to play with the udev rules.
First of all you have to identify your device. Find the idProduct and the idVendor of your device. You can use:
lsusb
Then in the rules.d folder (/etc/udev/rules.d) create a new file with the name:
10-my-usb.rules
In this file add this line
SUBSYSTEM=="usb",ATTRS{idVendor}=="XXXX", ATTRS{idProduct}=="XXXX", MODE="666", GROUP+="plugdev"
Replace the XXXX with the value you get before
Then restart your udev rules:
sudo udevadm trigger
Then unplug and replug normally you can use it

How to detect when a usb cable is connected/disconnected on the device side in Linux 2.6.37?

I have a embedded device that runs linux 2.6.37.
I want my application to know when the USB is connected.
Currently I can achieve this by pooling
/sys/devices/platform/musb/musb-hdrc.0/vbus.
However this approach does not distinguish between a USB charger or a USB host.
I found this udev approach but I don't think it's available in my version of the kernel. because I did not find any USB related nodes in my /dev. This discussing also shows that it might not be feasible, ether.
I also found linux hotplug and tried the netlink example, but I didn't see any output running the example when I connect/disconnect the USB cable.
What I want to do is to detect connection type on the device, when USB is connected, and prepare (unmount file system) and switch to g_file_storage if device is connected to a host, and do nothing if device is connect to a charger.
How shall I achieve this?
To achieve that, you can use the inotify(7) feature, available in all linux kernels to be awaken as soon as some device node gets created in /sys.
To know what type of device you have, you have to read the usb info from proper usb ioctl call (or if you are not a kernel interface expert, using the libusb interface) to get the device vendor, device id and device class fields coming from the device. Normally, the hotplug software gets informed on these clase of events (via a special socket). The most probably reason you don't get the device properly initialized is some misconfiguration in the config files for udev system, which normally has one entry for each possible device vendor/device id pair and allows it to load the appropiate device driver to control it. The process continues with the device driver module creating dynamically the actual devices, and they'll appear in the /dev/ filesystem as a consequence of some other kernel event to udevd.
Read apropiate documents in <linux_src>/Documentation (this directory directory belongs to the linux kernel source code, so you'll probably need to install it), and udevd(8) man pages to be able to add a new usb.
On 2.6.37 kernel, this could be done by polling
/sys/devices/platform/musb-omap2430.0/musb-hdrc.0/mode
If handshake with host is successful then it will read as "peripheral", if fail it'll be "idle".

Linux Virtual USB device driver

My goal is to create a virtual USB char device (not block device) for Linux 2.6.32 and above (I use debian squeeze) that would be recognize by the system.
I would like that this device be listed with lsusb as a normal USB device, and that every application could use libusb in order to open the device, and send control message, and make bulk write/read. But behind this virtual device, it's behavior would be set by my application. I want to set it's product ID, it's vendor ID, answer to USB status, and bulk read.
I've read some posts about how to use USB/IP in order to create a virtual USB device, and that's exactly what I want to do
Installation and emulation of virtual USB Device
http://breaking-the-system.blogspot.fr/2014/08/emulating-usb-devices-in-python-with-no.html
But unfortunately, when I tried with 2.6.32 kernel and above, I didn't succeed making it work. So I looked at how to create a kernel module that would create the virtual device :
http://pete.akeo.ie/2011/08/writing-linux-device-driver-for-kernels.html
This one looks great also, but the sample provided doest not indicate how to make it an USB device.
I've seen some post talking about it with windows but none that could help me with Linux.
I would like to avoid buying some USB programmable cards when it can be done with software.
Have anyone any leads on how to make the first methods works under newer kernel, or convert the sample code of the second method for making an USB device ?
I have fixed the code of http://breaking-the-system.blogspot.fr/2014/08/emulating-usb-devices-in-python-with-no.html (first method using USB/IP) to work with linux 4.3.
In the original code are missing USB requests like set configuration and get status. Without the implementation of all USB requests used for the OS driver the code will not work.
The fixed code can be downloaded in https://github.com/lcgamboa/USB-Emulation .
I guess raw-gadget kernel module is the thing that you want?
you can check the dummy_hcd and tests directory inside the repo, it will guide you how to create a virtual USB device

Resources