Linux kernel 为什么我的内核模块会抛出;“断管”;尝试写入设备时出错?

Linux kernel 为什么我的内核模块会抛出;“断管”;尝试写入设备时出错?,linux-kernel,usb,kernel-module,Linux Kernel,Usb,Kernel Module,我目前正在用C编写Linux内核模块。该模块为USB指示灯(该设备由三个彩色LED组成)提供了极其基本的驱动程序。我成功地让驱动程序顺利加载和卸载,并创建了设备(/dev/wn0,/dev/wn1,等等)。但是,我在尝试写入设备时不断出错: $ echo "1" >/dev/wn0 bash: echo: write error: Broken pipe 模块的完整代码如下所示。然而,有趣的部分是wn\u set\u color()函数: /* Create the data buffe

我目前正在用C编写Linux内核模块。该模块为USB指示灯(该设备由三个彩色LED组成)提供了极其基本的驱动程序。我成功地让驱动程序顺利加载和卸载,并创建了设备(
/dev/wn0
/dev/wn1
,等等)。但是,我在尝试写入设备时不断出错:

$ echo "1" >/dev/wn0
bash: echo: write error: Broken pipe
模块的完整代码如下所示。然而,有趣的部分是
wn\u set\u 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内核编程一无所知,所以我可能会做一些愚蠢的事情。如果你能解释一下,我将不胜感激


编辑:以下是一些进一步的信息:

  • lsusb-v
    输出为

  • usb_endpoint_descriptor
    类的
    bDescriptorType
    成员包含设备公开的单个端点的“5”(
    bEndpointAddress
    129
    -或
    0x81
    为十六进制)

  • 是发送到设备的其中一个控制单元的屏幕抓图

usb\u control\u msg()
最终调用
usb\u submit\u urb()
。该文件描述了此函数可以返回的错误:

-EPIPE          The pipe type specified in the URB doesn't match the
                endpoint's actual type.
如果
usb\u submit\u urb()
成功,则
usb\u control\u 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.

您检查过内核日志中的任何消息吗?

我觉得这与您的
usb\u sndctrlpipe
调用有关。此函数的定义如下:
unsigned int usb\u sndctrlpipe(struct usb\u device*dev,unsigned int
端点)

您似乎在适当地传递设备指针,但是您传递的控制端点的值
0
,正如您所提到的,不是端点的地址。我建议在端点的十六进制值开头定义一个常量,并将其传递给调用

然而,我相信你有一个更大的问题

看看您的lsusb,似乎您的端点实际上不是一个控制端点,而是一个中断端点。这将更改通信所需调用的函数。例如,您将需要
usb\u sndctrlpipe
而不是
usb\u rcvintpipe(struct-usb\u-device*dev,unsigned-int-endpoint)
来生成管道(因为它是lsusb中列出的IN端点),并使用不同的函数而不是
usb\u-control\u-msg
。不幸的是,据我所知,似乎没有自动构建中断urb的功能,因此您需要创建一个urb结构,如的第13.3.2.1节所述。更糟糕的消息是(除非我遗漏了什么),因为您唯一的端点似乎是端点中的中断,因此您似乎只能从设备接收中断,而无法向设备发送任何内容。您确定通过usb更改灯的颜色是设备支持的功能吗

有关更多信息,请访问以下网站:

  • (关于端点的详细信息以及如何读取描述符)
  • (usb通信的功能定义)

除了模块正在打印的消息之外,内核日志(通过
dmesg
)中没有任何有趣的内容。