如何在linux中获取usb的urb信息

时间:2012-07-20 07:02:42

标签: c linux usb libusb

我试着获取usb stick的urb信息。我写的如下:

#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <usb.h>
/* #include <stropts.h> */
/* #include <inttypes.h> */
#include <linux/usbdevice_fs.h>
/* #include <asm/byteorder.h> */
/* #include <linux/usb/ch9.h> */
#define USBDEVFS_REAPURB           _IOW('U', 12, void *)
int main(int argc, char *argv[])
{ 
  int fd;
  int result;
  int i;
  struct usbdevfs_urb * receive;
  receive = malloc(sizeof (struct usbdevfs_urb));

  bzero(receive, sizeof (struct usbdevfs_urb));

  char file[30];
  strncpy (file, argv[1], 30);

  if ((fd = open(file, O_RDWR)) < 0)
    {
      printf("failed to open device: %s, \n error: %s \n", file, strerror(errno));
    }
  else 
    {
      printf ("Open successed: Device: %s\n", file);
      for (i = 0; i < 1000; ++i)
        {
          printf ("polling...\n");
          result = ioctl(fd, USBDEVFS_REAPURB, receive);
            if (result < 0)
              {
                printf ("Error!  : ioctl returned : %d\n errno =%s\n", result, strerror(errno));
                break;
              }
          printf ("The %d th time ok.\n", i + 1);
          usleep(2000);
        }
    }
  close(fd);
  return 0;
}

我可以编译它。但是当我运行它时它说无效的参数。 那么,我怎么了?

2 个答案:

答案 0 :(得分:5)

我最后遇到了类似的问题 - 所以这是我的笔记......除了评论中指出的问题,我认为OP代码的主要问题是:

  1. 你不能只是“收获”URB;你首先必须“提交”一个(读或写)URB,然后你“收获”它
  2. 您不能只是open从命令行参数(file)获取的argv[1]字符串,并获取对URB ioctl有效的文件描述符
  3. 至于1,请参阅c - User mode USB isochronous transfer from device-to-host

      

    此外,一旦我填写了这个结构,我认为我需要调用以下内容:   int retSubmit = ioctl( fd, USBDEVFS_SUBMITURB, &usbRequest );
      然后一旦提交,我可以等待请求完成使用
      USBDEVFS_REAPURBNDELAY

    '[Linux-usb-users] usbfs urb reap problem.' - MARC

      

    我用来提交URB的例程和对它的调用如下:
      ...
      提交URB工作正常。这就是我试图收获它的方式:
      ......

    linux.usb.devel - Re: usbdevfs questions (and others... ) - msg#00167

      

    是的,您向中断端点提交了BULK类型usbdevfs_urb。   它获取一个数据包。你可以提交多个   排队。而且我猜'收获'是REAd Pointer,而不是严酷的   收割者(虽然可能是......)。

    认为(但我不确定100%)“提交”和“收获”等同于Virtual USB Analyzer - Tutorial中提到的“提交”和“完成”。

    就2而言 - 取决于设备的类型。例如,如果您将具有FT232 USB串行芯片的Arduino Duemillanove连接到Linux PC,它将自动加载ftdi_sio内核驱动程序,后者又加载usbserial驱动程序,然后创建文件(设备节点)/dev/ttyUSB0。因此,Linux最好将这个文件视为一个普通的串行端口 - 不一定与URB请求相关(我想类似于USB闪存驱动器的东西);当我尝试使用/dev/ttyUSB0参数调用OP代码时,我得到了与OP相同的错误。

    获取此文件描述符有点困难,因为有点难以追踪示例:

    'Re: Accessing usb devices with USBDEVFS' - MARC

      

    2006年5月5日星期五下午04:45:30 -0400,Danny Budik写道:
      &GT;我如何使用“原始”usbfs?我尝试从/ dev / bus / usb文件中读取   &GT;并得到一个绑定 - 地址已经在使用错误。

         

    了解如何实施libusb以获得如何执行此操作的良好示例   'lsusb'的源代码也会帮助你。

    Linux Kernel Documentation/usb/proc_usb_info.txt

      

    注意:文件系统已从“usbdevfs”重命名为
              “usbfs”,以减少与“devfs”的混淆。你可以           仍然可以看到旧的“usbdevfs”名称的引用。

    我基本上从[Discuss-gnuradio] New implementation for fusb_linux without allocs/frees中的代码开始,并尝试修改OP代码,以便它与Arduino Duemillanove一起使用。问题是它使用旧的libusb-0.1代码,它有一些不同的标题和函数名称;例如libusb-0.1libusb/usbi.h,而较新的libusb-1.0libusb/libusbi.h。实质上,libusb函数可用于获取正确的文件描述符。

    修改后的OP代码如下所示,我们称之为 testu.c 。我在Ubuntu Natty上进行了测试 - 首先,连接Arduino Duemillanove,它挂钩了ftdi_sio驱动程序(这可以通过tail -f /var/log/syslog在终端中检查)。因此,首先,删除自动挂钩的驱动程序(libusb不需要它与设备通信,它可能会干扰;删除后注意,/dev/ttyUSB0文件不存在再见):

    sudo modprobe -r ftdi_sio   # this also removes usbserial 
    lsmod | grep ftdi           # make sure ftdi_sio isn't listed by lsmod
    

    然后,我们将使用USB供应商/产品ID通过libusb连接到设备;要找到它,请使用lsusb

    $ lsusb | grep FT
    Bus 002 Device 005: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC
    

    VID:PID 0403:6001testu.c中被硬编码;然后我们可以构建并运行它。请注意,testu程序必须以root身份运行(通过sudo) - 否则libusb将无法与设备通信:

    $ gcc -o testu -Wall -g testu.c `pkg-config --libs --cflags libusb-1.0`
    testu.c:23:1: warning: ‘fd_from_usb_dev_handle’ defined but not used
    
    $ sudo ./testu
    First
    Second 0x8B4B4F0
    Open successed: Device: 0403:6001 6
    polling...
    The 1 th time ok.
    polling...
    The 2 th time ok.
    polling...
    The 3 th time ok.
    polling...
    The 4 th time ok.
    polling...
    The 5 th time ok.
    polling...
    The 6 th time ok.
    polling...
    The 7 th time ok.
    polling...
    The 8 th time ok.
    polling...
    The 9 th time ok.
    polling...
    The 10 th time ok.
    

    代码提交一个写请求(在端点0x02上),然后重新接收它 - 我可以看到Arduino上的RX指示灯闪烁 - 意味着一些数据确实到达了它,正如预期的那样。然而,没有比这更多 - 所以我不确定代码是否回答“获取usb的urb信息”部分:)但是,它确实显示了如何获取文件描述符,所以原始{{ 1}} s可以工作 - 尽管是通过ioctl(你可能需要深入挖掘libusb源代码,以便在没有libusb的情况下做同样的事情)。

    这是libusb(注意,安装testu.c包以便它可以编译):

    libusb-dev

    嗯,希望这有助于某人,
    干杯!

答案 1 :(得分:0)

通过仔细检查您的USB请求不会干扰内核驱动程序,您可以在不分离内核驱动程序的情况下执行此类请求。但libusb工作流程强制要求设备,从而分离其非usb子内核驱动程序。所以你需要自己执行usb ioctls

Here is an example向FTDI USB设备发送USB控制消息,以便刷新其RX和TX FIFO,而无需分离ftdi_sio内核驱动程序。