Creating a driver to translate HID-USB requests into HCI packets - c++

So this may seem a little odd, but I'm rather limited by the hardware I have on hand.
I've got a device that consists of a TI CC2640R2 wired to a Silicon Labs CP2110 UART to USB-HID bridge. The basic premise of the device is to send Bluetooth HCI commands from the TI chip to the CP2110, which translates the UART data to an HID record, which can be read by application code on the host machine, and vice versa. What I'd like to do is to wire this device into the predefined HCI stack in Windows 10, so the desktop can use the device as a standard Bluetooth endpoint.
Normally, this wouldn't be a problem, as the device's USB chip would enumerate it as a Bluetooth device, which would cause the PnP manager in Windows to attach it to the system's Bluetooth stack. The HID device, however, complicates matters.
In order to make this work properly, I'd need to intercept HID records from the target device, unpack them, and forward them to the HCI stack so Windows Bluetooth would know what to do. I'd have to do the exact opposite going the other way - take an HCI command, package it into the appropriate HID record, and send the record to the target device.
I've managed to get the source code for the KMDF example of a Bluetooth Serial HCI Bus Driver, but I don't know the proper way to get the target device from the HID class driver, or if I'd need to do something with an HID minidriver to bridge the two driver stacks.
Is it possible to retrieve a pointer to an HID device from kernel mode, and if so, how would I go about doing that?
If not, and an HID minidriver is required to intercept and relay commands, what would be the best method of combining the HCI driver and the HID minidriver to allow the two to interoperate cleanly?

Related

Creating a Fake Serial Port to Emulate Modem

I'm quite new to programming at linux and its file-based communication.
I need to create a virtual modem (or modem emulator) at linux machine. The idea is that the software module that sends commands to hardware modem on an FPGA,
At FPGA:
SoftwareModule <= ttyACM => HardwareModem
What I need to achieve at my computer:
SoftwareModule <=> MyModemEmulator acting like a fake UART
Purpose is that the software module can be tested on a linux machine where I have a fake software modem UART(?) port. So the software module sends the modem commands and my fake modem module catches and responds accordingly. So my module will be actually acting like a hardware modem.
What could be the steps I need to take for that? I'm quite new to working with serial ports and don't have deep knowledge of linux or hardware stuff.
I have come across 'socat' but I'm not sure if that can really serve the purpose.
So far I have only learned how to create a basic file system with FUSE (as it was suggested by someone), but I'm not sure how can I use it for my purpose. I'm not looking for a proprietary solution, and not looking for windows based solution either.
Please guide me to the right directions.
Thank you !
Creating a Fake Serial Port to Emulate Modem
What you refer to as a "serial port" in Linux is actually a serial terminal with many software layers.
Study Linux serial drivers, and the termios man page for salient functions that need to be emulated.
And you have not even considered how to factor in the USB component of the communication path.
At FPGA:
SoftwareModule <= ttyACM => HardwareModem
...
My computer with ubuntu does not have ttyACM
A /dev/ttyACMx device node is only created when a USB serial gadget is connected to the host.
So it's not surprising that you cannot find such a device node.
What I need to achieve at my computer:
SoftwareModule <=> MyModemEmulator acting like a fake UART
You have stated the issue poorly, since you (misguidedly) think that a "fake UART" (integrated with your "MyModemEmulator") is the appropriate solution.
Do not try to emulate both a serial terminal and an external modem on the Ubuntu host, since you are "quite new to programming at linux and serial ports" and the task of accurately emulating a serial terminal is risky and expensive.
What your goal should be is:
SoftwareModule <= ? => MyModemEmulator
and the question is "what is needed in the middle to interface these two units?".
IOW you have posted an XY problem.
There are a plethora of SBCs (single board computer) that have a USB gadget port and can be configured as a USB serial gadget that uses CDC ACM.
Since the actual "hardware modem on an FPGA" will use a USB CDC ACM connection, you should consider using an actual /dev/ttyACMx serial terminal, and emulating just the external device ("hardware modem") with a SBC.
In other words, instead of trying to achieve:
SoftwareModule <=> MyModemEmulator + fake USB serial terminal
it should be much easier to use existing interfaces and implement:
SoftwareModule <= USB => emulated HardwareModem
with a SBC running your Linux application for modem emulation using /dev/ttyGS0 (a USB serial terminal on the gadget end).
By using an actual USB CDC ACM connection and not implementing the "fake USB serial terminal", this approach eliminates an entire layer of SW+HW emulation and its possible false test results.
Addendum
If the use and/or cost of embedded Linux on a SBC concerns you, then there is an alternative scheme to emulate the "hardware modem" on your Ubuntu PC host instead of the SBC using a USB-to-RS232-to-USB connection.
Acquire a pair (i.e. quantity 2) of USB-to-RS232 adapters and a (very short) null-modem cable.
Connect the DB-9 ends of the adapters to the null-modem cable to make a single cable with both ends having a USB male type-A connector.
Plug one adapter into the PC to create the /dev/ttyUSB0 device node. Treat this as the equivalent to /dev/ttyACM0 for your SoftwareModule.
Plug the other adapter into the PC to create the /dev/ttyUSB1 device node. Treat this as the equivalent to /dev/ttyGS0 for your emulated "hardware modem".
Develop, execute, and debug your emulated "hardware modem" on the Ubuntu PC host (without the unnecessary task of "creating a fake serial port").

