首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Linux驱动程序:中断URBs

Linux驱动程序:中断URBs
EN

Stack Overflow用户
提问于 2013-04-27 17:30:57
回答 1查看 7.3K关注 0票数 3

我想我实际上有两个独立的问题,但我认为它们之间有足够的关系,足以把它们都包括在内。上下文是一个Linux设备驱动程序(不是用户空间)。

  1. 发送请求URB后,调用complete回调后如何接收响应?
  2. 如何才能将中断URBs用于单个请求/响应对,而不是作为实际的连续中断轮询(它们是预期的)?

因此,作为背景,我正在为微芯片MCP2210开发一个驱动程序--一个带有GPIO的USB协议转换器(USB2.0,数据表)。此设备宣传为通用HID,并公开两个中断端点(输入和输出)以及它的控制端点。

我是从一个工作的,(但阿尔法质量)的演示驱动程序开始的,它是由其他人写的,并与社区友好地分享。然而,这是一个HID驱动程序,它用来与设备通信的机制非常昂贵!(发送64字节消息需要分配6k HID报表结构,有时在中断上下文中执行分配,需要GFP_ATOMIC!)。我们将从一个嵌入式的低内存设备上访问这个。

我对USB驱动程序还很陌生,对于Linux设备驱动程序来说,我还是很绿色的。不过,我正试图将其转换为普通的USB驱动程序(而不是HID),这样我就可以在通信中使用更便宜的中断URBs。这是我发送请求的代码。为了(尝试)简洁起见,我不包括结构的定义等等,但是如果您需要更多的代码,请告诉我。dev->cur_cmd是我保存正在处理的当前命令的地方。

代码语言:javascript
复制
/* 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:

代码语言:javascript
复制
/* 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.bIntervaldev->int_in_ep->desc.bInterval都等于1,这会继续每125微秒发送我的请求吗?如果是这样的话,我该怎么说“好的,泰,现在停止这个中断”。MCP2210只提供一个配置,一个接口,其中只有两个中断端点。(我知道所有的东西都有控制界面,但我不确定它在图片中的位置。)

而不是垃圾这个问题与lsusb -v,我将对它进行包装。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-04-29 11:26:28

通常,请求/响应通信的工作方式如下:

  1. 提交答复URB;
  2. 提交申请市建局;
  3. 在请求完成处理程序中,如果请求没有实际发送,则取消响应URB并中止;
  4. 在响应完成处理程序中,处理响应数据。

如果您有一个几乎立即完成的单个URB,那么所有这些异步完成处理程序都是一个大麻烦;因此,有一个同步工作的助手函数usb_interrupt_msg()

用于轮询的URBs必须重新提交(通常来自完成处理程序)。如果不重新提交URB,则不会发生轮询。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16255017

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档