简体   繁体   English

如何在Linux中获取USB的城市信息

[英]how to get usb's urb info in linux

I'm try to get usb stick's urb info. 我正在尝试获取USB随身听的城市信息。 And I write like follows: 我的写法如下:

#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;
}

I can compile it. 我可以编译它。 But when I run it it said that Invalid argument. 但是当我运行它时,它说无效参数。 So, what's wrong with me? 那我怎么了

I ended up with a similar problem - so here are my notes... Besides the problems pointed out so far in comments, I think the main issues with the OP code are: 我最终遇到了类似的问题-所以这里是我的笔记...除了到目前为止在注释中指出的问题之外,我认为OP代码的主要问题是:

  1. You cannot just "reap" a URB; 您不能只是“收获” URB; you first have to "submit" a (read or write) URB, then you "reap" it 您必须先“提交”(读或写)URB,然后再“获取”
  2. You cannot just open a file string that you got as path from command line arguments ( argv[1] ), and obtain a file descriptor valid for URB ioctl 您不能只open从命令行参数( argv[1] )作为路径获取的file字符串,并获得对URB ioctl有效的文件描述符。

As for 1, see maybe c - User mode USB isochronous transfer from device-to-host 至于1,请参阅c-从设备到主机的用户模式USB同步传输

Also, once I have filled this structure am I right in thinking I need to call the following: 另外,一旦我填写了这个结构,我就认为我需要调用以下内容:
int retSubmit = ioctl( fd, USBDEVFS_SUBMITURB, &usbRequest );
and then once submitted I can wait for the request to complete using 然后提交后,我可以等待请求完成使用
USBDEVFS_REAPURBNDELAY

or '[Linux-usb-users] usbfs urb reap problem.' “ [Linux-usb-users] usbfs urb收获问题”。 - MARC -MARC

The routine, and the call to it, whidch I use to submit the URB are as follows: 我用来提交URB的例程以及对它的调用如下:
... ...
Submitting the URB works fine. 提交URB可以正常工作。 This is how I try to reap it: 这是我尝试获得的方式:
... ...

linux.usb.devel - Re: usbdevfs questions (and others... ) - msg#00167 linux.usb.devel-Re:usbdevfs问题(及其他...)-msg#00167

Yes, you submit a BULK type usbdevfs_urb to the interrupt endpoint. 是的,您向中断端点提交了BULK类型的usbdevfs_urb。 It gets one packet of data. 它获取一个数据包。 You can submit multiple ones that will queue up. 您可以提交多个将排队的请求。 and I'm guessing 'reap' is REAd Pointer, not like the grim reaper (although maybe it is...:) 而且我猜'reap'是REAd Pointer,不像死神(尽管也许是... :)

