├── .gitignore ├── README.md └── libusb-test.c /.gitignore: -------------------------------------------------------------------------------- 1 | .tags* 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## libusb-test 2 | 3 | ### 1.compile command 4 | ``` 5 | chmod +x build.sh 6 | ./build.sh 7 | or 8 | gcc -o libusb libusb-test.c -lusb-1.0 -lpthread -lm 9 | ``` 10 | 11 | ### 2.功能 12 | - 支持bulk/interrupt endpoint 数据读写 13 | - 支持hotplug 14 | - 支持命令行参数 15 | - 支持快捷发送数据 16 | - 支持将收到的数据保存为文件 17 | - 支持'lsusb'功能,可列出系统所有usb设备 18 | - 支持打印显示特定usb设备(VID:PID)的描述符 19 | 20 | ### 3.使用实例 21 | #### 1. help 22 | ./libusb -h 23 | #### 2. list usb devices 24 | sudo ./libusb -l 25 | >bus: 001 device: 001, VID: 1d6b PID: 0002, EHCI Host Controller 26 | bus: 002 device: 064, VID: 0471 PID: 0999 27 | bus: 002 device: 003, VID: 0e0f PID: 0002 28 | bus: 002 device: 002, VID: 0e0f PID: 0003, VMware Virtual USB Mouse 29 | bus: 002 device: 001, VID: 1d6b PID: 0001, UHCI Host Controller 30 | #### 3. print descriptor 31 | sudo ./libusb -v 0471 -p 0999 -a 32 | this wil print: device descriptor,configuration descriptor, interface descriptor, endpoint descriptor. 33 | #### 4. bulk transfer 34 | sudo ./libusb -b 35 | or 36 | sudo ./libusb 37 | #### 5. interrupt transfer 38 | sudo ./libusb -i 39 | #### 6. save as file 40 | sudo ./libusb -f 41 | or 42 | sudo ./libusb -ffilepath 43 | #### 7. send data quickly 44 | enter 'test64' when the program is running. 45 | also enter test128, test200, etc. 46 | ![@send 63 bytes data quickly ](http://img.hb.aicdn.com/ab533da26e9a3d279fa59b8f2b21001ca5ea276e863b-QtoXo7_fw658) 47 | 48 | -------------------------------------------------------------------------------- /libusb-test.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * 3 | * File Name : libusb-test.c 4 | * Author : baoli 5 | * Create Date : 2017.11.21 6 | * Version : 1.0 7 | * Description : libusb test 8 | * compile command: gcc -o libusb libusb-test.c -lusb-1.0 -lpthread -lm 9 | * History : 1. Data: 10 | * Author: 11 | * Modification: 12 | * 13 | ********************************************************************************/ 14 | 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | 28 | typedef unsigned char uchar; 29 | typedef unsigned int uint; 30 | 31 | 32 | #define VID 0x0471 33 | #define PID 0x0999 34 | 35 | #define BULK_RECV_EP 0x82 36 | #define BULK_SEND_EP 0x02 37 | #define INT_RECV_EP 0x81 38 | #define INT_SEND_EP 0x01 39 | 40 | #define SEND_BUFF_LEN 500 41 | #define RECV_BUFF_LEN 500 42 | 43 | #define BULK_TEST 1 44 | #define INT_TEST 2 45 | 46 | #define SAVE_FILE_PATH "libusb_test_recv_data" 47 | 48 | 49 | sem_t print_sem; //信号量 50 | FILE *g_file_stream = NULL; 51 | int g_no_device_flag = 0; 52 | int g_file_save_en = 0; //文件保存使能标志 53 | int g_send_flag = 0; //调用数据发送函数标志 54 | 55 | uchar rev_buf[SEND_BUFF_LEN]; //usb 接收缓冲区 56 | uchar send_buf[SEND_BUFF_LEN]; //usb发送缓冲区 57 | 58 | libusb_device_handle *dev_handle; 59 | 60 | char test_bytes[] = 61 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 62 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 63 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 64 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 65 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 66 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 67 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 68 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 69 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 70 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 71 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 72 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 73 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 74 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 75 | "abcdefghijklmnopqrstuvwxyz0123456789\n" 76 | "abcdefghijklmnopqrstuvwxyz0123456789\n"; //37*15=555 bytes 77 | 78 | 79 | 80 | int bulk_send(char *buf, int num); 81 | int interrupt_send(char *buf, int num); 82 | void *bulk_rev_thread(void *arg); 83 | void *interrupt_rev_thread(void *arg); 84 | int LIBUSB_CALL usb_event_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data); 85 | void help(void); 86 | int str2hex(char *hex); 87 | void hex2str(uchar *pbDest, uchar *pbSrc, ushort nLen); 88 | void *usb_monitor_thread(void *arg); 89 | int save_to_file(FILE *file_stream, uchar *data, int length); 90 | void print_devs(libusb_device **devs); 91 | int list_devices(void); 92 | void print_endpoint(const struct libusb_endpoint_descriptor *endpoint); 93 | void print_altsetting(const struct libusb_interface_descriptor *interface); 94 | void print_interface(const struct libusb_interface *interface); 95 | void print_configuration(struct libusb_config_descriptor *config); 96 | void print_device(libusb_device *dev, struct libusb_device_descriptor *desc); 97 | int print_descriptor(libusb_device *dev); 98 | int get_descriptor_with_vid_pid(int vid, int pid); 99 | void sigint_handler(int sig); 100 | 101 | 102 | //采用bulk端点发送数据 103 | int bulk_send(char *buf, int num) 104 | { 105 | 106 | int size; 107 | int rec; 108 | 109 | g_send_flag = 1; 110 | rec = libusb_bulk_transfer(dev_handle, BULK_SEND_EP, buf, num, &size, 0); 111 | if(rec == 0) { 112 | printf("bulk send sucess,length: %d bytes\n", size); 113 | sem_post(&print_sem); 114 | } 115 | else{ 116 | g_send_flag = 0; 117 | printf("bulk send faild, err: %s\n", libusb_error_name(rec)); 118 | } 119 | 120 | return 0; 121 | 122 | } 123 | 124 | 125 | //采用interrupt端点发送数据 126 | int interrupt_send(char *buf, int num) 127 | { 128 | 129 | int size; 130 | int rec; 131 | 132 | g_send_flag = 1; 133 | rec = libusb_interrupt_transfer(dev_handle, INT_SEND_EP, buf, num, &size, 0); 134 | if(rec == 0) { 135 | printf("interrupt send sucess, length: %d bytes\n", size); 136 | sem_post(&print_sem); 137 | } 138 | else{ 139 | g_send_flag = 0; 140 | printf("interrupt send faild, err: %s\n", libusb_error_name(rec)); 141 | } 142 | 143 | return 0; 144 | 145 | } 146 | 147 | 148 | //bulk 端点接收线程 149 | void *bulk_rev_thread(void *arg) 150 | { 151 | int i=0; 152 | int size; 153 | int rec; 154 | int save_bytes; 155 | char hex_buf[RECV_BUFF_LEN*5]; 156 | 157 | printf("bulk_rev_thread started.\n"); 158 | 159 | while(1) 160 | { 161 | if(g_no_device_flag){ 162 | usleep(50 * 1000); 163 | continue; 164 | } 165 | 166 | memset(rev_buf, 0, RECV_BUFF_LEN); 167 | rec = libusb_bulk_transfer(dev_handle, BULK_RECV_EP, rev_buf, RECV_BUFF_LEN, &size, 0); 168 | if(rec == 0) 169 | { 170 | if(g_send_flag == 1) //考虑如果没有调用发送数据函数,接收到数据后调用sem_wait会一直等待直到调用了bulk_send,才会继续往下执行 171 | { 172 | g_send_flag = 0; 173 | sem_wait(&print_sem); 174 | } 175 | 176 | printf("\nbulk ep rev sucess, length: %d bytes. \n", size); 177 | 178 | if(g_file_save_en){ 179 | save_bytes = save_to_file(g_file_stream, rev_buf, size); 180 | printf("save %d bytes to file.\n", save_bytes); 181 | } 182 | 183 | hex2str(hex_buf, rev_buf, size); 184 | printf("data is: \n%s\n", rev_buf); 185 | printf("hex is: \n%s\n", hex_buf); 186 | } 187 | else 188 | { 189 | printf("bulk ep rev faild, err: %s\n", libusb_error_name(rec)); 190 | if(rec == LIBUSB_ERROR_IO) 191 | g_no_device_flag = 1; //防止一直输出err 192 | } 193 | } 194 | 195 | } 196 | 197 | 198 | //interrupt 端点接收线程 199 | void *interrupt_rev_thread(void *arg) 200 | { 201 | int i=0; 202 | int size; 203 | int rec; 204 | int save_bytes; 205 | char hex_buf[RECV_BUFF_LEN*5]; 206 | 207 | printf("interrupt_rev_thread started.\n"); 208 | 209 | while(1) 210 | { 211 | if(g_no_device_flag){ 212 | usleep(50 * 1000); 213 | continue; 214 | } 215 | 216 | memset(rev_buf, 0, RECV_BUFF_LEN); 217 | rec = libusb_interrupt_transfer(dev_handle, INT_RECV_EP, rev_buf, RECV_BUFF_LEN, &size, 0); 218 | if(rec == 0) 219 | { 220 | if(g_send_flag == 1) //考虑如果没有调用发送数据函数,接收到数据后调用sem_wait会一直等待直到调用了interrupt_send,才会继续往下执行 221 | { 222 | g_send_flag = 0; 223 | sem_wait(&print_sem); 224 | } 225 | 226 | printf("\ninterrupt ep rev sucess, length: %d bytes. \n", size); 227 | 228 | if(g_file_save_en){ 229 | save_bytes = save_to_file(g_file_stream, rev_buf, size); 230 | printf("save %d bytes to file.\n", save_bytes); 231 | } 232 | 233 | hex2str(hex_buf, rev_buf, size); 234 | printf("data is: \n%s\n", rev_buf); 235 | printf("hex is: \n%s\n", hex_buf); 236 | } 237 | else 238 | { 239 | printf("interrupt ep rev faild, err: %s\n", libusb_error_name(rec)); 240 | if(rec == LIBUSB_ERROR_IO) 241 | g_no_device_flag = 1; //防止一直输出err 242 | } 243 | } 244 | 245 | 246 | } 247 | 248 | 249 | //usb hotplugin callback function 250 | int LIBUSB_CALL usb_event_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data) 251 | { 252 | struct libusb_device_descriptor desc; 253 | int r; 254 | 255 | printf("\nusb hotplugin event.\n"); 256 | 257 | r = libusb_get_device_descriptor(dev, &desc); 258 | if (LIBUSB_SUCCESS != r) { 259 | printf("error getting device descriptor.\n"); 260 | } 261 | 262 | if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) { 263 | printf("usb device attached: %04x:%04x\n", desc.idVendor, desc.idProduct); 264 | 265 | if (dev_handle) { 266 | libusb_close(dev_handle); 267 | dev_handle = NULL; 268 | } 269 | 270 | r = libusb_open(dev, &dev_handle); 271 | if (LIBUSB_SUCCESS != r) { 272 | printf ("error opening device.\n"); 273 | } 274 | else { 275 | if(libusb_kernel_driver_active(dev_handle, 0) == 1) { //find out if kernel driver is attached 276 | printf("kernel driver active\n"); 277 | if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it 278 | printf("kernel driver detach\n"); 279 | } 280 | int r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the first) of device (mine had jsut 1) 281 | if (r < 0) { 282 | printf("libusb_claim_interface failed\n"); 283 | return 0; 284 | } 285 | 286 | g_no_device_flag = 0; 287 | printf("usb device open sucess\n\n"); 288 | printf("input data to send or command:"); 289 | fflush(stdout); 290 | } 291 | } 292 | else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) { 293 | g_no_device_flag = 1; 294 | printf("usb device removed: %04x:%04x\n", desc.idVendor, desc.idProduct); 295 | if (dev_handle) { 296 | libusb_close(dev_handle); 297 | dev_handle = NULL; 298 | 299 | } 300 | } 301 | else 302 | ; 303 | 304 | return 0; 305 | } 306 | 307 | 308 | //usb hotplugin monitor thread 309 | void * usb_monitor_thread(void *arg) 310 | { 311 | printf("usb monitor thread started.\n"); 312 | 313 | int r = 0; 314 | while (1) { 315 | r = libusb_handle_events(NULL); 316 | if (r < 0) 317 | printf("libusb_handle_events() failed: %s\n", libusb_error_name(r)); 318 | } 319 | 320 | } 321 | 322 | 323 | void help(void) 324 | { 325 | printf("usage: libusb-test [-h] [-b] [-i] [-v vid] [-p pid] [-ffile_path] [-l] [-a] \n"); 326 | printf(" -h : display usage\n"); 327 | printf(" -b : test bulk transfer\n"); 328 | printf(" -i : test interrupt transfer\n"); 329 | printf(" -v : usb VID\n"); 330 | printf(" -p : usb PID\n"); 331 | printf(" -f : file path to save data\n"); 332 | printf(" -l : list usb devices\n"); 333 | printf(" -a : print descriptor for the usb(VID:PID)\n"); 334 | 335 | return; 336 | 337 | } 338 | 339 | 340 | //将char类型(0-255)的buf转换成以十六进制显示的字符串。 341 | //使用这个函数可以避免多次循环调用printf("%x", buf[i]); 提高效率,并且能避免线程切换造成输出乱序的问题。 342 | //buf={'1', '2', '3', 'a', 'b', 'c'} -> "0x31 0x32 0x33 0x61 0x62 0x63" 343 | //buf={0,1,2,3} -> "0x00 0x01 0x02 0x03" 344 | void hex2str(uchar *dest, uchar *src, ushort nLen) 345 | { 346 | int i; 347 | 348 | for (i=0; i 0x1234 or "1234" -> 0x1234 359 | int str2hex(char *hex) 360 | { 361 | int sum = 0; 362 | int tmp = 0; 363 | char hex_str[5]; 364 | 365 | if(strlen(hex) == 6) //0x1234 366 | memcpy(hex_str, &hex[2], 4); 367 | else 368 | memcpy(hex_str, hex, 4); 369 | 370 | for(int i = 0; i < 4; i++) 371 | { 372 | tmp = hex_str[i] - (((hex_str[i] >= '0') && (hex_str[i] <= '9')) ? '0' : \ 373 | ((hex_str[i] >= 'A') && (hex_str[i] <= 'Z')) ? 'A' - 10 : 'a' - 10); 374 | sum += tmp * pow(16, 3-i); 375 | } 376 | 377 | return sum; 378 | } 379 | 380 | 381 | 382 | //将接收到数据保存到文件中 383 | int save_to_file(FILE *file_stream, uchar *data, int length) 384 | { 385 | int write_num; 386 | write_num = fwrite(data, 1, length, file_stream); 387 | fputc('\n', file_stream); //为每段数据换行,方便查看 388 | fflush(file_stream); 389 | 390 | return write_num; 391 | 392 | } 393 | 394 | 395 | 396 | void print_devs(libusb_device **devs) 397 | { 398 | libusb_device *dev; 399 | int i = 0, j = 0; 400 | uint8_t path[8]; 401 | libusb_device_handle *handle = NULL; 402 | char string[256]; 403 | 404 | while ((dev = devs[i++]) != NULL) { 405 | struct libusb_device_descriptor desc; 406 | int r = libusb_get_device_descriptor(dev, &desc); 407 | if (r < 0) { 408 | printf("failed to get device descriptor\n"); 409 | return; 410 | } 411 | 412 | printf("bus: %03d device: %03d, VID: %04x PID: %04x", 413 | libusb_get_bus_number(dev), libusb_get_device_address(dev), desc.idVendor, desc.idProduct); 414 | 415 | int ret = libusb_open(dev, &handle); 416 | if (LIBUSB_SUCCESS == ret) { 417 | if (desc.iProduct) { 418 | ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, string, sizeof(string)); //显示产品信息 419 | if (ret > 0) 420 | printf(", %s", string); 421 | } 422 | 423 | } 424 | printf("\n"); 425 | 426 | if (handle) 427 | libusb_close(handle); 428 | 429 | } 430 | } 431 | 432 | //列出系统所有的USB设备. 433 | //包括:bus number. device number, vid, pid, product info 434 | int list_devices(void) 435 | { 436 | libusb_device **devs; 437 | int r; 438 | ssize_t cnt; 439 | 440 | r = libusb_init(NULL); 441 | if (r < 0) 442 | return r; 443 | 444 | cnt = libusb_get_device_list(NULL, &devs); 445 | if (cnt < 0) 446 | return (int) cnt; 447 | 448 | print_devs(devs); 449 | libusb_free_device_list(devs, 1); 450 | 451 | libusb_exit(NULL); 452 | return 0; 453 | } 454 | 455 | 456 | 457 | void print_endpoint(const struct libusb_endpoint_descriptor *endpoint) 458 | { 459 | int i, ret; 460 | 461 | printf(" Endpoint descriptor:\n"); 462 | printf(" bEndpointAddress: %02xh\n", endpoint->bEndpointAddress); 463 | printf(" bmAttributes: %02xh\n", endpoint->bmAttributes); 464 | printf(" wMaxPacketSize: %d\n", endpoint->wMaxPacketSize); 465 | printf(" bInterval: %d\n", endpoint->bInterval); 466 | printf(" bRefresh: %d\n", endpoint->bRefresh); 467 | printf(" bSynchAddress: %d\n", endpoint->bSynchAddress); 468 | 469 | } 470 | 471 | void print_altsetting(const struct libusb_interface_descriptor *interface) 472 | { 473 | int i; 474 | 475 | printf(" Interface descriptor:\n"); 476 | printf(" bInterfaceNumber: %d\n", interface->bInterfaceNumber); 477 | printf(" bAlternateSetting: %d\n", interface->bAlternateSetting); 478 | printf(" bNumEndpoints: %d\n", interface->bNumEndpoints); 479 | printf(" bInterfaceClass: %d\n", interface->bInterfaceClass); 480 | printf(" bInterfaceSubClass: %d\n", interface->bInterfaceSubClass); 481 | printf(" bInterfaceProtocol: %d\n", interface->bInterfaceProtocol); 482 | printf(" iInterface: %d\n", interface->iInterface); 483 | 484 | for (i = 0; i < interface->bNumEndpoints; i++) 485 | print_endpoint(&interface->endpoint[i]); 486 | } 487 | 488 | 489 | void print_interface(const struct libusb_interface *interface) 490 | { 491 | int i; 492 | 493 | for (i = 0; i < interface->num_altsetting; i++) 494 | print_altsetting(&interface->altsetting[i]); 495 | } 496 | 497 | void print_configuration(struct libusb_config_descriptor *config) 498 | { 499 | int i; 500 | 501 | printf(" Configuration descriptor:\n"); 502 | printf(" wTotalLength: %d\n", config->wTotalLength); 503 | printf(" bNumInterfaces: %d\n", config->bNumInterfaces); 504 | printf(" bConfigurationValue: %d\n", config->bConfigurationValue); 505 | printf(" iConfiguration: %d\n", config->iConfiguration); 506 | printf(" bmAttributes: %02xh\n", config->bmAttributes); 507 | printf(" MaxPower: %d\n", config->MaxPower); 508 | 509 | for (i = 0; i < config->bNumInterfaces; i++) 510 | print_interface(&config->interface[i]); 511 | } 512 | 513 | 514 | void print_device(libusb_device *dev, struct libusb_device_descriptor *desc) 515 | { 516 | int i; 517 | 518 | printf("Device descriptor:\n"); 519 | printf(" bDescriptorType: %d\n", desc->bDescriptorType); 520 | printf(" bcdUSB: %#06x\n", desc->bcdUSB); 521 | printf(" bDeviceClass: %d\n", desc->bDeviceClass); 522 | printf(" bDeviceSubClass: %d\n", desc->bDeviceSubClass); 523 | printf(" bDeviceProtocol: %d\n", desc->bDeviceProtocol); 524 | printf(" bMaxPacketSize0: %d\n", desc->bMaxPacketSize0); 525 | printf(" idVendor: %#06x\n", desc->idVendor); 526 | printf(" idProduct: %#06x\n", desc->idProduct); 527 | printf(" bNumConfigurations: %d\n", desc->bNumConfigurations); 528 | 529 | 530 | for (i = 0; i < desc->bNumConfigurations; i++) { 531 | struct libusb_config_descriptor *config; 532 | int ret = libusb_get_config_descriptor(dev, i, &config); 533 | if (LIBUSB_SUCCESS != ret) { 534 | printf("Couldn't retrieve descriptors\n"); 535 | continue; 536 | } 537 | 538 | print_configuration(config); 539 | libusb_free_config_descriptor(config); 540 | } 541 | } 542 | 543 | 544 | //打印USB设备的描述符 545 | int print_descriptor(libusb_device *dev) 546 | { 547 | struct libusb_device_descriptor desc; 548 | int ret, i; 549 | 550 | ret = libusb_get_device_descriptor(dev, &desc); 551 | if (ret < 0) { 552 | printf("failed to get device descriptor\n"); 553 | return -1; 554 | } 555 | 556 | print_device(dev, &desc); 557 | 558 | } 559 | 560 | 561 | //根据VID:PID,打印特定USB设备的描述符 562 | int get_descriptor_with_vid_pid(int vid, int pid) 563 | { 564 | libusb_device **devs; 565 | libusb_device *found = NULL; 566 | libusb_device *dev; 567 | ssize_t cnt; 568 | int r, i; 569 | 570 | r = libusb_init(NULL); 571 | if (r < 0) 572 | return -1; 573 | 574 | cnt = libusb_get_device_list(NULL, &devs); 575 | if (cnt < 0) 576 | return -1; 577 | 578 | while ((dev = devs[i++]) != NULL) { 579 | struct libusb_device_descriptor desc; 580 | r = libusb_get_device_descriptor(dev, &desc); 581 | if (r < 0) 582 | return -1; 583 | if (desc.idVendor == vid && desc.idProduct == pid) { 584 | found = dev; 585 | break; 586 | } 587 | } 588 | 589 | print_descriptor(found); 590 | 591 | libusb_free_device_list(devs, 1); 592 | 593 | libusb_exit(NULL); 594 | return 0; 595 | } 596 | 597 | 598 | //ctrl+c 信号处理函数 599 | void sigint_handler(int sig) 600 | { 601 | if(g_file_stream) 602 | fclose(g_file_stream); 603 | 604 | printf("\nlibusb test quit.\n"); 605 | exit(0); 606 | } 607 | 608 | 609 | 610 | int main(int argc, char **argv) 611 | { 612 | int r; 613 | int opt; 614 | int test_mode; 615 | int vid, pid; 616 | int send_length; 617 | 618 | libusb_context *ctx = NULL; 619 | 620 | struct sigaction act; 621 | 622 | pthread_t bulk_rev_thread_id; 623 | pthread_t int_rev_thread_id; 624 | pthread_t usb_monitor_thread_id; 625 | 626 | test_mode = BULK_TEST; 627 | vid = VID; 628 | pid = PID; 629 | g_file_save_en = 0; 630 | g_send_flag = 0; 631 | 632 | act.sa_handler = sigint_handler; 633 | sigemptyset(&act.sa_mask); 634 | act.sa_flags = 0; 635 | sigaction(SIGINT, &act, NULL); 636 | 637 | //命令行参数解析 638 | while((opt = getopt(argc, argv, "bif::hv:p:la")) != -1) 639 | { 640 | switch(opt) 641 | { 642 | case 'b' : 643 | test_mode = BULK_TEST; 644 | break; 645 | case 'i' : 646 | test_mode = INT_TEST; 647 | break; 648 | case 'f' : 649 | g_file_stream = fopen(optarg == NULL ? SAVE_FILE_PATH : optarg, "wb"); //写打开,并将文件长度截为0,没有则新建 650 | if(g_file_stream) 651 | g_file_save_en = 1; 652 | else 653 | perror("file open faild: "); 654 | break; 655 | case 'v' : 656 | vid = str2hex(optarg); 657 | break; 658 | case 'p' : 659 | pid = str2hex(optarg); 660 | break; 661 | case 'l' : 662 | list_devices(); 663 | exit(0); 664 | break; 665 | case 'a' : 666 | get_descriptor_with_vid_pid(vid, pid); 667 | exit(0); 668 | break; 669 | case 'h' : 670 | help(); 671 | return 0; 672 | break; 673 | default : 674 | printf("unkonw option.\n"); 675 | help(); 676 | return 0; 677 | } 678 | } 679 | 680 | 681 | printf("\nlibusb test\n"); 682 | if(test_mode == BULK_TEST) 683 | printf("test bulk transfer\n"); 684 | else if(test_mode == INT_TEST) 685 | printf("test interrupt transfer\n"); 686 | else{ 687 | printf("unkonw test mode.\n"); 688 | return 0; 689 | } 690 | printf("usb device: VID:%#06x PID:%#06x\n\n", vid, pid); //#:输出0x,06:vid或pid第一个数字为0时,输出0x0471而不是0x471 691 | 692 | r = sem_init(&print_sem, 0, 0); //初始化信号量,用于解决多线程下printf输出乱序的问题 693 | if(r != 0) 694 | perror("sem_init faild: "); 695 | 696 | r = libusb_init(&ctx); //initialize the library for the session we just declared 697 | if(r < 0) { 698 | printf("libusb init faild, err:%s\n", libusb_error_name(r)); //there was an error 699 | return -1; 700 | } 701 | 702 | libusb_set_debug(ctx, LIBUSB_LOG_LEVEL_WARNING); 703 | 704 | if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { 705 | printf("hotplug capabilites are not supported on this platform.\n"); 706 | libusb_exit (NULL); 707 | return -1; 708 | } 709 | 710 | r = libusb_hotplug_register_callback(ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_NO_FLAGS, vid, pid, LIBUSB_HOTPLUG_MATCH_ANY, usb_event_callback, NULL, NULL); 711 | if (LIBUSB_SUCCESS != r) { 712 | printf("error registering callback: %s\n", libusb_error_name(r)); 713 | libusb_exit(ctx); 714 | return -1; 715 | } 716 | 717 | dev_handle = libusb_open_device_with_vid_pid(ctx, vid, pid); //open a usb device with VID&PID 718 | if(dev_handle == NULL) { 719 | printf("cannot open device\n"); 720 | return -1; 721 | } 722 | else 723 | printf("usb device opened.\n"); 724 | 725 | r = libusb_kernel_driver_active(dev_handle, 0); 726 | if(r == 0) //ok 727 | ; 728 | else if(r == 1) { 729 | printf("Kernel driver is active, now try detached\n"); 730 | if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it 731 | printf("Kernel driver is detached!\n"); 732 | else{ 733 | printf("libusb_detach_kernel_driver, err:%s\n", libusb_error_name(r)); 734 | return -1; 735 | } 736 | } 737 | else{ 738 | printf("libusb_kernel_driver_active, err:%s\n", libusb_error_name(r)); 739 | return -1; 740 | } 741 | 742 | r = libusb_claim_interface(dev_handle, 0); //claim interface 0 ,stm32采用接口0 743 | if(r < 0) { 744 | printf("cannot claim interface, err:%s\n", libusb_error_name(r)); 745 | return -1; 746 | } 747 | 748 | //热插拔监听 749 | r = pthread_create(&usb_monitor_thread_id, 0, usb_monitor_thread, 0); 750 | if(r != 0 ) 751 | { 752 | perror("usb_monitor_thread creation faild\n"); 753 | } 754 | 755 | //new thread,usb rev data 756 | if(test_mode == BULK_TEST){ 757 | r = pthread_create(&bulk_rev_thread_id, NULL, bulk_rev_thread, NULL); 758 | if(r != 0 ) 759 | { 760 | perror("thread creation faild\n"); 761 | } 762 | } 763 | else if(test_mode == INT_TEST){ 764 | r = pthread_create(&int_rev_thread_id, NULL, interrupt_rev_thread, NULL); 765 | if(r != 0 ) 766 | { 767 | perror("thread creation faild\n"); 768 | } 769 | } 770 | 771 | 772 | while(1) 773 | { 774 | usleep(10 * 1000); 775 | printf("\ninput data to send or command:"); 776 | 777 | memset(send_buf, 0, SEND_BUFF_LEN); 778 | fgets(send_buf, SEND_BUFF_LEN, stdin); 779 | send_length = strlen(send_buf)-1; 780 | send_buf[send_length] = '\0' ; //将读入的换行符转为\0 781 | 782 | //用于快捷发送数据,如输入test64,会自动发送64字节数据,输入test100则会自动发送100字节数据 783 | if(strncmp(send_buf, "test", 4) == 0){ 784 | send_length = atoi(&send_buf[4]); 785 | if(send_length > strlen(test_bytes)){ 786 | printf("send_length:%d should less than max_length:%ld\n", send_length, strlen(test_bytes)); 787 | continue; 788 | } 789 | printf("test sending %d bytes.\n", send_length); 790 | memcpy(send_buf, test_bytes, send_length); 791 | } 792 | 793 | if(test_mode == BULK_TEST) 794 | bulk_send(send_buf, send_length); 795 | else if(test_mode == INT_TEST) 796 | interrupt_send(send_buf, send_length); 797 | else 798 | ; 799 | } 800 | 801 | } 802 | --------------------------------------------------------------------------------