zoukankan      html  css  js  c++  java
  • libusb 源码阅读

    libusb_init(NULL), 如果传入一个NULL, 则libusb 内部会有一个 usbi_default_context 变量在内部保存上下文. 这样以后调用 libusb 函数时可以不指定 context, libusb 使用默认的内部变量.

    详见 USBI_GET_CONTEXT(ctx);


    usbi_backend->init --> op_init

    查找 usbfs 根目录

    usbfs_path = find_usbfs_path();

    1. 先到 "/dev/bus/usb/" 目录下查找是否有任意有效文件(非'.'开头的隐藏文件), 如果有的话, 则 usbfs_path 为 "/dev/bus/usb"
    2. 如果没有的话, 就到 "/proc/bus/usb" 下寻找. 如果找到, 则 usbfs_path 为 "/proc/bus/usb"
    3. 如果还没有找到, 则查找 /dev/ 下的 /dev/usbdev%d.%d 格式的文件. 如果找到的话, 则 usbfs_path 为 "/dev" . 这种情况比较特殊, 会置标志 usbdev_names = 1;
    4. 如果还没找到的话, 就没办法了. 返回错误.

    比较内核版本

    libusb 里有个函数 kernel_version_ge(2,6,32), 使用 uname() 系统调用来获取当前运行内核版本信息.

    sysfs 里的 USB 信息

    遍历 "/sys/bus/usb/devices" , 找 usb 开头的目录. 这个目录表示总线. 查找其下是否有 busnum, devnum, descriptor, bConfigurationValue 等文件, 以判断其能力.

    如果 /sys 下的信息完整, 则以后就可以直接从 /sys 下读到 USB 的信息. 否则就要到上面查找出的 usbfs 里读.

    libusb 里的代码这样写, 看来整个 USB 的趋势还是倾向于到 /sys/ 下获取信息.

    usbi_io_init(ctx)

    pipe() 创建了两个管道 ctx->ctrl_pipe[2], 并把读管道加入到 poll 监听列表里.


    cnt = libusb_get_device_list(NULL, &devs);
    

    查找设备数量. 实现中是去查找 /sys/bus/devices/ 下的目录, 条件是: 非数字开头 && "usb" 字符开头 && 名字没有':' , 其下的 busnum 和 devnum 就是总线号和设备号

    每个设备用 libusb_device 结构表示, 唯一标志符是 session_id, session_id = busnum << 8 | devaddr;

    struct libusb_device {
    	/* lock protects refcnt, everything else is finalized at initialization
    	 * time */
    	usbi_mutex_t lock;
    	int refcnt;
    
    	struct libusb_context *ctx;
    
    	uint8_t bus_number;
    	uint8_t device_address;
    	uint8_t num_configurations;
    	enum libusb_speed speed;
    
    	struct list_head list;
    	unsigned long session_data;
    	unsigned char os_priv[0];
    };
    

    最后的 os_priv 会使用 initialize_device() 分配一片操作系统相关的空间给它, 以存储设备路径等信息, 在linux 下为:

    struct linux_device_priv {
    	char *sysfs_dir;
    	unsigned char *dev_descriptor;
    	unsigned char *config_descriptor;
    };
    

    int libusb_get_device_descriptor(libusb_device *dev, struct libusb_device_descriptor *desc);

    libusb_device *dev 中有所有该设备在 /sys 下的文件路径信息, 那么此函数就会读该路径下的 "descriptors" 文件, 该文件是 USB 设备描述符, 其中就存储了 vendor, producdt 等信息.


    同步IO

    控制传输, 块传输, 中断传输

    int 	libusb_control_transfer (libusb_device_handle *dev_handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout)
     	Perform a USB control transfer. 
     
    
    int 	libusb_bulk_transfer (struct libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout)
     	Perform a USB bulk transfer. 
     
    
    int 	libusb_interrupt_transfer (struct libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout)
     	Perform a USB interrupt transfer. 
    

    异步IO

  • 相关阅读:
    regedit注册表
    Environment应用
    VMI帮助类
    Image帮助类
    asp.net core+Postman
    printf和cout的区别详述
    C++指针
    Qt button和buttons区别
    visual studio收函数
    编译警告
  • 原文地址:https://www.cnblogs.com/sammei/p/4121945.html
Copyright © 2011-2022 走看看