我正在尝试获取USB内存棒的城市信息。我写如下:

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

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

最佳答案

我最终遇到了一个类似的问题-所以这里是我的笔记...除了到目前为止在注释中指出的问题之外,我认为OP代码的主要问题是:

  • 您不能仅仅“获得” URB;您首先必须“提交”(读或写)URB,然后再“收获”它
  • 您不能仅对从命令行参数(open)作为路径获得的file字符串进行argv[1],并获得对URB有效的文件描述符ioctl

  • 至于1,也许是c - User mode USB isochronous transfer from device-to-host



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



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



    我认为(但我不确定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



    Linux Kernel Documentation/usb/proc_usb_info.txt



    我基本上从[Discuss-gnuradio] New implementation for fusb_linux without allocs/frees中的代码开始,并尝试修改OP代码,使其可与Arduino Duemillanove一起使用。问题在于,它使用了较旧的libusb-0.1代码,该代码具有一些不同的标题和函数名称。例如libusb-0.1具有libusb/usbi.h,而较新的libusb-1.0具有libusb/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: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.
    

    代码提交了一个写入请求(在端点0x02上),然后重新获得了请求-我可以看到Arduino上的RX led闪烁-意味着确实有一些数据到达了它。但是,发生的事情并不多-所以我不确定代码是否回答了“获取USB的城市信息”部分:)。但是,它的确显示了如何获取文件描述符,因此原始ioctl可以工作-尽管通过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/[email protected]/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;
    }
    

    好吧,希望这对某人有帮助,
    干杯!

    关于c - 如何在Linux中获取USB的城市信息,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11574418/

    10-15 05:15