/install/lib/pkgconfig/libusb.pc, 内容如下:
prefix=/home/xxg/libusb-0.1.12/install
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libusb
Description: USB access library
Version: 0.1.12
Libs: -L${libdir} -lusb
Cflags: -I${includedir}
一 libusb 介绍
libusb 设计了一系列的外部API 为应用程序所调用,通过这些API应用程序可以操作硬件,从libusb的源代码可以看出,这些API 调用了内核的底层接口,和kernel driver中所用到的函数所实现的功能差不多,只是libusb更加接近USB 规范。使得libusb的使用也比开发内核驱动相对容易的多。
一些重要的数据结构:
-
struct usb_dev_handle {
-
int fd;
-
struct usb_bus *bus;
-
struct usb_device *device;
-
int config;
-
int interface;
-
int altsetting;
-
void *impl_info;
-
};
-
-
struct usb_device {
-
struct usb_device *next, *prev;
-
char filename[PATH_MAX + 1];
-
struct usb_bus *bus;
-
struct usb_device_descriptor descriptor;
-
struct usb_config_descriptor *config;
-
void *dev; /* Darwin support */
-
};
-
-
struct usb_bus {
-
struct usb_bus *next, *prev;
-
char dirname[PATH_MAX + 1];
-
struct usb_device *devices;
-
};
二 libusb 的外部接口
2.1 初始化设备接口
这些接口也可以称为核心函数,它们主要用来初始化并寻找相关设备。
usb_init
函数定义: void usb_init(void);
从函数名称可以看出这个函数是用来初始化相关数据的,这个函数大家只要记住必须调用就行了,而且是一开始就要调用的.
usb_find_busses
函数定义: int usb_find_busses(void);
寻找系统上的usb总线,任何usb设备都通过usb总线和计算机总线通信。进而和其他设备通信。此函数返回总线数。
usb_find_devices
函数定义: int usb_find_devices(void);
寻找总线上的usb设备,这个函数必要在调用usb_find_busses()后使用。以上的三个函数都是一开始就要用到的,此函数返回设备数量。
usb_get_busses
函数定义: struct usb_bus *usb_get_busses(void);
这个函数返回总线的列表,在高一些的版本中已经用不到了,这在下面的实例中会有讲解
2.2 操作设备接口
usb_open
函数定义: usb_dev_handle *usb_open(struct *usb_device dev);
打开要使用的设备,在对硬件进行操作前必须要调用usb_open 来打开设备,这里大家看到有两个结构体 usb_dev_handle 和 usb_device 是我们在开发中经常碰到的,有必要把它们的结构看一看。在libusb 中的usb.h和usbi.h中有定义。
这里我们不妨理解为返回的 usb_dev_handle 指针是指向设备的句柄,而行参里输入就是需要打开的设备。
usb_close
函数定义: int usb_close(usb_dev_handle *dev);
与usb_open相对应,关闭设备,是必须调用的, 返回0成功,<0 失败。
usb_set_configuration
函数定义: int usb_set_configuration(usb_dev_handle *dev, int configuration);
设置当前设备使用的configuration,参数configuration 是你要使用的configurtation descriptoes中的bConfigurationValue, 返回0成功,<0失败( 一个设备可能包含多个configuration,比如同时支持高速和低速的设备就有对应的两个configuration,详细可查看usb标准)
usb_set_altinterface
函数定义: int usb_set_altinterface(usb_dev_handle *dev, int alternate);
和名字的意思一样,此函数设置当前设备配置的interface descriptor,参数alternate是指interface descriptor中的bAlternateSetting。返回0成功,<0失败
usb_resetep
函数定义: int usb_resetep(usb_dev_handle *dev, unsigned int ep);
复位指定的endpoint,参数ep 是指bEndpointAddress,。这个函数不经常用,被下面介绍的usb_clear_halt函数所替代。
usb_clear_halt
函数定义: int usb_clear_halt (usb_dev_handle *dev, unsigned int ep);
复位指定的endpoint,参数ep 是指bEndpointAddress。这个函数用来替代usb_resetep
usb_reset
函数定义: int usb_reset(usb_dev_handle *dev);
这个函数现在基本不怎么用,不过这里我也讲一下,和名字所起的意思一样,这个函数reset设备,因为重启设备后还是要重新打开设备,所以用usb_close就已经可以满足要求了。
usb_claim_interface
函数定义: int usb_claim_interface(usb_dev_handle *dev, int interface);
注册与操作系统通信的接口,这个函数必须被调用,因为只有注册接口,才能做相应的操作。
Interface 指 bInterfaceNumber. (下面介绍的usb_release_interface 与之相对应,也是必须调用的函数)
usb_release_interface
函数定义: int usb_release_interface(usb_dev_handle *dev, int interface);
注销被usb_claim_interface函数调用后的接口,释放资源,和usb_claim_interface对应使用。
2.3 控制传输接口
usb_control_msg
函数定义:int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout);
从默认的管道发送和接受控制数据
usb_get_string
函数定义: int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf, size_t buflen);
usb_get_string_simple
函数定义: int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf, size_t buflen);
usb_get_descriptor
函数定义: int usb_get_descriptor(usb_dev_handle *dev, unsigned char type, unsigned char index, void *buf, int size);
usb_get_descriptor_by_endpoint
函数定义: int usb_get_descriptor_by_endpoint(usb_dev_handle *dev, int ep, unsigned char type, unsigned char index, void *buf, int size);
2.4 批传输接口
usb_bulk_write
函数定义: int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
usb_interrupt_read
函数定义: int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
2.5 中断传输接口
usb_bulk_write
函数定义: int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
usb_interrupt_read
函数定义: int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
C代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "usb.h"
#define IDVENDOR 0x0483
#define IDPRODUCT 0xD0D0 //ST公司的CR95HF
#define DEBUGP printf
//------------------------------------------------------------------
// handles to USB ports
#define MAX_PORTNUM 16
struct usb_dev_handle* usbhnd[MAX_PORTNUM];
struct usb_device *usb_dev_list[MAX_PORTNUM];
int usb_num_devices = -1;
int g_portnum = 0;
// Initialize the USB system
static char USBInit(void)
{
struct usb_bus *bus;
struct usb_device *dev;
static int USBInitDone = 0;
int i, iret = 0;
if (USBInitDone != 0) return 0;
// initialize USB subsystem
usb_init();
usb_set_debug(0);
usb_find_busses();
usb_find_devices();
for (i=0; inext) {
for (dev = bus->devices; dev; dev = dev->next) {
DEBUGP("%s/%s %04X/%04X\n", bus->dirname, dev->filename,
dev->descriptor.idVendor, dev->descriptor.idProduct);
if (dev->descriptor.idVendor == IDVENDOR && dev->descriptor.idProduct == IDPRODUCT) {
DEBUGP("Find device \n");
usbhnd[g_portnum] = usb_open(dev);
iret = 1;
if (usbhnd[g_portnum] == NULL) {
iret = 0;
}
break;
}
}
}
DEBUGP("USBInit ret = %d\n", iret);
USBInitDone = 1 ;
return iret;
}
void USBClose(int portnum)
{
usb_release_interface(usbhnd[portnum], 0);
usb_close(usbhnd[portnum]);
usbhnd[portnum] = NULL;
}
int main(void)
{
int iret;
iret = USBInit();
if (iret) {
USBClose(g_portnum);
}
return 1;
}
WR703N上运行结果:
root@OpenWrt:/xutest# ./libusbtest
001/005 04FA/2490
001/002 1A40/0101
001/001 1D6B/0002
root@OpenWrt:/xutest# ./libusbtest
libusb demo begin, qiushui_007 test ok
001/005 04FA/2490
001/002 1A40/0101
001/001 1D6B/0002
USBInit ret = 0
root@OpenWrt:/xutest# ./libusbtest
libusb demo begin, qiushui_007 test ok
001/006 0483/D0D0
Find device
USBInit ret = 1
root@OpenWrt:/xutest# ./libusbtest
Segmentation fault
root@OpenWrt:/xutest# ./libusbtest
libusb demo begin, qiushui_007 test ok
001/006 0483/D0D0
Find device
USBInit ret = 1
另: 封装了lua的运行结果
root@OpenWrt:/xutest# lua testow.lua
a bc d , len = 9 a bc d, len = 6
1B 4C 75 61 51 00 01 02 03 04 07 08 12
1B 4C 75 61 51 00 00 04 04 04 08 04 false 12
13 27 Lua 81 0 0 4 4 4 8 4
A1 B0 B9 12 12 B9 B0 A1 12 B9 B0 A1
13 314159265 314159265 314159265
313233343536, crc8_hex = 0xEC
array = F1 F2 F3 F4 F5 F6
crc8 = 0x45
owAcquireEx_DS9490: USB
001/013 04FA/2490
Find DS2490, usb_num_devices = 0
owAcquireEx_DS9490: begin ---
owAcquireEx_DS9490: portnum = 0
read_rom = 0001804400000002
direct read rom: 0001804400000002
read_1991 = E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
read_1991_hex = E1E2E3E4E5E6E7E8E9EAEBECEDEEEF
root@OpenWrt:/xutest# ./luatest
--> Hello LUA, this is my first lua program for yingying!
--> 2
lua: crc8 = EC, 07
owAcquireEx_DS9490: USB
001/013 04FA/2490
Find DS2490, usb_num_devices = 0
owAcquireEx_DS9490: begin ---
owAcquireEx_DS9490: portnum = 0
ROM 1 = 02178145000000C3
ROM 2 = 01C1C64E1400000A
1. 源码参考: libusb-0.1.12的源码中参考 linux.c,
-
/*
-
* Linux USB support
-
*
-
* Copyright (c) 2000-2003 Johannes Erdfelt <johannes@erdfelt.com>
-
*
-
* This library is covered by the LGPL, read LICENSE for details.
-
*/
-
-
#include <stdlib.h> /* getenv, etc */
-
#include <unistd.h>
-
#include <string.h>
-
#include <stdio.h>
-
#include <fcntl.h>
-
#include <errno.h>
-
#include <sys/time.h>
-
#include <dirent.h>
-
-
#include "linux.h"
-
#include "usbi.h"
-
-
static char usb_path[PATH_MAX + 1] = "";
-
-
static int device_open(struct usb_device *dev)
-
{
-
char filename[PATH_MAX + 1];
-
int fd;
-
-
snprintf(filename, sizeof(filename) - 1, "%s/%s/%s",
-
usb_path, dev->bus->dirname, dev->filename);
-
-
fd = open(filename, O_RDWR);
-
if (fd < 0) {
-
fd = open(filename, O_RDONLY);
-
if (fd < 0)
-
USB_ERROR_STR(-errno, "failed to open %s: %s",
-
filename, strerror(errno));
-
}
-
-
return fd;
-
}
-
-
int usb_os_open(usb_dev_handle *dev)
-
{
-
dev->fd = device_open(dev->device);
-
-
return 0;
-
}
-
-
int usb_os_close(usb_dev_handle *dev)
-
{
-
if (dev->fd < 0)
-
return 0;
-
-
if (close(dev->fd) == -1)
-
/* Failing trying to close a file really isn't an error, so return 0 */
-
USB_ERROR_STR(0, "tried to close device fd %d: %s", dev->fd,
-
strerror(errno));
-
-
return 0;
-
}
-
-
int usb_set_configuration(usb_dev_handle *dev, int configuration)
-
{
-
int ret;
-
-
ret = ioctl(dev->fd, IOCTL_USB_SETCONFIG, &configuration);
-
if (ret < 0)
-
USB_ERROR_STR(-errno, "could not set config %d: %s", configuration,
-
strerror(errno));
-
-
dev->config = configuration;
-
-
return 0;
-
}
-
-
int usb_claim_interface(usb_dev_handle *dev, int interface)
-
{
-
int ret;
-
-
ret = ioctl(dev->fd, IOCTL_USB_CLAIMINTF, &interface);
-
if (ret < 0) {
-
if (errno == EBUSY && usb_debug > 0)
-
fprintf(stderr, "Check that you have permissions to write to %s/%s and, if you don't, that you set up hotplug () correctly.\n", dev->bus->dirname, dev->device->filename);
-
-
USB_ERROR_STR(-errno, "could not claim interface %d: %s", interface,
-
strerror(errno));
-
}
-
-
dev->interface = interface;
-
-
return 0;
-
}
-
-
int usb_release_interface(usb_dev_handle *dev, int interface)
-
{
-
int ret;
-
-
ret = ioctl(dev->fd, IOCTL_USB_RELEASEINTF, &interface);
-
if (ret < 0)
-
USB_ERROR_STR(-errno, "could not release intf %d: %s", interface,
-
strerror(errno));
-
-
dev->interface = -1;
-
-
return 0;
-
}
-
-
int usb_set_altinterface(usb_dev_handle *dev, int alternate)
-
{
-
int ret;
-
struct usb_setinterface setintf;
-
-
if (dev->interface < 0)
-
USB_ERROR(-EINVAL);
-
-
setintf.interface = dev->interface;
-
setintf.altsetting = alternate;
-
-
ret = ioctl(dev->fd, IOCTL_USB_SETINTF, &setintf);
-
if (ret < 0)
-
USB_ERROR_STR(-errno, "could not set alt intf %d/%d: %s",
-
dev->interface, alternate, strerror(errno));
-
-
dev->altsetting = alternate;
-
-
return 0;
-
}
-
-
/*
-
* Linux usbfs has a limit of one page size for synchronous bulk read/write.
-
* 4096 is the most portable maximum we can do for now.
-
* Linux usbfs has a limit of 16KB for the URB interface. We use this now
-
* to get better performance for USB 2.0 devices.
-
*/
-
#define MAX_READ_WRITE (16 * 1024)
-
-
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
-
int value, int index, char *bytes, int size, int timeout)
-
{
-
struct usb_ctrltransfer ctrl;
-
int ret;
-
-
ctrl.bRequestType = requesttype;
-
ctrl.bRequest = request;
-
ctrl.wValue = value;
-
ctrl.wIndex = index;
-
ctrl.wLength = size;
-
-
ctrl.data = bytes;
-
ctrl.timeout = timeout;
-
-
ret = ioctl(dev->fd, IOCTL_USB_CONTROL, &ctrl);
-
if (ret < 0)
-
USB_ERROR_STR(-errno, "error sending control message: %s", strerror(errno));
-
-
return ret;
-
}
-
-
#define URB_USERCONTEXT_COOKIE ((void *)0x1)
-
-
/* Reading and writing are the same except for the endpoint */
-
static int usb_urb_transfer(usb_dev_handle *dev, int ep, int urbtype,
-
char *bytes, int size, int timeout)
-
{
-
struct usb_urb urb;
-
int bytesdone = 0, requested;
-
struct timeval tv, tv_ref, tv_now;
-
struct usb_urb *context;
-
int ret, waiting;
-
-
/*
-
* HACK: The use of urb.usercontext is a hack to get threaded applications
-
* sort of working again. Threaded support is still not recommended, but
-
* this should allow applications to work in the common cases. Basically,
-
* if we get the completion for an URB we're not waiting for, then we update
-
* the usercontext pointer to 1 for the other threads URB and it will see
-
* the change after it wakes up from the the timeout. Ugly, but it works.
-
*/
-
-
/*
-
* Get actual time, and add the timeout value. The result is the absolute
-
* time where we have to quit waiting for an message.
-
*/
-
gettimeofday(&tv_ref, NULL);
-
tv_ref.tv_sec = tv_ref.tv_sec + timeout / 1000;
-
tv_ref.tv_usec = tv_ref.tv_usec + (timeout % 1000) * 1000;
-
-
if (tv_ref.tv_usec > 1000000) {
-
tv_ref.tv_usec -= 1000000;
-
tv_ref.tv_sec++;
-
}
-
-
do {
-
fd_set writefds;
-
-
requested = size - bytesdone;
-
if (requested > MAX_READ_WRITE)
-
requested = MAX_READ_WRITE;
-
-
urb.type = urbtype;
-
urb.endpoint = ep;
-
urb.flags = 0;
-
urb.buffer = bytes + bytesdone;
-
urb.buffer_length = requested;
-
urb.signr = 0;
-
urb.actual_length = 0;
-
urb.number_of_packets = 0; /* don't do isochronous yet */
-
urb.usercontext = NULL;
-
-
ret = ioctl(dev->fd, IOCTL_USB_SUBMITURB, &urb);
-
if (ret < 0) {
-
USB_ERROR_STR(-errno, "error submitting URB: %s", strerror(errno));
-
return ret;
-
}
-
-
FD_ZERO(&writefds);
-
FD_SET(dev->fd, &writefds);
-
-
restart:
-
waiting = 1;
-
context = NULL;
-
while (!urb.usercontext && ((ret = ioctl(dev->fd, IOCTL_USB_REAPURBNDELAY, &context)) == -1) && waiting) {
-
tv.tv_sec = 0;
-
tv.tv_usec = 1000; // 1 msec
-
select(dev->fd + 1, NULL, &writefds, NULL, &tv); //sub second wait
-
-
if (timeout) {
-
/* compare with actual time, as the select timeout is not that precise */
-
gettimeofday(&tv_now, NULL);
-
-
if ((tv_now.tv_sec > tv_ref.tv_sec) ||
-
((tv_now.tv_sec == tv_ref.tv_sec) && (tv_now.tv_usec >= tv_ref.tv_usec)))
-
waiting = 0;
-
}
-
}
-
-
if (context && context != &urb) {
-
context->usercontext = URB_USERCONTEXT_COOKIE;
-
/* We need to restart since we got a successful URB, but not ours */
-
goto restart;
-
}
-
-
/*
-
* If there was an error, that wasn't EAGAIN (no completion), then
-
* something happened during the reaping and we should return that
-
* error now
-
*/
-
if (ret < 0 && !urb.usercontext && errno != EAGAIN)
-
USB_ERROR_STR(-errno, "error reaping URB: %s", strerror(errno));
-
-
bytesdone += urb.actual_length;
-
} while ((ret == 0 || urb.usercontext) && bytesdone < size && urb.actual_length == requested);
-
-
/* If the URB didn't complete in success or error, then let's unlink it */
-
if (ret < 0 && !urb.usercontext) {
-
int rc;
-
-
if (!waiting)
-
rc = -ETIMEDOUT;
-
else
-
rc = urb.status;
-
-
ret = ioctl(dev->fd, IOCTL_USB_DISCARDURB, &urb);
-
if (ret < 0 && errno != EINVAL && usb_debug >= 1)
-
fprintf(stderr, "error discarding URB: %s", strerror(errno));
-
-
/*
-
* When the URB is unlinked, it gets moved to the completed list and
-
* then we need to reap it or else the next time we call this function,
-
* we'll get the previous completion and exit early
-
*/
-
ioctl(dev->fd, IOCTL_USB_REAPURB, &context);
-
-
return rc;
-
}
-
-
return bytesdone;
-
}
-
-
int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size,
-
int timeout)
-
{
-
/* Ensure the endpoint address is correct */
-
return usb_urb_transfer(dev, ep, USB_URB_TYPE_BULK, bytes, size,
-
timeout);
-
}
-
-
int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size,
-
int timeout)
-
{
-
/* Ensure the endpoint address is correct */
-
ep |= USB_ENDPOINT_IN;
-
return usb_urb_transfer(dev, ep, USB_URB_TYPE_BULK, bytes, size,
-
timeout);
-
}
-
-
/*
-
* FIXME: Packetize large buffers here. 2.4 HCDs (atleast, haven't checked
-
* 2.5 HCDs yet) don't handle multi-packet Interrupt transfers. So we need
-
* to lookup the endpoint packet size and packetize appropriately here.
-
*/
-
int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
-
int timeout)
-
{
-
/* Ensure the endpoint address is correct */
-
return usb_urb_transfer(dev, ep, USB_URB_TYPE_INTERRUPT, bytes, size,
-
timeout);
-
}
-
-
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
-
int timeout)
-
{
-
/* Ensure the endpoint address is correct */
-
ep |= USB_ENDPOINT_IN;
-
return usb_urb_transfer(dev, ep, USB_URB_TYPE_INTERRUPT, bytes, size,
-
timeout);
-
}
-
-
int usb_os_find_busses(struct usb_bus **busses)
-
{
-
struct usb_bus *fbus = NULL;
-
DIR *dir;
-
struct dirent *entry;
-
-
dir = opendir(usb_path);
-
if (!dir)
-
USB_ERROR_STR(-errno, "couldn't opendir(%s): %s", usb_path,
-
strerror(errno));
-
-
while ((entry = readdir(dir)) != NULL) {
-
struct usb_bus *bus;
-
-
/* Skip anything starting with a . */
-
if (entry->d_name[0] == '.')
-
continue;
-
-
if (!strchr("0123456789", entry->d_name[strlen(entry->d_name) - 1])) {
-
if (usb_debug >= 2)
-
fprintf(stderr, "usb_os_find_busses: Skipping non bus directory %s\n",
-
entry->d_name);
-
continue;
-
}
-
-
bus = malloc(sizeof(*bus));
-
if (!bus)
-
USB_ERROR(-ENOMEM);
-
-
memset((void *)bus, 0, sizeof(*bus));
-
-
strncpy(bus->dirname, entry->d_name, sizeof(bus->dirname) - 1);
-
bus->dirname[sizeof(bus->dirname) - 1] = 0;
-
-
LIST_ADD(fbus, bus);
-
-
if (usb_debug >= 2)
-
fprintf(stderr, "usb_os_find_busses: Found %s\n", bus->dirname);
-
}
-
-
closedir(dir);
-
-
*busses = fbus;
-
-
return 0;
-
}
-
-
int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices)
-
{
-
struct usb_device *fdev = NULL;
-
DIR *dir;
-
struct dirent *entry;
-
char dirpath[PATH_MAX + 1];
-
-
snprintf(dirpath, PATH_MAX, "%s/%s", usb_path, bus->dirname);
-
-
dir = opendir(dirpath);
-
if (!dir)
-
USB_ERROR_STR(-errno, "couldn't opendir(%s): %s", dirpath,
-
strerror(errno));
-
-
while ((entry = readdir(dir)) != NULL) {
-
unsigned char device_desc[DEVICE_DESC_LENGTH];
-
char filename[PATH_MAX + 1];
-
struct usb_device *dev;
-
struct usb_connectinfo connectinfo;
-
int i, fd, ret;
-
-
/* Skip anything starting with a . */
-
if (entry->d_name[0] == '.')
-
continue;
-
-
dev = malloc(sizeof(*dev));
-
if (!dev)
-
USB_ERROR(-ENOMEM);
-
-
memset((void *)dev, 0, sizeof(*dev));
-
-
dev->bus = bus;
-
-
strncpy(dev->filename, entry->d_name, sizeof(dev->filename) - 1);
-
dev->filename[sizeof(dev->filename) - 1] = 0;
-
-
snprintf(filename, sizeof(filename) - 1, "%s/%s", dirpath, entry->d_name);
-
fd = open(filename, O_RDWR);
-
if (fd < 0) {
-
fd = open(filename, O_RDONLY);
-
if (fd < 0) {
-
if (usb_debug >= 2)
-
fprintf(stderr, "usb_os_find_devices: Couldn't open %s\n",
-
filename);
-
-
free(dev);
-
continue;
-
}
-
}
-
-
/* Get the device number */
-
ret = ioctl(fd, IOCTL_USB_CONNECTINFO, &connectinfo);
-
if (ret < 0) {
-
if (usb_debug)
-
fprintf(stderr, "usb_os_find_devices: couldn't get connect info\n");
-
} else
-
dev->devnum = connectinfo.devnum;
-
-
ret = read(fd, (void *)device_desc, DEVICE_DESC_LENGTH);
-
if (ret < 0) {
-
if (usb_debug)
-
fprintf(stderr, "usb_os_find_devices: Couldn't read descriptor\n");
-
-
free(dev);
-
-
goto err;
-
}
-
-
/*
-
* Linux kernel converts the words in this descriptor to CPU endian, so
-
* we use the undocumented W character for usb_parse_descriptor() that
-
* doesn't convert endianess when parsing the descriptor
-
*/
-
usb_parse_descriptor(device_desc, "bbWbbbbWWWbbbb", &dev->descriptor);
-
-
LIST_ADD(fdev, dev);
-
-
if (usb_debug >= 2)
-
fprintf(stderr, "usb_os_find_devices: Found %s on %s\n",
-
dev->filename, bus->dirname);
-
-
/* Now try to fetch the rest of the descriptors */
-
if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG)
-
/* Silent since we'll try again later */
-
goto err;
-
-
if (dev->descriptor.bNumConfigurations < 1)
-
/* Silent since we'll try again later */
-
goto err;
-
-
dev->config = (struct usb_config_descriptor *)malloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor));
-
if (!dev->config)
-
/* Silent since we'll try again later */
-
goto err;
-
-
memset(dev->config, 0, dev->descriptor.bNumConfigurations *
-
sizeof(struct usb_config_descriptor));
-
-
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
-
unsigned char buffer[8], *bigbuffer;
-
struct usb_config_descriptor config;
-
-
/* Get the first 8 bytes so we can figure out what the total length is */
-
ret = read(fd, (void *)buffer, 8);
-
if (ret < 8) {
-
if (usb_debug >= 1) {
-
if (ret < 0)
-
fprintf(stderr, "Unable to get descriptor (%d)\n", ret);
-
else
-
fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", 8, ret);
-
}
-
-
goto err;
-
}
-
-
usb_parse_descriptor(buffer, "bbw", &config);
-
-
bigbuffer = malloc(config.wTotalLength);
-
if (!bigbuffer) {
-
if (usb_debug >= 1)
-
fprintf(stderr, "Unable to allocate memory for descriptors\n");
-
goto err;
-
}
-
-
/* Read the rest of the config descriptor */
-
memcpy(bigbuffer, buffer, 8);
-
-
ret = read(fd, (void *)(bigbuffer + 8), config.wTotalLength - 8);
-
if (ret < config.wTotalLength - 8) {
-
if (usb_debug >= 1) {
-
if (ret < 0)
-
fprintf(stderr, "Unable to get descriptor (%d)\n", ret);
-
else
-
fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", config.wTotalLength, ret);
-
}
-
-
free(bigbuffer);
-
goto err;
-
}
-
-
ret = usb_parse_configuration(&dev->config[i], bigbuffer);
-
if (usb_debug >= 2) {
-
if (ret > 0)
-
fprintf(stderr, "Descriptor data still left\n");
-
else if (ret < 0)
-
fprintf(stderr, "Unable to parse descriptors\n");
-
}
-
-
free(bigbuffer);
-
}
-
-
err:
-
close(fd);
-
}
-
-
closedir(dir);
-
-
*devices = fdev;
-
-
return 0;
-
}
-
-
int usb_os_determine_children(struct usb_bus *bus)
-
{
-
struct usb_device *dev, *devices[256];
-
struct usb_ioctl command;
-
int ret, i, i1;
-
-
/* Create a list of devices first */
-
memset(devices, 0, sizeof(devices));
-
for (dev = bus->devices; dev; dev = dev->next)
-
if (dev->devnum)
-
devices[dev->devnum] = dev;
-
-
/* Now fetch the children for each device */
-
for (dev = bus->devices; dev; dev = dev->next) {
-
struct usb_hub_portinfo portinfo;
-
int fd;
-
-
fd = device_open(dev);
-
if (fd < 0)
-
continue;
-
-
/* Query the hub driver for the children of this device */
-
if (dev->config && dev->config->interface && dev->config->interface->altsetting)
-
command.ifno = dev->config->interface->altsetting->bInterfaceNumber;
-
else
-
command.ifno = 0;
-
command.ioctl_code = IOCTL_USB_HUB_PORTINFO;
-
command.data = &portinfo;
-
ret = ioctl(fd, IOCTL_USB_IOCTL, &command);
-
if (ret < 0) {
-
/* errno == ENOSYS means the device probably wasn't a hub */
-
if (errno != ENOSYS && usb_debug > 1)
-
fprintf(stderr, "error obtaining child information: %s\n",
-
strerror(errno));
-
-
close(fd);
-
continue;
-
}
-
-
dev->num_children = 0;
-
for (i = 0; i < portinfo.numports; i++)
-
if (portinfo.port[i])
-
dev->num_children++;
-
-
/* Free any old children first */
-
free(dev->children);
-
-
dev->children = malloc(sizeof(struct usb_device *) * dev->num_children);
-
if (!dev->children) {
-
if (usb_debug > 1)
-
fprintf(stderr, "error allocating %zu bytes memory for dev->children\n",
-
sizeof(struct usb_device *) * dev->num_children);
-
-
dev->num_children = 0;
-
close(fd);
-
continue;
-
}
-
-
for (i = 0, i1 = 0; i < portinfo.numports; i++) {
-
if (!portinfo.port[i])
-
continue;
-
-
dev->children[i1++] = devices[portinfo.port[i]];
-
-
devices[portinfo.port[i]] = NULL;
-
}
-
-
close(fd);
-
}
-
-
/*
-
* There should be one device left in the devices list and that should be
-
* the root device
-
*/
-
for (i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) {
-
if (devices[i])
-
bus->root_dev = devices[i];
-
}
-
-
return 0;
-
}
-
-
static int check_usb_vfs(const char *dirname)
-
{
-
DIR *dir;
-
struct dirent *entry;
-
int found = 0;
-
-
dir = opendir(dirname);
-
if (!dir)
-
return 0;
-
-
while ((entry = readdir(dir)) != NULL) {
-
/* Skip anything starting with a . */
-
if (entry->d_name[0] == '.')
-
continue;
-
-
/* We assume if we find any files that it must be the right place */
-
found = 1;
-
break;
-
}
-
-
closedir(dir);
-
-
return found;
-
}
-
-
void usb_os_init(void)
-
{
-
/* Find the path to the virtual filesystem */
-
if (getenv("USB_DEVFS_PATH")) {
-
if (check_usb_vfs(getenv("USB_DEVFS_PATH"))) {
-
strncpy(usb_path, getenv("USB_DEVFS_PATH"), sizeof(usb_path) - 1);
-
usb_path[sizeof(usb_path) - 1] = 0;
-
} else if (usb_debug)
-
fprintf(stderr, "usb_os_init: couldn't find USB VFS in USB_DEVFS_PATH\n");
-
}
-
-
if (!usb_path[0]) {
-
if (check_usb_vfs("/dev/bus/usb")) {
-
strncpy(usb_path, "/dev/bus/usb", sizeof(usb_path) - 1);
-
usb_path[sizeof(usb_path) - 1] = 0;
-
} else if (check_usb_vfs("/proc/bus/usb")) {
-
strncpy(usb_path, "/proc/bus/usb", sizeof(usb_path) - 1);
-
usb_path[sizeof(usb_path) - 1] = 0;
-
} else
-
usb_path[0] = 0; /* No path, no USB support */
-
}
-
-
if (usb_debug) {
-
if (usb_path[0])
-
fprintf(stderr, "usb_os_init: Found USB VFS at %s\n", usb_path);
-
else
-
fprintf(stderr, "usb_os_init: No USB VFS found, is it mounted?\n");
-
}
-
}
-
-
int usb_resetep(usb_dev_handle *dev, unsigned int ep)
-
{
-
int ret;
-
-
ret = ioctl(dev->fd, IOCTL_USB_RESETEP, &ep);
-
if (ret)
-
USB_ERROR_STR(-errno, "could not reset ep %d: %s", ep,
-
strerror(errno));
-
-
return 0;
-
}
-
-
int usb_clear_halt(usb_dev_handle *dev, unsigned int ep)
-
{
-
int ret;
-
-
ret = ioctl(dev->fd, IOCTL_USB_CLEAR_HALT, &ep);
-
if (ret)
-
USB_ERROR_STR(-errno, "could not clear/halt ep %d: %s", ep,
-
strerror(errno));
-
-
return 0;
-
}
-
-
int usb_reset(usb_dev_handle *dev)
-
{
-
int ret;
-
-
ret = ioctl(dev->fd, IOCTL_USB_RESET, NULL);
-
if (ret)
-
USB_ERROR_STR(-errno, "could not reset: %s", strerror(errno));
-
-
return 0;
-
}
-
-
int usb_get_driver_np(usb_dev_handle *dev, int interface, char *name,
-
unsigned int namelen)
-
{
-
struct usb_getdriver getdrv;
-
int ret;
-
-
getdrv.interface = interface;
-
ret = ioctl(dev->fd, IOCTL_USB_GETDRIVER, &getdrv);
-
if (ret)
-
USB_ERROR_STR(-errno, "could not get bound driver: %s", strerror(errno));
-
-
strncpy(name, getdrv.driver, namelen - 1);
-
name[namelen - 1] = 0;
-
-
return 0;
-
}
-
-
int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface)
-
{
-
struct usb_ioctl command;
-
int ret;
-
-
command.ifno = interface;
-
command.ioctl_code = IOCTL_USB_DISCONNECT;
-
command.data = NULL;
-
-
ret = ioctl(dev->fd, IOCTL_USB_IOCTL, &command);
-
if (ret)
-
USB_ERROR_STR(-errno, "could not detach kernel driver from interface %d: %s",
-
interface, strerror(errno));
-
-
return 0;
-
}
2.