我想我实际上有两个不同的问题,但我认为它们足以将它们包括在内 . 上下文是Linux USB设备驱动程序(不是用户空间) .
发送请求URB后,如果调用 complete 回调,如何收到响应?
如何将中断URB用于单个请求/响应对,而不是实际的连续中断轮询(如预期那样)?
因此,对于某些背景,我正在为Microchip MCP2210一个带有GPIO的USB-to-SPI协议转换器(USB 2.0,datasheet here)开发驱动程序 . 此设备通告为通用HID,并公开两个中断 endpoints (输入和输出)以及它的控制 endpoints .
我从其他人写的一个工作开始(但是阿尔法品质)demo driver并且与社区分享 . 但是,这是一个HID驱动程序,它用来与设备通信的机制非常昂贵! (发送64字节消息需要分配6k HID报告结构,有时在中断的上下文中执行分配,需要GFP_ATOMIC!) . 我们将从嵌入式低内存设备访问它 .
我试图将其转换为普通的USB驱动程序(而不是HID),因此我可以使用较便宜的中断URB进行通信 . 这是我传输请求的代码 . 为了(尝试)简洁,我不包括我的结构的定义等,但如果您需要更多我的代码,请告诉我 . dev->cur_cmd 是我处理的地方'm keeping the current command I' .
/* use a local for brevity */
cmd = dev->cur_cmd;
if (cmd->state == MCP2210_CMD_STATE_NEW) {
usb_fill_int_urb(dev->int_out_urb,
dev->udev,
usb_sndintpipe(dev->udev, dev->int_out_ep->desc.bEndpointAddress),
&dev->out_buffer,
sizeof(dev->out_buffer), /* always 64 bytes */
cmd->type->complete,
cmd,
dev->int_out_ep->desc.bInterval);
ret = usb_submit_urb(dev->int_out_urb, GFP_KERNEL);
if (ret) {
/* snipped: handle error */
}
cmd->state = MCP2210_CMD_STATE_XMITED;
}
这是我的完整fn:
/* note that by "ctrl" I mean a control command, not the control endpoint */
static void ctrl_complete(struct urb *)
{
struct mcp2210_device *dev = urb->context;
struct mcp2210_command *cmd = dev->cur_cmd;
int ret;
if (unlikely(!cmd || !cmd->dev)) {
printk(KERN_ERR "mcp2210: ctrl_complete called w/o valid cmd "
"or dev\n");
return;
}
switch (cmd->state) {
/* Time to rx the response */
case MCP2210_CMD_STATE_XMITED:
/* FIXME: I think that I need to check the response URB's
* status to find out if it was even transmitted or not */
usb_fill_int_urb(dev->int_in_urb,
dev->udev,
usb_sndintpipe(dev->udev, dev->int_in_ep->desc
.bEndpointAddress),
&dev->in_buffer,
sizeof(dev->in_buffer),
cmd->type->complete,
dev,
dev->int_in_ep->desc.bInterval);
ret = usb_submit_urb(dev->int_in_urb, GFP_KERNEL);
if (ret) {
dev_err(&dev->udev->dev,
"while attempting to rx response, "
"usb_submit_urb returned %d\n", ret);
free_cur_cmd(dev);
return;
}
cmd->state = MCP2210_CMD_STATE_RXED;
return;
/* got response, now process it */
case MCP2210_CMD_STATE_RXED:
process_response(cmd);
default:
dev_err(&dev->udev->dev, "ctrl_complete called with unexpected state: %d", cmd->state);
free_cur_cmd(dev);
};
}
所以我至少在这里关闭?其次, dev->int_out_ep->desc.bInterval 和 dev->int_in_ep->desc.bInterval 都等于 1 ,这会持续每125微秒发送一次请求吗?如果是这样,我怎么说"ok, ty, now stop this interrupt" . MCP2210仅提供一种配置,一个接口,并且只有两个中断 endpoints . (我知道所有东西都有控制界面,不知道它在哪里适合图片 . )
而不是用lsusb -v垃圾邮件这个问题,我打算用它来粘贴它 .