虚拟机Linux访问usb设备,通过Libusb库方法实现读写usb设备所获取的实时图像数据

您所在的位置:网站首页 虚拟机读不到u盘 虚拟机Linux访问usb设备,通过Libusb库方法实现读写usb设备所获取的实时图像数据

虚拟机Linux访问usb设备,通过Libusb库方法实现读写usb设备所获取的实时图像数据

2024-07-11 23:14:08| 来源: 网络整理| 查看: 265

一、前言

基于Linux 平台USB驱动开发,主要有内核驱动的开发和libusb的无驱设计;首先为什么要选第三方库Libusb,可能是基于Libusb的程序只涉及到应用层,使用起来更加方便;如果是在内核驱动,就要考虑到内核大小、内核版本的兼容,如果客户需要把你的USB模块加入他们的平台,那岂不是还要重新根据客户要求裁剪、编写内核?又假如有许多客气,而且每个客气的平台不一样,那是不是需要为每个客户定制一个内核呀?所以……

记得前两天一直在搭建基于S5P4418平台Embedded arm_5.8QT和Embedded host_ 5.8QT,感触最多就是装的Linux环境和编译器版的不同,结局就可能会不同,不清楚开发环境对本文的例子的例子有多大的影响,我还是负责任地贴出我的环境,还介绍了UBS设备的连接以及库文件的安装。

环境: windows7_32bit+VMware_10.0.1_32bit+Ubuntu_12.04.5 LTS_32bit 编译器: gcc与g++ version 4.9.4 二、USB设备与虚拟机Linux的连接

USB工作模式:①存储模式,②传输模式。 要读取USB所传的实时数据,把UBS的模式设置为传输模式; 点击虚拟机的设置 至少选中上面两项_只能在ubuntu系统关机状态下更改 点击连接设备 这里写图片描述 这里写图片描述 在Linux上所读到USB的Vid与Pid值,是用来寻找相匹配的USB设备,endpoint是在传输数据时需要用到的端口。

三、第三方Libusb-1.0.9库的安装

下载源码包libusb-1.0.9.tar.bz2,用tar -xvf命令解压任意文件夹,进入解压的文件夹运行①./configure②make③make install;安装的头文件与库文件一般在/usr目录下,④cd /usr⑤find -name “libusb.h“可以找到安装库的头文件,动态库.so文件一般头文件上层目录的lib目录下,为什么要这样?等下用到的时候再作解释; 这里写图片描述 在测试libusb库的时候,直接用gcc编译出现fatal error: libusb.h: No such file or directory,上面所提到的头文件与动态库文件路径就有用了,编译的时候添加 -I/头文件路径与-L/动态库文件路径,编译OK。当然,理论上应该可以把它们的路径加入环境变量,由于时间有限…… 这里写图片描述 这里写图片描述 可以看到example中的demo能正常运行了~ Libusb库example测试源码

