首先从官网下载源码包,目前版本是1.0.9,官网地址(http://libusb.org/)
下载后直接./configure --prefix=/yourfolder ,make,make install,即可在yourfolder下面生成两个目录include和lib,分别包含libusb.h和libusb-1.0库文件,过程很简单,不再罗嗦,此处只补充一下在交叉编译环境下configure的方法。
./configure --prefix=/yourfolder --host=arm-linux
上面蓝色的部分就是要额外指定的内容,告诉平台是arm-linux。这里我也很晕configure是怎么指向实际的gcc程序的,因为测试用的arm-gcc的完整名称是arm-linux-gnueabihf-gcc,但是在configure的时候只指定了--host=arm-linux,配置完 之后查看生成的Makefile里的CC变量,竟然自动变成了arm-linux-anueabihf-gcc,这是约定俗成的吗?为了以后不被误导,此处得记录一下编译环境为ubuntu12.04+arm-gnueabihf,是通过apt源自动安装的那种arm-gcc。
libusb包中默认包含了一个listdevs.c的示例,可以枚举系统上的所有usb设备,在编译的时候要加上参数-lpthread -lrt,然后链接刚才make出来的库文件,我将普通Linux和ArmLinux的库文件都编译了一份,方便以后使用:
1 2 3 4 5 |
$ ls ArmLinux libusb.h listdevs Makefile arm-linux-gnueabihf_listdevs Linux listdevs.c Win32 |
如上,在ArmLinux下面是Arm版本的libusb,Linux下是普通x86版本的libusb,然后做一个粗糙的Makefile,每次编译的时候只要注释掉PLATFORM,编译出来的就是x86版本的listdevs,否则就是Arm版本的listdevs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
CC=gcc #PLATFORM=arm-linux-gnueabihf LIB1=./ArmLinux/lib LIB2=./Linux/lib INC=-I. all: listdevs.c ifndef PLATFORM $(CC) -o listdevs listdevs.c $(INC) $(LIB2)/libusb-1.0.a -lpthread -lrt else ${PLATFORM}-${CC} -o ${PLATFORM}_listdevs listdevs.c $(INC) $(LIB1)/libusb-1.0.a -lpthread -lrt endif |
后来我在示例里面加了几句话,用来打印设备的iProduct信息,这样输出的结果好看一下,类似这样:
1 2 3 4 5 6 7 8 9 10 |
[root@test libusb]# ./listdevs 1d6b:0002 (bus 1, device 1) Linux 2.6.32-279.el6.i686 ehci_hcd,EHCI Host Controller 1d6b:0001 (bus 2, device 1) Linux 2.6.32-279.el6.i686 uhci_hcd,UHCI Host Controller 1d6b:0001 (bus 3, device 1) Linux 2.6.32-279.el6.i686 uhci_hcd,UHCI Host Controller 1d6b:0001 (bus 4, device 1) Linux 2.6.32-279.el6.i686 uhci_hcd,UHCI Host Controller 1d6b:0001 (bus 5, device 1) Linux 2.6.32-279.el6.i686 uhci_hcd,UHCI Host Controller 413c:2105 (bus 4, device 2) Dell,Dell USB Keyboard 1c4f:0003 (bus 4, device 3) NULL(-8),U+P Mouse |
改后的源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
/* * libusb example program to list devices on the bus * Copyright (C) 2007 Daniel Drake <dsd@gentoo.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <stdio.h> #include <sys/types.h> #include <libusb.h> static void print_devs(libusb_device **devs) { libusb_device *dev; int i = 0; char *u_manufacturer,*u_product; libusb_device_handle *dev_handle; int ret; while ((dev = devs[i++]) != NULL) { struct libusb_device_descriptor desc; int r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { fprintf(stderr, "failed to get device descriptor"); return; } u_manufacturer=(char*)calloc(1,256); u_product=(char*)calloc(1,256); ret = libusb_open(dev,&dev_handle); if(ret < 0) { sprintf(u_manufacturer,"NULL(%d)",ret); sprintf(u_product,"NULL(%d)",ret); } else { ret = libusb_get_string_descriptor_ascii(dev_handle, desc.iProduct ,u_product, 256); if(ret < 0){ sprintf(u_product, "NULL(%d)",ret); } ret = libusb_get_string_descriptor_ascii(dev_handle, desc.iManufacturer,u_manufacturer, 256); if(ret < 0){ sprintf(u_manufacturer, "NULL(%d)",ret); } libusb_close(dev_handle); } printf("%04x:%04x (bus %d, device %d) %s,%s\n", desc.idVendor, desc.idProduct, libusb_get_bus_number(dev), libusb_get_device_address(dev), u_manufacturer,u_product); free(u_manufacturer); free(u_product); } } int main(void) { libusb_device **devs; int r; ssize_t cnt; r = libusb_init(NULL); if (r < 0) return r; cnt = libusb_get_device_list(NULL, &devs); if (cnt < 0) return (int) cnt; print_devs(devs); libusb_free_device_list(devs, 1); libusb_exit(NULL); return 0; } |
额外增加了一个libusb_get_string_descriptor_ascii方法,由于没有找到libusb详细的说明,所以只能琢磨测试。不知是不是调用libusb的方法不对,输出的结果比执行lsusb得到的内容少,例如下面lsusb输出结果,内容很详细:
1 2 3 4 5 6 7 8 9 |
[root@test libusb]# lsusb Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 004 Device 002: ID 413c:2105 Dell Computer Corp. Model L100 Keyboard |
上面的代码,只能在Linux上运行,在windows环境下libusb_open会返回错误,查看网上资料也没找到有效的解决办法,有人说没安装win usb,我试了也不管用,暂且搁置,毕竟windows上随便打开设备管理器,USB设备的信息都是一览无余的。
:Makefile条件判断必须放在行首,前面不能有分隔符
:libusb里面有建好的vs2010工程,可以直接打开编译win版本的libusb