我想我實際上有兩個單獨的問題,但我認爲它們足夠相關以包含它們兩者。上下文是一個Linux USB設備驅動程序(不是用戶空間)。Linux USB驅動程序:中斷URBs
- 發送請求URB後,如何收到迴應一旦我的
complete
回調被調用? - 如何使用中斷URB作爲單個請求/響應對,而不是作爲實際的連續中斷輪詢(如其預期的那樣)?
所以對於一些背景,我工作的一個驅動程序的Microchip MCP2210一個USB至SPI協議轉換器,GPIO(USB 2.0,datasheet here)。該設備作爲通用HID進行廣告宣傳,並公開兩個中斷端點(輸入和輸出)以及它的控制端點。
我從一個由其他人寫的工作(但是阿爾法品質)demo driver開始,並且友好地與社區分享。但是,這是一款HID驅動程序,它用於與設備通信的機制非常昂貴! (發送一個64字節的消息需要分配一個6k HID報告結構,並且有時在中斷的上下文中執行分配,需要GFP_ATOMIC!)。我們將通過嵌入式低內存設備訪問此內容。
我是新來的USB驅動程序,一般Linux設備驅動程序仍然很綠。但是,我試圖將其轉換爲簡單的USB驅動程序(而不是HID),因此我可以使用便宜的中斷URB進行通信。這是我的代碼,用於傳輸我的請求。爲了(嘗試)簡潔,我不包括我的結構等的定義,但請告訴我是否需要更多我的代碼。 dev->cur_cmd
是我正在處理當前正在處理的命令的地方。
/* 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微秒發送一次我的請求?如果是這樣,我怎麼說「好吧,現在停止這個中斷」。 MCP2210只提供一種配置,一種接口,並且只有兩個中斷端點。 (我知道一切都有控制界面,不知道哪裏適合圖片雖然)
而不是垃圾郵件這個問題與lsusb -v,我要pastebin它。
非常感謝您的迴應!這對我來說似乎很奇怪,你先提交響應URB,然後再提交請求。也許這是因爲即使您的任務在發送請求後被搶佔,USB主機驅動程序也可以*接收*響應。然而,我可以同時發送它們,當我可能處於可以睡眠並分配'GFP_KERNEL'的環境中,而不是在「完成」功能中(我相信)您無法入睡(我知道在一些spi主函數中就是這種情況)。 – 2013-05-05 04:12:17
嘿,我想我會在3年多的時間裏爲你拍攝更新。 [驅動程序](https://github.com/daniel-santos/mcp2210-linux)運行得非常好,開始被很多人使用。感謝您幫助我到達那裏! :) – 2016-02-11 06:07:21