#include #include #include static void print_devs(libusb_device **devs) { libusb_device *dev; int i = 0; 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; } printf("%04x:%04x (bus %d, device %d)\n", desc.idVendor, desc.idProduct, libusb_get_bus_number(dev), libusb_get_device_address(dev)); } } 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-1.0.9库的来实现USB的数据读取 #include #include #include #define USB_VID 0x0547 //USB的产商ID #define USB_PID 0x0503 //USB的产品ID #define EP0ADDR 0x01 //Write端口0地址,通道0 #define EP1ADDR 0x81 //Read 端口1地址,通道1 #define EP2ADDR 0x02 //Write端口2地址,通道2 #define EP3ADDR 0x86 //Read 端口3地址,通道3 #define USB_TIMEOUT 10000 //传输数据的时间延迟 #define COL 1024 //图像每一行均为1024个点 /********** IMage ************/ #define IR_ROW 485 //一帧图像总行数 #define IR_IMAGE_SIZE IR_ROW*COL*2 //一帧图像的大小,每个点2个字节 static libusb_device_handle *dev_handle = NULL; void printdev(libusb_device *dev){ libusb_device_descriptor desc; int r = libusb_get_device_descriptor(dev, &desc); if(r bNumInterfaces); const libusb_interface *inter; const libusb_interface_descriptor *interdesc; const libusb_endpoint_descriptor *epdesc; for(int i=0; ibNumInterfaces; i++){ inter =&config->interface[i]; printf("Number of alternate settings: %d\n",inter->num_altsetting); for(int j=0; jnum_altsetting; j++){ interdesc =&inter->altsetting[j]; printf("Interface Number: %d\n",(int)interdesc->bInterfaceNumber); printf("Number of endpoints: %d\n",(int)interdesc->bNumEndpoints); for(int k=0; kbNumEndpoints; k++){ epdesc =&interdesc->endpoint[k]; printf("Descriptor Type: %d\n",(int)epdesc->bDescriptorType); printf("EP Address: %d\n",(int)epdesc->bEndpointAddress); } } } libusb_free_config_descriptor(config); } int main() { int i = 0; int ret = 1; int transferred = 0; ssize_t cnt; unsigned char cmd_ir_start[50] = {0x55, 0xaa, 0x00, 0x00,0x05}; //读图像指令 unsigned char cmd_stop[50] = {0x5e, 0xaa}; //结束指令 char cmd_state[64]; unsigned short data_ir[IR_ROW][COL]; libusb_device_descriptor desc; libusb_device **devs; libusb_context *ctx = NULL; ret = libusb_init(NULL); if(ret < 0) { fprintf(stderr, "failed to initialise libusb\n"); return 1; } cnt = libusb_get_device_list(ctx, &devs); if(cnt < 0) { perror("Get Device Error\n"); return 1; } dev_handle = libusb_open_device_with_vid_pid(NULL, USB_VID, USB_PID); if(dev_handle == NULL){ perror("Cannot open device\n"); }else{ printf("Device Opened\n"); } printf("******************______************\n"); for(i =0; i < cnt; i++){ printdev(devs[i]); printf("__________________******_____________\n"); } libusb_free_device_list(devs, 1); if(libusb_kernel_driver_active(dev_handle, 0) == 1) { printf("Kernel Driver Active\n"); if(libusb_detach_kernel_driver(dev_handle, 0) == 0){ printf("Kernel Driver Detached!\n"); } } ret = libusb_claim_interface(dev_handle, 0); if(ret < 0) { perror("Cannot Claim Interface\n"); return 1; } // ret = usb_bulk_write(dev_handle, EP0ADDR, cmd_ir_start, sizeof(cmd_ir_start), USB_TIMEOUT); //ret = libusb_control_transfer(dev_handle, 0x21, 0x09, 0x0300, 0x00, dataOut+1, 0x20, USB_TIMEOUT); /* 1. 发送读Image数据指令,使用0号通道??????????????????*/ ret = libusb_bulk_transfer(dev_handle, EP0ADDR, cmd_ir_start, 5, &transferred, USB_TIMEOUT); if(ret==0 && transferred==5){ printf("write Successful!\n"); }else{ printf("write error!\n"); } ret = libusb_release_interface(dev_handle, 0); if(ret != 0){ printf("Cannot Released Interface!\n"); }else{ printf("Released Interface!\n"); } libusb_close(dev_handle); libusb_exit(ctx); return 0; }

这里写图片描述

最关键是在读写数据部分,我度娘到的大部分都是用usb开头,以usb开始的函数拥有write与read函数,而libusb开头的函数接口读写没分开(它们的版本不同,函数接口不同),到/usr/local/lib/libusb-1.0/libusb.h查看源码,能用到的同步传输接口如图: 这里写图片描述 但不知道怎么用函数接口,度娘介绍的少之又少,最后在自己解压的第三方库源码的example中找到了文件dpfp_threaded.c例子有介绍,部分源码如下

static int print_f0_data(void) { unsigned char data[0x10]; int r; unsigned int i; r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0xf0, 0, data, sizeof(data), 0); if (r < 0) { fprintf(stderr, "F0 error %d\n", r); return r; } if ((unsigned int) r < sizeof(data)) { fprintf(stderr, "short read (%d)\n", r); return -1; } printf("F0 data:"); for (i = 0; i < sizeof(data); i++) printf("%02x ", data[i]); printf("\n"); return 0; } static int get_hwstat(unsigned char *status) { int r; r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0x07, 0, status, 1, 0); if (r < 0) { fprintf(stderr, "read hwstat error %d\n", r); return r; } if ((unsigned int) r < 1) { fprintf(stderr, "short read (%d)\n", r); return -1; } printf("hwstat reads %02x\n", *status); return 0; } static int set_hwstat(unsigned char data) { int r; printf("set hwstat to %02x\n", data); r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x07, 0, &data, 1, 0); if (r < 0) { fprintf(stderr, "set hwstat error %d\n", r); return r; } if ((unsigned int) r < 1) { fprintf(stderr, "short write (%d)", r); return -1; } return 0; } static int set_mode(unsigned char data) { int r; printf("set mode %02x\n", data); r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x4e, 0, &data, 1, 0); if (r < 0) { fprintf(stderr, "set mode error %d\n", r); return r; } if ((unsigned int) r < 1) { fprintf(stderr, "short write (%d)", r); return -1; } return 0; }

关键是CTRL_IN与CTRL_OUT来控制数据的读写,我因为赶项目,换了老的第三方库,等有时间再学习下新库怎么用的,在这里只是提醒大家正确地选用库的版本,没有完全对的库,只有最适合自己的,;

