四联光电智能照明论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2483|回复: 0
打印 上一主题 下一主题

Libusb简介及例子

[复制链接]
  • TA的每日心情
    开心
    2018-12-28 16:25
  • 817

    主题

    1556

    帖子

    1万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    14941
    跳转到指定楼层
    楼主
    发表于 2016-11-22 19:49:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    Libusb据说在Mac,Linux,Windows跨平台的。目前为止我还没有在除Linux平台外的其它平台测试 。回归重点,用通俗语言介绍一下我最近了解的,一般的usb设备驱动是在按照通常的在内核中基于usb通信,为用户空间展示一个设备节点的方式实现。这个确实是遵守了unix世界的“一切皆为文件”的理论。这个看起来是皆大欢喜的事情,其实则不然,在有USB子系统行业标准(说人话就是usb协议中已经统一的通信方式)的时候一切都好办,这种情况如printer etc。但是正如你所了解的一样,标准协议一般要比一个新自定义协议出现要晚好几年,甚至有可能永久都出现不了。所以如果要实现这种协议一般会在USB设备的已经接口0额外的接口1(注:此处的接口并非物理上的接口)用于实现自己的协议。

    说的这么绕,就是为了说明这种情况存在的必然性。对于这种新的问题,有两种方案解决1是写内核驱动为用户空间提供一个设备节点;2就是在用户空间直接进行usb通信,抛开设备节点。当然这两种情况不能同时存在,使用2方法的时候,设备节点会自然消失。

    这种新的协议的问题一般是采用后者来实现,因为内核主线是不会采纳不通用的驱动代码的。所以为了不一直为所有的版本内核都添加自己的驱动,可以在用户空间直接USB通信。这才是大家都好的结局。

    这个时候大家猛然发现已经在内核中实现的基于printer协议的打印驱动程序也可以采用这个方法直接在用户空间USB通信实现,这样就可以完全和系统无关了,内核只要有usb通信协议就好了。上半场已经捋顺了,下面说说下半场。

    方向明确了,如何实现,这时候大家发现了libusb,libusb可以实现用户空间直接和usb设备直接通信。这样大家都采用了基于libusb的免驱模式,如实说就是免掉内核中的驱动模式。

    另外关于开源问题,以上说的和开源没有太大关系,重点是一段代码可以在多个平台运行的便利性和且不会对Linux内核的版本变化纠结。比如有名的例子主是hp公司的开源的hplip--linux平台的打印机驱动程序,它正是我说的情况。

    不过,用户支持libusb的usbfs在内核中的配置项被加上了一个DEPRECATED标识,这说明了什么,暂时还不行而知。(20141228更新:原因是安全见这里Enable support for Linux systems without either usbfs or udev,不过也有相对的解决方案)

    铺垫完了,回归正题。

    1.介绍
       官网: http://www.libusb.org/
       Lisbusbx之前是lisbusb一个分支,现在已经合并到Libusb上了。

    2.使用方法
       Ubuntu上安装方法:sudo apt-get install libusb-1.0-0-dev
       头文件 <libusb-1.0/libusb.h>
       链接库 -lusb-1.0
       关于api,由于网上的例子鱼龙混杂,这里说明一下1.0版本的api都是以libusb_开头的.

    3.例子

    如果如下例子可以编译过,说明环境没有问题了

    1. #include <unistd.h>  
    2. #include <stdio.h>  
    3. #include <libusb-1.0/libusb.h>  
    4.   
    5. // First, use "lsusb" see vid and pid.  
    6. // there is my printer(hp deskjet 1010) vid and pid.  
    7. #define VID 0x03f0  
    8. #define PID 0xb511  
    9.   
    10. static int device_satus(libusb_device_handle *hd)  
    11. {  
    12.   
    13.     int interface = 0;  
    14.     unsigned char byte;  
    15.     libusb_control_transfer(hd, LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,  
    16.             LIBUSB_REQUEST_CLEAR_FEATURE,  
    17.             0,  
    18.             interface,  
    19.             &byte, 1, 5000);  
    20.   
    21.     printf("status:0x%x\n", byte);  
    22. /**
    23. * byte
    24. * normal:0x18
    25. * other :0x10
    26. */  
    27.     return 0;  
    28. }  
    29.   
    30. int main() {  
    31.     libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices  
    32.     libusb_device_handle *dev_handle; //a device handle  
    33.     libusb_context *ctx = NULL; //a libusb session  
    34.     int r; //for return values  
    35.     ssize_t cnt; //holding number of devices in list  
    36.     r = libusb_init(&ctx); //initialize the library for the session we just declared  
    37.     if(r < 0) {  
    38.         perror("Init Error\n"); //there was an error  
    39.         return 1;  
    40.     }  
    41.     libusb_set_debug(ctx, LIBUSB_LOG_LEVEL_INFO); //set verbosity level to 3, as suggested in the documentation  
    42.   
    43.     cnt = libusb_get_device_list(ctx, &devs); //get the list of devices  
    44.     if(cnt < 0) {  
    45.         perror("Get Device Error\n"); //there was an error  
    46.         return 1;  
    47.     }  
    48.     printf("%d Devices in list.\n", cnt);  
    49.   
    50.     dev_handle = libusb_open_device_with_vid_pid(ctx, VID, PID); //these are vendorID and productID I found for my usb device  
    51.     if(dev_handle == NULL)  
    52.         perror("Cannot open device\n");  
    53.     else  
    54.         printf("Device Opened\n");  
    55.     libusb_free_device_list(devs, 1); //free the list, unref the devices in it  
    56.   
    57.     if(libusb_kernel_driver_active(dev_handle, 0) == 1) { //find out if kernel driver is attached  
    58.         printf("Kernel Driver Active\n");  
    59.         if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it  
    60.             printf("Kernel Driver Detached!\n");  
    61.     }  
    62.     r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the first) of device (mine had jsut 1)  
    63.     if(r < 0) {  
    64.         perror("Cannot Claim Interface\n");  
    65.         return 1;  
    66.     }  
    67.     printf("Claimed Interface\n");  
    68.   
    69.     device_satus(dev_handle);  
    70.   
    71.     libusb_close(dev_handle); //close the device we opened  
    72.     libusb_exit(ctx); //needs to be called to end the  
    73.   
    74.     return 0;  
    75. }  
    复制代码


    以上是一个简单的程序。获取打印机部分状态。

    另外,PC上的lsusb命令也是基于libusb-1.0的一个应用程序:


    1. $ ldd /usr/bin/lsusb  
    2.     linux-gate.so.1 =>  (0xb76fc000)  
    3.     libusb-1.0.so.0 => /lib/i386-linux-gnu/libusb-1.0.so.0 (0xb76ca000)  
    4.                   ......  
    5. $  
    复制代码


    源码:http://dist.momonga-linux.org/pu ... ibusb-0.1.10.tar.gz
    http://sourceforge.net/projects/libusb/files/libusb-1.0/
    关于libusb for Android见:https://github.com/libusb/libusb/blob/master/android/README
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|Silian Lighting+ ( 蜀ICP备14004521号-1 )

    GMT+8, 2024-5-16 01:47 , Processed in 1.093750 second(s), 23 queries .

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表