Ruby: Libusb, one USB Device, two input endpoints = difficulties - ruby

I'd like to read out an USB Device in Ruby with libusb, which has two endpoints for input, once 0x81, which is in fact a Midi input Connector, and 0x82, which is the HID of this particular device (where the midi input is built in).
The problem is: Libusb responds with an Timeout, if the Endpoint 0x81 (Midi) is not being fed with data through the Midi input. So in order to fetch data simultaneously also from Endpoint 0x82 (HID), i need a construction like
begin
data = #handle.bulk_transfer(:endpoint=>0x81, :dataIn=>512, :timeout=>20)
rescue
data2 = #handle.bulk_transfer(:endpoint=>0x82, :dataIn=>512, :timeout=>20)
end
But this doesn't work at all, because i won't get any updated data from the HID-Endpoint (0x82), unless the Midi-Endpoint also receives data .
Endpoint 0x82 doesn't generate an timeout when asking for data, but the transmitted Data doesn't change by any action on the HID. Without previously calling Endpoint 0x81 at least the HID works fine.
Is there anything additional that i should tell libusb before accessing another endpoint, after a timeout occurs? According to Lsusb the device itself only accepts bulk transfers on those endpoints.

Related

Zero-length packets for USB control transfers

In the context of a DFU driver, I'm trying to respond with a packet of length zero (not ZLP as in multiples of max size, just zero bytes) to a USB control in transfer. However, the host returns with a timeout condition. I tried both, the dfu-util tool and the corresponding protocol, as well as a minimal working example with pyusb just issuing a control in transfer of some length and the device returning no data.
My key question is: Do I achieve this by responding with a NAK or should I set the endpoint valid but without any data? The specs are rather vague about this, imo.
Here are some technical details since I'm not sure where the problem is:
Host: Linux Kernel 5.16.10, dfu-util and pyusb (presumably) both using libusb 0.1.12
Device: STM32L1 with ChibiOS 21.11.1 USB stack (sends NAK in the above situation, I also tried to modify it to send a zero-length packet without success)
It sounds like you are programming the firmware of a device, and you want your device to give a response that is 0 bytes long when the host starts a control read transfer.
You can't simply send a NAK token: that is what the device does when the data isn't ready yet, and it causes the host to try again later to read the data.
Instead, you must actually send a 0-length IN packet to the host. When the host receives this packet, it sees that the packet is shorter than the maximum packet size, so it knows the data phase of the control transfer is done, and it moves on to the status stage.

How CSMA/CA works on XBee?

I'm trying to implement S-MAC protocol on waspmote xbee sensors and i know it has its own CSMA/CA. So first of all I need to understand the basic of xBee collision avoidance.
Two senders set up in api mode in libraries and both periodically sending single bytes to a common receiver. I reduce the delay and many changing in libabries to make collision and to see how algorithm works. But when i monitor data at the receiver all looks as expected at the receiver .. byte1, byte 2 .. byte1, byte2.
Do u have any idea how can i make collision?
Are you sniffing the 802.15.4 traffic? That's the only way you'd see a collision.
The XBee module buffers the data you want to send, using the host communication parameters (baud rate, API mode, etc.) and then sends it out over 802.15.4 at 250kbps. The module has all of the collision avoidance built in, and will retransmit as necessary to deliver your message. If it's unable to deliver after some number of transmission attempts, you'll get a Transmit Status frame indicating failure.
On the receiving end, it buffers the data and delivers it to the local host using local serial settings (baud rate and API mode).
If you're trying to implement S-MAC, you need a different radio processor where you have low-level control over the radio. The XBee module provides an application layer and handles the MAC layer itself.

Listening to 2 senders on the same USB Port using Docklight

I am currently working on a script in docklight v2.0.
My setup is the following:
I have a splitter connected in the USB port of my PC.
That splitter is connected on a wire on which a communication is made between 2 devices.
Docklight is connected on the USB port and receives all the information transmited through that wire.
I have a script on docklight set up to put every byte in a buffer once docklight sniffs them.
My script is coded using the functions in Docklight and VBScript.
The problem I have is the following:
I put all the bytes in the same buffer, that mixes up the messages from both devices and it becomes impossible to analyse them.
What I need to do:
I need to know which byte comes from which device, Docklight is already able to do so, but I need to do that in my script so I can put the bytes in 2 different buffers to treat the data properly.
Using the fonction DL.OnReceive_GetChannel() solved my problem.

HW device via COM port, access individual pins

I'm currently working on a project which involves dealing with a HW device tailor-made for this purpose.
The device will serve the purpose of sending certain data via serial port (COM1, for instance). The data it is supposed to send doesn't matter that much.
I already have some knowledge regarding Windows serial port communication. CreateFile, WriteFile, and so on... BUT...
There is one "engine" on the device, which will send me the data when I ask it to, and in order to do so, I need to send there a signal (10101010) the rate of which will indicate the clock rate of that device "engine".
Here comes the explanation of how this device work. It gets a signal to send data through one pin. I'm supposed to send there 0 for start, 1 for end. Then, after this, it will watch some other pin for signal, sample it, and based on the frequency of ones and zeroes I send to it, it will start sending data via the thrid pin.
My questions are:
How to access individual pins of COM port?
How to manage the frequency and any delays I will need by myself?
I think that maybe I will have to do on this in kernel more by use of device drivers which will have to be developed.
There is an easier way. The COM port will send out the signal of alternating 1s and 0s if you just send a 0xAA byte.

Why is my kernel module throwing "broken pipe" errors when I try to write to a device?

I am currently in the process of writing a Linux kernel module in C. The module provides an extremely basic driver for a USB light (the device consists of three colored LEDs). I have managed to get the driver to load and unload without problems and also create the device (/dev/wn0, /dev/wn1, etc.). However, I keep getting errors when attempting to write to the device:
$ echo "1" >/dev/wn0
bash: echo: write error: Broken pipe
The entire code for the module is here. However, the interesting part is the wn_set_color() function:
/* Create the data buffer to be sent to the device. */
u8 buf[8] = {
red, green, blue, 0, 0, 0, 0x1F, 0x05
};
/* Send the data to the device. */
return usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
0, 0, 0, 0,
buf, 8, 0);
For some reason, it returns -32 instead of sending the data to the device.
I am completely new to Linux kernel programming so I'm likely doing something silly. If you can shed some light on this at all, it would be greatly appreciated.
Edit: here is some further information:
lsusb -v output is here
the bDescriptorType member of the usb_endpoint_descriptor class contains '5' for the single endpoint exposed by the device (bEndpointAddress is 129 - or 0x81 in hex)
here is a screengrab of one of the control URBs sent to the device
usb_control_msg() eventually calls down to usb_submit_urb(). The Documentation/usb/error-codes.txt file describes the errors that this function can return:
-EPIPE The pipe type specified in the URB doesn't match the
endpoint's actual type.
If usb_submit_urb() succeeded, then usb_control_msg() returns an urb->status value. This lists under EPIPE:
-EPIPE (**) Endpoint stalled. For non-control endpoints,
reset this status with usb_clear_halt().
(**) This is also one of several codes that different kinds of host
controller use to indicate a transfer has failed because of device
disconnect. In the interval before the hub driver starts disconnect
processing, devices may receive such fault reports for every request.
Have you checked for any messages in the kernel log?
I have a feeling it has to do with your usb_sndctrlpipe call. The definition of this function is as follows: unsigned int usb_sndctrlpipe(struct usb_device *dev, unsigned int
endpoint).
You seem to be passing the device pointer appropriately, however your pass in the value 0 for your control endpoint, which as you mention, is not the address of your endpoint. I would recommend defining a constant at the beginning with the hex value of your endpoint and passing that to your calls.
However, I believe you have a bigger problem.
Looking at your lsusb, it seems that your endpoint is not actually a control endpoint, but an interrupt endpoint. This changes the functions that you need to call to communicate. For example, instead of usb_sndctrlpipe you will need usb_rcvintpipe(struct usb_device *dev, unsigned int endpoint) to generate the pipe (since it is an IN endpoint as listed in your lsusb) and use a different function instead of usb_control_msg. Unfortunately, from what I can gather, it seems like there are no functions available to automatically construct interrupt urbs so you will need to create a urb struct as described in section 13.3.2.1 of http://www.makelinux.net/ldd3/chp-13-sect-3. Even worse news is that (unless I am missing something) because your only endpoint seems to be the interrupt IN endpoint, it would seem that you can only receive interrupts from the device and are not able to send anything to the device. Do you know for sure that changing the colors of the lamp via usb is a functionality supported by the device?
More information can be found at the following:
http://www.beyondlogic.org/usbnutshell/usb4.shtml (thorough information on endpoints and how to read the descriptors)
http://www.makelinux.net/ldd3/chp-13-sect-3 and
http://www.makelinux.net/ldd3/chp-13-sect-5 (function definitions for usb communication)

Resources