Making a QT-creator Application communicate with a Microcontroller

Currently I want to create a qt application on my Desktop that say, has 3 buttons. These 3 buttons can change certain variables for my device, which will be connected to the desktop with a microcontroller.
I want my desktop application to be able to communicate with the microcontroller. For example, clicking a button might flip a certain boolean variable and the microcontroller will adjust accordingly.
I have no idea how to start and what sort of questions I should be asking and how to tackle this at a high level.
Thank you.
My desktop is a macbook pro retina 15-inch 2014 and my microcontroller is either an Teensy, or an Intel Atom.
I don't know what type of microcontroller you are using, but if it has support for UART you can use the QSerialPort lib (http://doc.qt.io/qt-5/qserialport.html) to send data using a serial port.
In case of an arduino, you can send messages using this lib directly via the USB emulated COM port. If it don't have USB emulated COM port, you should use a serial adapter (an Arduino board can play this role).
The first thing to look at is what communication buses are common between your desktop computer and your microcontroller. Does your microcontroller have USB or ethernet capabilities? Does your microcontroller have expansion boards for WiFi or bluetooth support? Do you have access to an I2C bus in your desktop PC?
Depending on the answers above, if your microcontroller and your computer do not share common communication buses, you might have to use intermediary hardware, for instance, you might want to use something like the FTDI USB (on your desktop) to UART (for the microcontroller) cables, you can find those here: http://www.ftdichip.com/Products/Cables/USBTTLSerial.htm
In that case I'd recommend using a cable with VCD drivers, so the cable appears as a Serial port to your computer, which you can access in QT by using QSerialPort (http://doc.qt.io/qt-5/qserialport.html)
There would be other similar solutions, but I'd say that, if there are no shared buses between your microcontroller and host, this would be one of the most universal. Maybe if you specify your microcontroller or embedded board We could help a little more.

Send zeroes and ones to the USB data pins?

Am trying to figure how can I make some software and USB hardware.
Let's put the hardware thing aside for now. For software, how can I send data to a USB port?
C++ / Java or any other language (prefer to be working on Linux).
USB ports are not like "dumb" RS-232 serial ports. It's a bus, that requires quite complicated handling, all driven by the host (the computer, typically). Very low-level operations such as "sending ones and zeros" to the data pins are more or less impossible.
The easiest way to program USB from user-space in Linux is probably to use libusb.
On the client (your custom USB hardware) end, either look for a system featuring a built-in USB controller, or a software stack. I don't think writing your own software stack is feasible, since you (no offense) don't seem to be quite at that level regarding your knowledge of USB.
V-USB is a software USB stack for Atmel's AVR microcontrollers, for instance.
As others have pointed out you have to write a driver for the USB device.
Another option is to communicate with the device using a serial protocol over USB, then your hardware needs an USB to serial chip. The best answer regarding USB over serial is in the question How to get C++ to perform I/O from a USB Port like a Serial Port by Mike DeSimone
If you want to bitbang I/O using USB, then you can connect a FTDI chip like the FT232 (which is used in many USB to serial cables) to the USB port.
On the PC you can use libFTDI to bitbang the I/O pins of the FTDI chip.
I think this is the easiest way for controlling I/O pins using USB.
An alternative to serial port emulation is USB HID (Human Input Device), which is supported on Linux out of the box. You'd use the "HIDAPI" to communicate with your device.
A usb port is just a serial port. Therefore, the first place that you want to look is writing a sofware to handle serial port communication.
Be aware that the OS may assign a different port number to the device whenever it's connected.

How to get C++ to perform I/O from a USB Port like a Serial Port

