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

mad*_*per 2 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;
}
Run Code Online (Sandbox Code Playgroud)

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

sda*_*aau 5

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

  1. 你不能只是"收获"URB; 你首先必须"提交"一个(读或写)URB,然后你"收获"它
  2. 您不能只是从命令行参数()获取路径openfile字符串argv[1],并获取对URB有效的文件描述符ioctl

至于1,请参阅c - 用户模式从设备到主机的USB等时传输

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

'[Linux-usb-users] usbfs urb收获问题. - MARC

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

linux.usb.devel - Re:usbdevfs问题(和其他人......) - 消息#00167

是的,您向中断端点提交了BULK类型usbdevfs_urb.它获取一个数据包.您可以提交多个将排队的.而且我猜'收获'是REAd指针,不像死神(虽然也许是...... :)

认为(但我不确定100%)"提交"和"收获"等同于"提交"和"完成",如虚拟USB分析器 - 教程中所述.

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

获取此文件描述符有点困难,因为它很难跟踪示例:

'Re:使用USBDEVFS访问USB设备' - MARC

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

看看如何实现libusb,以获得如何执行此操作的良好示例.
'lsusb'的源代码也会帮助你.

Linux内核文档/ usb/proc_usb_info.txt

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

我基本上从[Discuss-gnuradio] fusb_linux的新实现中的代码开始,没有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
Run Code Online (Sandbox Code Playgroud)

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

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

VID:PID 0403:6001是硬编码的testu.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.
Run Code Online (Sandbox Code Playgroud)

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

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

#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 *)

#include <libusb.h>

struct libusb_device_handle *d_udh = NULL;


// [http://www.mail-archive.com/discuss-gnuradio@gnu.org/msg17549.html [Discuss-gnuradio] New implementation for fusb_linux without allocs/frees]
static int
fd_from_usb_dev_handle (libusb_device_handle *udh) //(usb_dev_handle *udh)
{
  return *((int *) udh);
}

//~ ./libusb/os/linux_usbfs.c
struct linux_device_handle_priv {
  int fd;
};

//~ ./libusb/libusbi.h
#define usbi_mutex_t                    pthread_mutex_t
struct list_head {
        struct list_head *prev, *next;
};
struct libusb_device_handle {
        /* lock protects claimed_interfaces */
        usbi_mutex_t lock;
        unsigned long claimed_interfaces;

        struct list_head list;
        struct libusb_device *dev;
        unsigned char os_priv[0];
};

//~ ./libusb/os/linux_usbfs.c
struct linux_device_handle_priv* _device_handle_priv(
        struct libusb_device_handle *handle)
{
  struct linux_device_handle_priv* out;
  out =  (struct linux_device_handle_priv *) handle->os_priv;
  return out;
};



int main(int argc, char *argv[])
{
  int fd;
  int result;
  int i;
  struct usbdevfs_urb * receive;
  struct usbdevfs_urb * send;
  struct linux_device_handle_priv *hpriv;
  send = malloc(sizeof (struct usbdevfs_urb));
  memset(send, 0, sizeof (*send));
  send->buffer_length = 10;
  send->buffer = malloc(sizeof(unsigned char)*10);
  send->type = USBDEVFS_URB_TYPE_BULK;
  send->endpoint = 0x02;
  send->signr = 0;


  receive = malloc(sizeof (struct usbdevfs_urb));

  bzero(receive, sizeof (struct usbdevfs_urb));

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

  printf ("First\n");
  result = libusb_init(NULL);
  if (result < 0)
  {
    printf("failed to initialise libusb:\n");
  }
  d_udh = libusb_open_device_with_vid_pid(NULL, 0x0403, 0x6001);
  hpriv = _device_handle_priv(d_udh);
  printf ("Second 0x%X\n", (unsigned int)d_udh);
  result = d_udh ? 0 : -EIO;
  //~ if ((fd = open(file, O_RDWR)) < 0)
  if (result < 0)
    {
      printf("failed to open device: %s, \n error: %s \n", "0403:6001", strerror(errno)); //file
    }
  else
    {
      //~ fd = fd_from_usb_dev_handle(d_udh); // doesn't work
      fd = _device_handle_priv(d_udh)->fd;
      printf ("Open successed: Device: %s %d\n", "0403:6001", fd ); // file);
      for (i = 0; i < 10; ++i)
        {
          result = ioctl (fd, USBDEVFS_SUBMITURB, send);
            if (result < 0)
              {
                printf ("Error! USBDEVFS_SUBMITURB : ioctl returned : %d\n errno =%s\n", result, strerror(errno));
                break;
              }
          printf ("polling...\n");
          result = ioctl(fd, USBDEVFS_REAPURB, receive);
            if (result < 0)
              {
                printf ("Error! USBDEVFS_REAPURB : 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;
}
Run Code Online (Sandbox Code Playgroud)

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