我目前正在用C编写Linux内核模块。该模块为USB灯提供了一个非常基本的驱动程序(该设备由三个彩色LED组成)。我设法让驱动程序无问题地加载和卸载,并创建设备(/dev/wn0
,/dev/wn1
等)。但是,在尝试写入设备时,我一直收到错误:
$ echo "1" >/dev/wn0
bash: echo: write error: Broken pipe
模块的整个代码是here。然而,有趣的部分是wn_set_color()
函数:
/* 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);
出于某种原因,它返回-32
而不是将数据发送到设备。
我对Linux内核编程完全陌生,所以我可能会做些傻事。如果你能够对此有所了解,我们将不胜感激。
编辑:这里有一些进一步的信息:
答案 0 :(得分:4)
usb_control_msg()
最终致电usb_submit_urb()
。 Documentation/usb/error-codes.txt文件描述了此函数可以返回的错误:
-EPIPE The pipe type specified in the URB doesn't match the
endpoint's actual type.
如果usb_submit_urb()
成功,则usb_control_msg()
会返回urb->status
值。这列在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.
您是否检查过内核日志中的任何消息?
答案 1 :(得分:2)
我觉得这与你的usb_sndctrlpipe
电话有关。该函数的定义如下:unsigned int usb_sndctrlpipe(struct usb_device *dev, unsigned int
endpoint)
。
您似乎正在正确地传递设备指针,但是您在控制端点的值0
中的传递(如您所述)不是您的端点的地址。我建议在开头用您的端点的十六进制值定义一个常量,并将其传递给您的调用。
但是,我相信你有一个更大的问题。
查看您的lsusb,您的端点似乎实际上不是控制端点,而是中断端点。这会更改您需要调用以进行通信的功能。例如,代替usb_sndctrlpipe
,您将需要usb_rcvintpipe(struct usb_device *dev, unsigned int endpoint)
来生成管道(因为它是lsusb中列出的IN端点)并使用不同的函数而不是usb_control_msg
。不幸的是,从我可以收集到的内容来看,似乎没有可用于自动构造中断urb的函数,因此您需要创建一个urb结构,如http://www.makelinux.net/ldd3/chp-13-sect-3的第13.3.2.1节所述。更糟糕的消息是(除非我遗漏了一些东西),因为您的唯一端点似乎是中断 IN 端点,看起来您只能从设备接收中断并且无法发送任何内容到设备。您是否确定通过USB更改灯泡的颜色是设备支持的功能?
更多信息可在以下网站找到: