How to use "control endpoint" (default endpoint) in client application? - c

I have USB HID device, which has only control endpoint. "USB Device Viewer" by Microsoft indicates 0 endpoints as it never counts control endpoints.
I don't know much about this device - it's basically black box to me. All I know is, that it's HID class and it's capable of simple serial communication (there's 1-Wire on "the other end of a cable").
As for HW, there's AVR MCU(not much help there). And as for FW, it uses VID, PID, which doesn't say anything to google (clearly made up).
I red here that after USB device is configured, one can use control endpoint for device specific use.
My question is:
Is it possible under Windows 7 using WDK to use control endpoint in user space application?
If not, is there any other way?
If yes, how?
HidD_GetHidGuid(&guid); doesn't even list my device. Probably due to the fact that device claims to be class 0x00 not only in device descriptor:
*bDeviceClass: 0x00 -> This is an Interface Class Defined Device*
but in interface descriptor too:
bInterfaceClass: 0x00
*!*CAUTION: 0 is a Reserved USB Device Interface Class

Did you run Wireshark? (Though I believe Wireshark doesn't monitor USB on windows - not sure about that. There are other USB packet sniffers around)
With wireshark you can monitor all communications to the device.
Though I don't know the WDK, I have the impression that many, if not most people use libusb (http://libusb.info/). There is a Windows version which can run on both 32 and 64-bit versions. This library is fairly easy to use, and has access to all endpoints.

Related

Initializing Device Interfaces for Windows HID Drivers without WdfDeviceCreateDeviceInterface

I'm working on creating a virtual HID device in Windows 10. To help me with developing the drivers, I've been analyzing the example provided here: https://github.com/Microsoft/Windows-driver-samples/tree/master/hid/vhidmini2.
One thing that they do has me stumped: in app/testvhid.c, the application sends data to the driver by finding the device interface of the driver, and sending data to that. However, the driver never calls WdfDeviceCreateDeviceInterface, which I had assumed was required to create a device interface. In fact, there appears to be no mention of interfaces at all in the driver code.
My question is: how would one go about accessing an interface for an HID device, when no calls to WdfDeviceCreateDeviceInterface have been made?
HID device has VID/PID and Usage and Usage page information as the attributes, which you can see in the sample source code.
The way testvhid.c does is that it enumerates all the HID devices in the system and select the device that matches the VID/PID or Usage/UsagePage you want.
FYI, user-mode module calls HidD_GetAttributes() to get the information.

Linux USB device driver misconception

My question is going to be rather vague but I will try to explain as detailed as I can what I am trying to resolve.
Trying to learn Linux kernel USB stack I have started to think of making a simple USB driver for my Atmel evaluation board based on ARM M0+ MCU to run away from Windows tools (Visual Studio plugin).
I have spent few days learning kernel's USB API and come to conclusion of how to make this. My driver aims to make my board connected to PC through USB cable act like a simple USB flash drive. Making that I then can easily program it with a new version of firmware written by me.
I have found that I need to find out specific interface (I am talking about interface in terms of USB specification, not interface we used to use as a code abstraction) that holds an endpoint (pipe) responsible for interaction with flash memory. And then I can map it to character device and interact with it using standard I/O operations that are described in struct file_operations structure.
Simply using cat on /proc/* file descriptor that was created by USB Core subsystem I have investigated that interface responsible for interaction with flash memory holds bulk endpoint (likewise, this terms come from USB specification, CMIIAW) that act as a "descriptor". Linux kernel USB Core subsystem gives neat interfaces to talk to different kind of endpoints whether it control, interrupt, bulk or asynchronous endpoint.
Now I have come closer to my very question.
Also the main transfer unit in communication between two USB devices is abstraction called urb - you allocate it, you fill it, you send it to USB Core subsystem, you read it if it was IN type of urb and, finally, you free it. What is confusing for me and tightly related to my question is the next API include/linux/usb.h:
static inline void usb_fill_bulk_urb(struct urb *urb,
struct usb_device *dev,
unsigned int pipe,
void *transfer_buffer,
int buffer_length,
usb_complete_t complete_fn,
void *context)
Assume I have obtained an information from board's datasheet about where to write a program code. Let's say, we have 0x00100 - 0x10000 memory region. I will compile my code, obtain a binary and then using standard Linux tools or writing a simple user-space wrapper application I will use lseek to set file's offset to 0x00100 and write system call provided with a buffer (binary compiled previously) and it's length.
In kernel space, I will have to allocate urb in write system call handler, fill it with a buffer sent from user space and submit this urb to USB Core.
BUT I can not find a way how to specify an OFFSET set earlier by lseek. Do I miss something? Maybe I missed some concepts or, perhaps, I am watching in a wrong way?
When your embedded Linux device acts as a USB mass storage device, the flash as a peripheral on Linux device is unmounted, and the gadget driver is loaded. Linux then loses control to the flash, and now the PC connected to your Linux device fully controls the flash. This is because a flash as a USB device can only has one USb host.
The gadget driver works purely in kernel space. It does not receive or transmit data from/to user space. It calls vfs_read() and vfs_write() to access the files on the flash, with an field offset. The offset is got from the USB commands sent from your host - Windows PC.
There is no way to specify offset using USB subsystem's API. I misunderstood whole conception of USB as communication protocol, unwise me. You must first learn underlying protocol your device uses to communicate with others.
If your device acts as a USB HID device then learning specification of how to exchange data with USB HID device is the way to go. If there is something proprietary then you can do nothing but reverse engineer it (listening USB packets with a sniffer on system where a driver for your device exists).
As for my board it has embedded debugger that serves as a communication module besides being debugger itself. Specifically, my device is equipped with EDBG and here is a link on description of protocol it uses for communication.

Reading from usb as a comport

I'm quite a beginner in the embedded world, since I'm always at the "other side of the wire" as a SW engineer so please don't crucify me for a question that might seem silly.
When I'm working with a Bluetooth device that connects to the computer, it is usually presented as a virtual COM-port which I connect and read the data from using winapi. Now our embedded engineer presented me a device that sends the same data through a USB cable which also presents as a virtual comport at my system which I read the same (meaning, for me it is completely transparent).
Now I wonder, in any other devices that use a USB connection, I don't see the device as a comport (like a mouse, or a keyboard), yet the info is sent. Why there is a need in a comport in this case, and what other reading options available?
You should read some basic USB information.
The difference you've noticed is because USB supports something called "device classes", that basically control how the computer (the host) views the device.
One such class is "USB communications device" which often becomes a virtual COM port, for instance.
Another is the very commonly seen "USB mass storage device" which is what e.g. flash drives use.
A third is the one you mention for mouses and keyboards, which is called "USB human interface device".
Which class a particular device uses is communicated when it's first connected on the bus, so that the host can load the proper driver. You cannot magically force a device to switch classes, the class is typically a "hard" (non-modifiable) part of the device's implementation, chosen by the designers of the device.

USB Device with Ingenico iCT220

Short Story
I have been tasked to connect an USB bar code scanner to this terminal [linky (PDF)], it has an usb host port ("usb master" according to documentation) on which i can connect any usb device then using ingenico sdk's (C based) systemfioctl's functions i can detect if an usb device is present,read its PID, VID, Class, Sub Class and protocol,
The problem...
the only thing cannot do is read its input, i have tried with a mouse, keyboard and a joystic, according to documentation the OS creates a device file "com6" in order to interact with this usb port, the thing is that every time i fread this device it always reads 0 bytes, since this thing does not runs any version of linux i guess i cannot use conventional HID libraries.
does anyone ever had to do such a bizarre thing before?

use win32 API to see whether a Windows XPe system has got USB2 or just 1.1

Is there a way, just using the win32 API, to find out what version of USB is available? The XPe build is pretty barebones and doesn't doesn't have WMI.
I considered the USBview technique: enumerate the USB hubs by opening \.\HCD0 through say \.\HCD9, use DeviceIoControl to get the hub name, and looking for an enhanced host controller. But to build this I'd need the DDK which I'm not familiar with and don't want to install unless I really have to.
Is there a simpler way?
As you mention, UsbView enumerates USB hubs and devices. Its source is in the DDK at ddk\xp\src\wdm\usb\usbview.
I found a simpler approach that was device-specific and worked in my situation. I was able to determine speed based on the maximum packet size for the device. The packet size is in struct member MaximumPacketSize in structure USBD_PIPE_INFORMATION. On MSDN, see OSRUSBFX2 which says "The maximum packet size depends on the speed" - the USB 2.0 size is 0x200 and the USB 1.1 size is 0x40. Search MSDN for OSRUSBFX2 for more info.
Although not as general-purpose as enumerating USB devices, the USBD_PIPE_INFORMATION approach might work in your situation and is much simpler.

Resources