libusb 介绍
libusb是开源的C库,使用该库是的用户可以在应用程序中直接访问 USB 设备,无需为 USB 设备编写内核驱动。libusb支持多个平台 (Linux, window, iOS),所以可以很方便地将应用程序移植到其他平台。
linux libusb 安装
从网上下载libusb的源码,下载地址:http://www.libusb.org/, 下载后编译安装。
# tar jxvf libusb-1.0.20.tar.bz2
# cd libusb-1.0.20
# ./configure
# make
# sudo make install
ubuntu下可以通过以下命令快速安装。
sudo apt-get isntall libusb*
安装后,libusb的头文件被安装在/usr/local/include/libusb-1.0 ,链接库被安装在/usr/loacal/lib目录下。
usb bulk 传输例程
这个例程演示如何使用 libusb 库,编写 USB bulk xfer 上位机demo,可以正常接收和发送数据。注意,修改程序中的 VID 和 PID 的值和你 device 板子上所定义的一致,传输数据块的大小不要超过 device 定义的最大传输长度。
int main(void)
{
libusb_device **devs, *dev;
int ret, i;
ssize_t cnt;
usb_pro_t usb_pro;
struct libusb_device_handle *handle = NULL;
libusb_context *ctx = NULL;
ret = libusb_init(&ctx);
if (ret < 0)
return -1;
libusb_set_debug(ctx, 3);
cnt = libusb_get_device_list(NULL, &devs);
if (cnt < 0) {
printf("no usb dev on bus\r\n");
return -1;
}
i = 0;
while((dev = devs[i++]) != NULL) {
ret = libusb_get_device_descriptor(dev,&desc);
if (ret < 0) {
printf("failed to get device descriptor");
goto error;
}
if ((desc.idVendor == VID) && (desc.idProduct == PID)) {
printf("bLength: 0x%04x\r\n", desc.bLength);
printf("bDescriptorType: 0x%04x\r\n", desc.bDescriptorType);
printf("bcdUSB: 0x%04x\r\n", desc.bcdUSB);
printf("bDeviceClass: 0x%04x\r\n", desc.bDeviceClass);
printf("bDeviceSubClass: 0x%04x\r\n", desc.bDeviceSubClass);
printf("bDeviceProtocol: 0x%04x\r\n", desc.bDeviceProtocol);
printf("bMaxPacketSize0: 0x%04x\r\n", desc.bMaxPacketSize0);
printf("vendor id: 0x%04x\r\n", desc.idVendor);
printf("product id: 0x%04x\r\n", desc.idProduct);
printf("bcdDevice: 0x%04x\r\n", desc.bcdDevice);
printf("iManufacturer: 0x%04x\r\n", desc.iManufacturer);
printf("iProduct: 0x%04x\r\n", desc.iProduct);
printf("iSerialNumber: 0x%04x\r\n", desc.iSerialNumber);
printf("bNumConfigurations: 0x%04x\r\n", desc.bNumConfigurations);
}
}
handle = libusb_open_device_with_vid_pid(ctx, VID, PID);
if (handle == NULL) {
printf("cant't open device\r\n");
goto error;
} else {
printf("open device\r\n");
}
libusb_free_device_list(devs, 1);
if (libusb_kernel_driver_active(handle, 0) ==1) {
printf("kernel driver active, detach it \r\n");
if (libusb_detach_kernel_driver(handle, 0) == 0) {
printf("detached kernel driver\r\n");
}
else {
goto error;
}
}
ret = libusb_claim_interface(handle, 0);
if (ret < 0) {
printf("can't claim interface\r\n");
goto error;
} else {
printf("claimed interface\r\n");
}
char data[64];
int actual_len = 0;
int didi = 1000;
for (int i = 0; i< 1000; i++) {
memset(data, 0, sizeof(data));
/* receive data from device */
/*
ret = libusb_bulk_transfer(handle, edp2in, data, 64, &actual_len, 0);
if (actual_len = 0) {
printf("received nothing\r\n");
} else {
printf("bulk transfer: %s\r\n", data);
}
usleep(200000);
*/
char *str = "am host";
sprintf(data, "am host %d\r\n", i);
ret = libusb_bulk_transfer(handle, edp2out, data, strlen(data), &actual_len, 0);
if (actual_len != 0) {
printf("send data: %s\r\n", data);
}
usleep(200000);
}
libusb_close(handle);
error:
printf("free device list\r\n");
libusb_free_device_list(devs, 1);
libusb_exit(NULL);
return 0;
}
- 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
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 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
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
编译
编译代码可以使用 makefile 文件,也可以是使用命令行命令编译,这里给出两种编译方法。
CC = gcc
# your libusb library path, be careful your path.
LDIR = /usr/loacal/lib
# link flag
LFLAG = -lusb-1.0
# libusb hearder file path
INCLUDES = /usr/local/include/libusb-1.0
CFLAGS = -I$(INCLUDES) -std=c99
src = $(wildcard *.c)
obj = $(patsubst %.c, %.o, $(src))
.PHONY: all clean
all: main
main: $(obj)
$(CC) $(obj) -o main -L$(LDIR) $(LFLAG)
%.o:%.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
@-rm -f main $(obj)
- 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
- 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
- 命令行编译
命令中-I/usr/local/include/libusb-1.0 告诉编译器 libusb 的头文件所在的路径。-L/usr/local/lib/ 告诉链接器所要链接的库文件路径。-lusb-1.0 告诉编译器需要链接 libusb-1.0.so这个库。
gcc -I/usr/local/include/libusb-1.0 -std=c99 main.c -o main -L/usr/local/lib/ -lusb-1.0
运行
编译后会在当前目录下生成一个名叫“main“的可执行文件,运行这个文件。如果打开USB设备时出错提示permission error,那么使用
# sudo ./main
运行后,HOST每隔200ms 向 device 发送一个数据包。
源码下载
我的源码已上传到http://download.csdn.net/detail/chengwenyang/9479835 ,包含STM32F4Discovery板子的 usb bulk 传输的工程文件和 使用 libusb 编写的上位机程序。