四、用Libusb-0.1.12库来实现USB的数据读取 库文件的安装方法同Libusb-1.0.9类似,可能不同的就是头文件与动态库.so文件的路径不同,利用find -name命令查找即可,我的存放的路径在/usr/local/include与/usr/ local/lib下面,头文件usb.h与Libusb-1.0. 9的libusb.h不同,当然库函数也不会相同;因为要做一个封装的库文件供第三方使用,只需把重要的函数API与重要信息提供出来即可。 主程序main()函数: #include #include #include "libusbir.h"//封装的库头文件 #define USB_VID 0x0547 //USB设备的产商ID #define USB_PID 0x0503 //USB设备的产品ID int main(int argc, char *argv[]){ int ret = 0, i = 0; char data_ir[IR_IMAGE_SIZE] = {0}; struct usb_device* device = NULL; usb_dev_handle* device_handle = NULL;; //1. 通过USB的VID与PID找到设备 if((device = find_device(USB_VID, USB_PID)) == NULL) { printf("USB_DEVICE not found!\n"); exit(0); } //2. 打开找到的设备返回传输数据所要操作的句柄Handle if((device_handle=open_device(device)) == NULL) { printf("Open USB_DEVICE failed!\n"); exit(0); } while(1){ //3. 数据是实时的,采用while(1)读取数据 ret = bulk_read_data(device_handle, data_ir); if(ret < 0){ printf("Read Data fail!\n"); exit(0); } //打印数据的测试函数 print_data(data_ir); } //4. 关闭USB设备 close_usb_handle(device_handle); return 0; }

封装好的库头文件源码:

#ifndef _LIBUSBIR_H_ #define _LIBUSBIR_H_ #endif #include //libusb-0.1.12库的头文件 #define EP0ADDR 0x01 //端口0地址,通道0 #define EP1ADDR 0x81 //端口1地址,通道1 #define EP2ADDR 0x02 //端口2地址,通道2 #define EP3ADDR 0x86 //端口3地址,通道3 #define USB_TIMEOUT 10000 //传输数据的时间延迟 /********** IMAGE ************/ #define IR_ROW 288 //IMAGE Line #define COL 512*2 //IMAGE Column #define IR_IMAGE_SIZE IR_ROW*COL*2 //IMAGE一帧图像的大小 static struct usb_bus *bus = NULL; static struct usb_device* dev = NULL; static usb_dev_handle *device_handle = NULL; struct usb_device* find_device(int usb_vid, int usb_pid) { /* 1. 初始化相关数据并寻找相关设备,一开始就要调用 */ usb_init(); /* 2. 寻找系统上的usb总线,任何usb设备都通过usb总线与主机通讯,返回总线数 */ usb_find_busses(); /* 3. 寻找usb总线上的设备*/ usb_find_devices(); /* 4. 获得系统总线链表的句柄,modified by Su */ for (bus = usb_busses; bus; bus = bus->next) { /* 遍历总线上的设备 */ for (dev = bus->devices; dev; dev = dev->next) { if(dev->descriptor.idVendor == usb_vid && dev->descriptor.idProduct == usb_pid) { printf("Found USB_DEVICE!!!\n"); return dev; } } } return NULL; } usb_dev_handle* open_device(struct usb_device* udev) { if(udev != NULL) { device_handle = usb_open(udev); /* 进行设备的初始化 1.设置当前的设备使用的configuration,参数2是要使用配置描述符中的bConfigurationValue */ usb_set_configuration(device_handle, 1); /* 2.注册与操作系统通讯的接口,必须被调用,只有注册接口才能做相应的操作,参数2指bInterfaceNumber */ usb_claim_interface(device_handle, 0); /* 3.设置当前的设备使用的interface descriptor,参数2是指向接口描述符中的bAlternateSetting */ usb_set_altinterface(device_handle, 0); } return device_handle; } int bulk_read_data(usb_dev_handle* device_handle, char* data_ir){ int ret = -1; char cmd_ir_start[50] = {0x55, 0xaa, 0x00, 0x00,0x05}; //读Image指令 char cmd_stop[50] = {0x5e, 0xaa}; //结束指令 char cmd_state[64]; /* 1. 发送读Image数据指令,使用0号通道 */ ret = usb_bulk_write(device_handle, EP0ADDR, cmd_ir_start, 5, USB_TIMEOUT); if(ret < 0){ printf("Failed to write the start transfer camand!\n"); /* 2. 读Image数据, 使用通道3,最小2KB,最大3MB */ ret = usb_bulk_read(device_handle, EP3ADDR, data_ir, IR_IMAGE_SIZE, USB_TIMEOUT); //printf("Have read data length is: %d\n", ret); if(ret != IR_IMAGE_SIZE){ printf("Failed to read data!\n"); } /* 3. 发送结束指令(以0x5e,0xaa开头,使用通道0, 最大64字节)*/ ret = usb_bulk_write(device_handle, EP0ADDR, cmd_stop, 2, USB_TIMEOUT); if(ret < 0){ printf("Failed to write the stop transfer camand!\n"); } /* 4. 读状态指令(以0x5e,0xaa开头,使用通道1, 最大64字节)*/ ret = usb_bulk_read(device_handle, EP1ADDR, cmd_state, sizeof(cmd_state), USB_TIMEOUT); if(ret < 0){ printf("Failed to read data!\n"); } return ret; } int close_usb_handle(usb_dev_handle* device_handle){ usb_release_interface(device_handle, 0); usb_close(device_handle); return 0; } int print_data(char* data_ir){ int i = 0; printf("*** Start To Reading Data After Read operation***\n"); for( i= 1024 * 240;i


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