I think (but I'm not sure 100%) that "submit" and "reap" are equivalent to "submit" and "completion" as noted in Virtual USB Analyzer - Tutorial . 认为 (但我不确定100%)“提交”和“收获”等同于Virtual USB Analyzer-Tutorial中指出的“提交”和“完成”。

As far as the 2. goes - it depends on the kind of the device. 就2.而言-它取决于设备的类型。 For instance, if you connect an Arduino Duemillanove, which has an FT232 USB serial chip, to a Linux PC - that will automatically load the ftdi_sio kernel driver, which in turn loads usbserial driver, which then creates the file (device node) /dev/ttyUSB0 . 例如,如果将具有FT232 USB串行芯片的Arduino Duemillanove连接到Linux PC,它将自动加载ftdi_sio内核驱动程序,该驱动程序又加载usbserial驱动程序,然后创建文件(设备节点) /dev/ttyUSB0 Thus, Linux would see this file, at best, as a plain serial port - not something necessarily related to a URB request (I guess something similar goes for USB flash thumbdrives); 因此,Linux最多只能将此文件视为一个普通的串行端口-不一定与URB请求有关(我想USB闪存指驱动器也有类似的情况)。 and I was getting the same error as OP, when trying to call the OP code with an argument of /dev/ttyUSB0 . 当尝试使用参数/dev/ttyUSB0调用OP代码时,出现了与OP相同的错误。

Obtaining this file descriptor is somewhat difficult, as it's kinda hard to track down examples: 获取此文件描述符有些困难,因为很难找到示例:

'Re: Accessing usb devices with USBDEVFS' - MARC “回复:使用USBDEVFS访问USB设备”-MARC

On Fri, May 05, 2006 at 04:45:30PM -0400, Danny Budik wrote: Danny Budik在2006年5月5日星期五04:45:30 PM -0400写道:
> How do I use the "raw" usbfs? >如何使用“原始” USBFS? I tried reading from the /dev/bus/usb file 我尝试从/ dev / bus / usb文件读取
> and got a bind - address already in use error. >并得到一个绑定-地址已在使用中错误。

Look at how libusb is implemented for a good example of how to do this. 查看如何实现libusb,以获取有关如何执行此操作的良好示例。
The source code to 'lsusb' will also help you out here. “ lsusb”的源代码也将在这里为您提供帮助。

Linux Kernel Documentation/usb/proc_usb_info.txt Linux内核文档/usb/proc_usb_info.txt

NOTE : The filesystem has been renamed from "usbdevfs" to 注意 :文件系统已从“ usbdevfs”重命名为
"usbfs", to reduce confusion with "devfs". “ usbfs”,以减少与“ devfs”的混淆。 You may 你可以
still see references to the older "usbdevfs" name. 仍然可以看到对较早的“ usbdevfs”名称的引用。

I basically started from the code in [Discuss-gnuradio] New implementation for fusb_linux without allocs/frees , and tried to modify the OP code so it works with an Arduino Duemillanove. 我基本上是从[Discuss-gnuradio]不带allocs / frees的fusb_linux的新实现中的代码开始的,并尝试修改OP代码,使其可与Arduino Duemillanove一起使用。 The problem is that it uses the older libusb-0.1 code, which has some different names of headers and functions; 问题在于它使用了较旧的libusb-0.1代码,该代码具有一些不同的标题和函数名称。 eg libusb-0.1 has libusb/usbi.h , while the newer libusb-1.0 has libusb/libusbi.h . 例如libusb-0.1具有libusb / usbi.h ,而较新的libusb-1.0具有libusb / libusbi.h In essence, libusb functions can be used to obtain the proper file descriptor. 本质上, libusb函数可用于获取正确的文件描述符。

The modified OP code is below, let's say we call it testu.c . 修改后的OP代码如下,假设我们将其testu.c I've tested it on Ubuntu Natty - first, connect the Arduino Duemillanove, which hooks the ftdi_sio driver (this can be checked in terminal with tail -f /var/log/syslog ). 我已经在Ubuntu Natty上对其进行了测试-首先,连接挂接ftdi_sio驱动程序的Arduino Duemillanove(可以在终端中使用tail -f /var/log/syslog进行检查)。 So, to begin with, remove the auto-hooked driver ( libusb doesn't need it to talk to the device, and it's possible it could interfere; note after removal, /dev/ttyUSB0 file doesn't exist anymore): 因此,首先,删除自动挂钩的驱动程序( libusb不需要它与设备对话,并且很可能会干扰;注意删除后, /dev/ttyUSB0文件不再存在):

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

Then, we will use the USB vendor/product ID to connect to the device via libusb ; 然后,我们将使用USB供应商/产品ID通过libusb连接到设备; to find it, use lsusb : 要找到它,请使用lsusb

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

The VID:PID 0403:6001 is hardcoded in testu.c ; VID:PID 0403:6001testu.c硬编码; then we can build and run it. 然后我们可以构建并运行它。 Note that the testu program has to be ran as root (via sudo ) - else libusb won't be able to communicate with the device: 请注意, 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.

The code submits a write request (on endpoint 0x02), then reaps it - and I can see the RX led blink on the Arduino - meaning some data does get to it, as expected. 代码提交了一个写请求(在端点0x02上),然后重新获得了请求-我可以看到Arduino上的RX led闪烁-意味着确实有一些数据到达了它。 However, not much more than that happens - so I'm not sure if the code answers the "get usb's urb info" part :) However, it does show how the file descriptor can be obtained, so the raw ioctl s can work - albeit via libusb (you'd probably have to dig deeper through the libusb source, in order to do the same without libusb). 但是,发生的事情并不多-所以我不确定代码是否回答了“获取usb的urb信息”部分:)但是,它确实显示了如何获取文件描述符,因此原始ioctl可以工作-尽管可以通过libusb (您可能必须深入研究libusb源代码,才能在没有libusb的情况下进行相同的操作)。

Here is testu.c (note, install the libusb-dev package so it can compile): 这是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;
}

Well, hope this helps someone, 好吧,希望这对某人有帮助,
Cheers! 干杯!

By carefully checking your USB requests won't interfere with the kernel driver, you can perform such requests without detaching the kernel driver. 通过仔细检查USB请求不会干扰内核驱动程序,您可以执行这些请求而无需分离内核驱动程序。 But the libusb workflow imposes claiming the device and thus detaching its non-usb sub kernel driver. 但是libusb工作流程强加了对设备的所有权,因此分离了其非usb子内核驱动程序。 So you need to perform the usb ioctls yourself. 因此,您需要自己执行USB ioctl

Here is an example of sending a USB control message to a FTDI USB device in order to flush its RX and TX FIFOs, without having to detach the ftdi_sio kernel driver. 这是向FTDI USB设备发送USB控制消息以刷新其RX和TX FIFO的示例,而不必分离ftdi_sio内核驱动程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM