Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 910
Nathan Osman Avatar asked Jan 14 '13 03:01

Nathan Osman


2 Answers

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?

like image 134
caf Avatar answered Oct 22 '22 01:10

caf


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)
like image 25
user3098015 Avatar answered Oct 22 '22 02:10

user3098015