我最终遇到了类似的问题 - 所以这是我的笔记......除了评论中指出的问题之外,我认为 OP 代码的主要问题是:
- 你不能仅仅“收获”一个URB;你首先必须“提交”一个(读或写)URB,然后你“收获”它
- 您不能只是从命令行参数 ( ) 作为路径获得
open
的字符串,并获得对 URB 有效的文件描述符file
argv[1]
ioctl
至于 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 问题。” - 马克
我用来提交 URB 的例程及其调用如下:
...
提交 URB 工作正常。这就是我尝试收获它的方式:
...
linux.usb.devel - 回复:usbdevfs 问题(和其他......) - msg#00167
是的,您向中断端点提交了一个 BULK 类型的 usbdevfs_urb。它得到一包数据。您可以提交多个将排队的。我猜'reap'是读指针,不像死神(虽然也许是……:)
我认为(但我不确定 100%)如Virtual USB Analyzer - Tutorial中所述,“提交”和“收获”等同于“提交”和“完成” 。
就 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 日星期五下午 4:45:30 -0400,Danny Budik 写道:
> 如何使用“原始”usbfs?我尝试从 /dev/bus/usb 文件中读取
> 并得到一个 bind - address already in use 错误。
查看 libusb 是如何实现的,以获得如何做到这一点的一个很好的例子。
'lsusb' 的源代码也将在这里为您提供帮助。
Linux 内核文档/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.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:PID0403: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的urb信息”部分:)
但是,它确实显示了如何获取文件描述符,因此原始ioctl
s可以工作-尽管通过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;
}
好吧,希望这对某人有所帮助,
干杯!