Is it possible to read/write from/to a specific USB port, avoiding all that USB handshaking stuff?
What I want to do is communicate with a microcontroller, for example, that doesn't have a USB driver on board via USB. I want my C++ application to be able to send data via a specific USB port and then to receive data from that same USB port.
Basically what I want to be able to do is treat that USB port like a serial port. Is this possible? Is there a workaround I can use?
Thanks in advance.
PS: I know this isn't the best way to go about communication with a uC, but let's assume, for some reason, I have to do it this way.
Edit: BTW I'm using Windows 7
The usual solution is to use an FTDI USB-to-serial chip, such as the FT232R, on your microcontroller board. Then, as far as your MCU is concerned, it's talking to a serial port, and on the host machine you just have to have the right drivers.
On my Mac, the FTDI chip shows up as a serial port at /dev/tty.usbmodem____, where ____ is some persistent unique ID assigned by the Mac on first detection. Unplugging and replugging, even weeks later, gets the same number, but it's a different number on a different Mac.
On Windows, it shows up as a new COM port if you have the drivers installed, IIRC. On Linux, it shows up as /dev/ttyUSB_ where _ is a serial number starting at 0, if you have FTDI serial driver support enabled in the kernel. This can get tricky if you plug in more than one FTDI chip.
If your microcontroller has a built-in USB port, then you need to find the software for it to identify itself as a standard CDC (Communication Device Class) serial port device (standard documentation available). Most OSs have support for this standard USB device class.
Use one of the USB to serial port adapters. The USB port will look just like a serial port to your C++ program.
In general you can do a close approximation of this using the HID interface: drivers are built in, and you can send feature reports in both directions. It isn't quite serial port simplicity (since it is packets, as opposed to a continuous byte stream) but hidapi makes it really simple and cross-platform.

Read data from Wii-balanceboard

Im trying to get the output from a Wii Fit (balance board). I can find the device via the C++ Bluetooth enumerators but attempts to connect via a windows socket are failing.
Im wondering if anyone has had success in such a direction (C++, windows) I'd love to hear how you did it.
The Wii Balance Board is a HID device. To understand communications with the Balance Board, you need to know a little bit about Bluetooth HID. There's good information on WiiBrew about the Wiimote and the Wii Balance Board.
I don't think you can use Windows Sockets to connect to a HID device. The Windows Socket Bluetooth interface only allows you to connect to RFCOMM-based services. HID is based on L2CAP which is further down the Bluetooth protocol stack. There's some information at MSDN about that limitation.
If you're just looking to hack around with it, you can try Bluecove for Java. You may be able to do something using another stack (for example, Widcomm). If you're locked in to Windows and C++, you may have to look into writing an custom HID driver for the Balance Board.
As pwc said there is a limitation in the MS Bluetooth API, so with sockets you cannot have something else except RFCOMM, but this doesn't mean you cannot go down at L2CAP layer. What you have to do is to implement a client profile driver and you can use as starting point an article from MSDN: Creating a L2CAP Client Connection to a Remote Device and vice-versa: Accepting L2CAP Connections in a Bluetooth Profile Driver
Next of course as pwc said you have to study Bluetooth HID and WiiBrew for the communication protocol.
Also a good document to read is Bluetooth Wireless Technology FAQ - 2010 which states clear that it is possible to have L2CAP connections with Microsoft Bluetooth stack driver. Of course not with sockets.
When using HID on a Bluetooth device there is generally no need to create a L2CAP connection directly. All(???) of the Bluetooth stacks on Win32 have support for Bluetooth HID and provide access to the HID stream/control through the native Windows HID API. No (direct) L2CAP required! :-)
On WinCE there is built-in support for Bluetooth HID also, but I'm not sure there's a way to access a HID API.
That's how Brian Peek's wiimore library works -- it uses the HID API. The good thing about that is that one gets supports for all(?) the Bluetooth stacks that way -- they each support HID devices via the Windows HID API, whereas to use L2CAP directly one would have to support each of the stacks' APIs... (That's if they have one! BlueSoleil has no L2CAP API as far as I can see).
So, on Win32 one should just pair with the device and check that the HID checkbox is checked on its Bluetooth Service control panel tab (whichever Bluetooth stack is in use). In my 32feet.NET library one can discover the device and then ensure that HID is enabled for it with:
BluetoothDeviceInfo[] list = btCli.DiscoveryDevices();
var deviceInfo = list[n]; // Select the correct device
deviceInfo.SetServiceState(BluetoothService.HumanInterfaceDevice, true);
(That should work on MSFT and BlueSoleil; there's no API for that on Widcomm AFAIK -- although when paired it might be automatically enabled anyway).
The one possible exception case is that apparently some devices are not fully compliant with the Bluetooth/HID specs, I'm told the PS3 blu-ray controller is like that. Then one might want to try L2CAP connections directly -- however its likely that the stack's support for HID will interfere with third-party applications trying to provide the same service...