wordpress注册验证邮箱验证,外贸推广seo招聘,专业网站建设管理,小公司做网站用哪种服务器文章目录 #x1f308;应用层获取USB设备信息总体思路#x1f308;应用层代码实例#x1f308;实例测试#x1f308;应用层通过endpoint进行数据读写 #x1f308;应用层获取USB设备信息总体思路
应用层可以打开USB设备的节点#xff0c;读取包括USB设备的配置#xff… 文章目录 应用层获取USB设备信息总体思路应用层代码实例实例测试应用层通过endpoint进行数据读写 应用层获取USB设备信息总体思路
应用层可以打开USB设备的节点读取包括USB设备的配置端口端点等信息。具体来说对于USB设备均存在对应的VID PID其中VID指的是Vendor ID厂商识别码用于唯一标识USB设备的制造商。PID指的是Product ID产品识别码用于唯一标识USB设备的产品型号。通过VID和PID可以确定一个具体的USB设备因为每个设备的VID和PID是唯一的可以帮助系统识别和与设备进行交互。 如果上位机正常识别USB设备我们可以通过对应节点信息/sys/bus/usb/devices按照文件目录去搜索如果目录中idVendor和idProduct与我们要搜索的一致可以判定为我们需要找的设备节点。如下图1-4目录中的idVendor和idProduct与我们要找寻的一致
rootVostro:/sys/bus/usb/devices/1-4# ls -al
total 0
drwxr-xr-x 12 root root 0 Aug 31 20:55 .
drwxr-xr-x 8 root root 0 Aug 10 11:55 ..
drwxr-xr-x 6 root root 0 Aug 31 20:55 1-4:1.0
drwxr-xr-x 6 root root 0 Aug 31 20:55 1-4:1.1
drwxr-xr-x 7 root root 0 Aug 31 20:55 1-4:1.2
drwxr-xr-x 7 root root 0 Aug 31 20:55 1-4:1.3
drwxr-xr-x 7 root root 0 Aug 31 20:55 1-4:1.4
drwxr-xr-x 7 root root 0 Aug 31 20:55 1-4:1.5
drwxr-xr-x 7 root root 0 Aug 31 20:55 1-4:1.6
-rw-r--r-- 1 root root 4096 Aug 31 20:55 authorized
-rw-r--r-- 1 root root 4096 Aug 31 20:55 avoid_reset_quirk
-r--r--r-- 1 root root 4096 Aug 31 20:55 bcdDevice
-rw-r--r-- 1 root root 4096 Aug 31 20:55 bConfigurationValue
-r--r--r-- 1 root root 4096 Aug 31 20:55 bDeviceClass
-r--r--r-- 1 root root 4096 Aug 31 20:55 bDeviceProtocol
-r--r--r-- 1 root root 4096 Aug 31 20:55 bDeviceSubClass
-r--r--r-- 1 root root 4096 Aug 31 20:55 bmAttributes
-r--r--r-- 1 root root 4096 Aug 31 20:55 bMaxPacketSize0
-r--r--r-- 1 root root 4096 Aug 31 20:55 bMaxPower
-r--r--r-- 1 root root 4096 Aug 31 20:55 bNumConfigurations
-r--r--r-- 1 root root 4096 Aug 31 20:55 bNumInterfaces
-r--r--r-- 1 root root 4096 Aug 31 20:55 busnum
-r--r--r-- 1 root root 4096 Aug 31 20:55 configuration
-r--r--r-- 1 root root 65553 Aug 31 20:55 descriptors
-r--r--r-- 1 root root 4096 Aug 31 20:55 dev
-r--r--r-- 1 root root 4096 Aug 31 20:55 devnum
-r--r--r-- 1 root root 4096 Aug 31 20:55 devpath
lrwxrwxrwx 1 root root 0 Aug 31 20:55 driver - ../../../../../bus/usb/drivers/usb
drwxr-xr-x 3 root root 0 Aug 31 20:55 ep_00
lrwxrwxrwx 1 root root 0 Aug 31 20:55 firmware_node - ../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d/device:51
-r--r--r-- 1 root root 4096 Aug 31 20:55 idProduct
-r--r--r-- 1 root root 4096 Aug 31 20:55 idVendor
-r--r--r-- 1 root root 4096 Aug 31 20:55 ltm_capable
-r--r--r-- 1 root root 4096 Aug 31 20:55 manufacturer
-r--r--r-- 1 root root 4096 Aug 31 20:55 maxchild
drwxr-xr-x 2 root root 0 Aug 31 20:55 physical_location
lrwxrwxrwx 1 root root 0 Aug 31 20:55 port - ../1-0:1.0/usb1-port4
drwxr-xr-x 2 root root 0 Aug 31 20:55 power
-r--r--r-- 1 root root 4096 Aug 31 20:55 product
-r--r--r-- 1 root root 4096 Aug 31 20:55 quirks
-r--r--r-- 1 root root 4096 Aug 31 20:55 removable
--w------- 1 root root 4096 Aug 31 20:55 remove
-r--r--r-- 1 root root 4096 Aug 31 20:55 rx_lanes
-r--r--r-- 1 root root 4096 Aug 31 20:55 serial
-r--r--r-- 1 root root 4096 Aug 31 20:55 speed
lrwxrwxrwx 1 root root 0 Aug 31 20:55 subsystem - ../../../../../bus/usb
-r--r--r-- 1 root root 4096 Aug 31 20:55 tx_lanes
-rw-r--r-- 1 root root 4096 Aug 31 20:55 uevent
-r--r--r-- 1 root root 4096 Aug 31 20:55 urbnum
-r--r--r-- 1 root root 4096 Aug 31 20:55 version
在找到对应目录后读取该目录下面的uevent节点会获取到该USB设备对应的主设备号次设备号设备名称、设备类型等相关信息如下图
rootVostro:/sys/bus/usb/devices/1-4# cat uevent
MAJOR189
MINOR115
DEVNAMEbus/usb/001/116
DEVTYPEusb_device
DRIVERusb
PRODUCT2cb7/1/100
TYPE0/0/0
BUSNUM001
DEVNUM116
这里我们需要获取的是DEVNAMEbus/usb/001/116这个信息该信息表示在/dev设备目录下/dev/bus/usb/001/116为该USB设备的节点我们后续读取USB设备信息以及数据读写操作都是通过这个节点进行的如下图我们可以看到/dev/bus/usb/001/目录下有多个USB设备其中116为我们需要的设备节点
rootVostro:/sys/bus/usb/devices/1-4# cd /dev/bus/usb/001/
rootVostro:/dev/bus/usb/001# ls -al
total 0
drwxr-xr-x 2 root root 120 Sep 1 17:59 .
drwxr-xr-x 4 root root 80 Aug 10 11:55 ..
crw-rw-rw- 1 root root 189, 0 Aug 10 11:56 001
crw-rw-rw- 1 root root 189, 2 Aug 10 11:56 003
crw-rw-rw- 1 root root 189, 3 Aug 10 11:56 004
crw-rw-rw- 1 root root 189, 115 Aug 31 20:55 116
找到该节点后通过应用层的open函数打开设备通过read函数读取并解析设备的相关信息即可获得USB设备的配置端点端口等信息。 应用层代码实例
#include stdio.h
#include string.h
#include stdlib.h
#include errno.h
#include fcntl.h
#include unistd.h
#include sys/types.h
#include dirent.h
#include linux/usbdevice_fs.h
#include linux/usb/ch9.h#define BUF_SIZE 512
#define MAX_PATH_LEN 512
#define USB_DIR_BASE /sys/bus/usb/devicestypedef struct
{int idVendor;int idProduct;int InterfaceNum;int usbdev;char portname[BUF_SIZE];char syspath[BUF_SIZE];char busname[BUF_SIZE];int bulk_ep_in;int bulk_ep_out;int wMaxPacketSize;int usb_need_zero_package;int (* write)(const void *handle, void *pbuf, int size, int portnum);int (* read)(const void *handle, void *pbuf, int size, int portnum);
} s_usbdev_t;s_usbdev_t udev;int strStartsWith(const char *str, const char *match_str)
{for ( ; *str ! \0 *match_str ! \0; str, match_str) {if (*str ! *match_str) {return 0;}}return *match_str \0;
}static int get_usbsys_val(const char *sys_filename, int base)
{char buff[64] {0};int ret_val -1;int fd open(sys_filename, O_RDONLY);if (fd 0) {return -1;}if (read(fd, buff, sizeof(buff)) 0) {printf(read:%s failed\n, sys_filename);}else {ret_val strtoul(buff, NULL, base);}close(fd);return ret_val;
}static int get_busname_by_uevent(const char *uevent, char *busname)
{FILE *fp NULL;char line[BUF_SIZE] {0};int MAJOR 0, MINOR 0;char DEVTYPE[64] {0}, PRODUCT[64] {0};fp fopen(uevent, r);if (fp NULL) {printf(fopen %s failed, errno:%d(%s)\n, uevent, errno, strerror(errno));return -1;}while (fgets(line, sizeof(line), fp)){if (line[strlen(line) - 1] \n || line[strlen(line) - 1] \r) {line[strlen(line) - 1] 0;}if (strStartsWith(line, MAJOR)){MAJOR atoi(line[strlen(MAJOR)]);}else if (strStartsWith(line, MINOR)){MINOR atoi(line[strlen(MINOR)]);}else if (strStartsWith(line, DEVICE)){strncpy(busname, line[strlen(DEVICE)], MAX_PATH_LEN);}else if (strStartsWith(line, DEVNAME)){strncpy(busname, line[strlen(DEVNAME)], MAX_PATH_LEN);}else if (strStartsWith(line, DEVTYPE)){strncpy(DEVTYPE, line[strlen(DEVTYPE)], sizeof(DEVTYPE));}else if (strStartsWith(line, PRODUCT)){strncpy(PRODUCT, line[strlen(PRODUCT)], sizeof(PRODUCT));}}fclose(fp);if (MAJOR ! 189 || MINOR 0 || busname[0] 0|| DEVTYPE[0] 0 || PRODUCT[0] 0|| strStartsWith(DEVTYPE, usb_device) 0) {return -1;}return 0;
}int usb_dev_open(int usb_vid, int usb_pid)
{char devdesc[MAX_PATH_LEN*2] {0};char devname[MAX_PATH_LEN128] {0};size_t desc_length 0, len 0;int bInterfaceNumber 0;DIR *usbdir NULL;struct dirent *dent NULL;int idVendor 0, idProduct 0;int bNumInterfaces 0, bConfigurationValue 0;char sys_filename[MAX_PATH_LEN] {0};usbdir opendir(/sys/bus/usb/devices);if (usbdir NULL) {return -1;}while ((dent readdir(usbdir)) ! NULL){if (strcmp(dent-d_name, .) 0 || strcmp(dent-d_name, ..) 0) {continue;}snprintf(sys_filename, sizeof(sys_filename), %s/%s/idVendor, USB_DIR_BASE, dent-d_name);if ((idVendor get_usbsys_val(sys_filename, 16)) 0) {continue;}snprintf(sys_filename, sizeof(sys_filename), %s/%s/idProduct, USB_DIR_BASE, dent-d_name);if ((idProduct get_usbsys_val(sys_filename, 16)) 0) {continue;}snprintf(sys_filename, sizeof(sys_filename), %s/%s/bConfigurationValue, USB_DIR_BASE, dent-d_name);if ((bConfigurationValue get_usbsys_val(sys_filename, 10)) 0) {continue;}snprintf(sys_filename, sizeof(sys_filename), %s/%s/bNumInterfaces, USB_DIR_BASE, dent-d_name);if ((bNumInterfaces get_usbsys_val(sys_filename, 10)) 0) {continue;}if((idVendor usb_vid)(idProduct usb_pid)){udev.idVendor idVendor;udev.idProduct idProduct;printf(----------------------------------\n);printf(idVendor: %04x\n, udev.idVendor);printf(idProduct: %04x\n, udev.idProduct);printf(bNumInterfaces: %d\n, bNumInterfaces);printf(bConfigurationValue: %d\n, bConfigurationValue);snprintf(sys_filename, sizeof(sys_filename), %s/%s/uevent, USB_DIR_BASE, dent-d_name);get_busname_by_uevent(sys_filename, udev.busname);printf(busname: %s\n, udev.busname);printf(----------------------------------\n);break;}usleep(10000);}if (usbdir) {closedir(usbdir);usbdir NULL;}snprintf(devname, sizeof(devname), /dev/%s, udev.busname);if (access(devname, F_OK | R_OK| W_OK)) {printf(access %s failed, errno:%d(%s)\n, devname, errno, strerror(errno));return -1;}udev.usbdev open(devname, O_RDWR | O_NOCTTY);if (udev.usbdev 0) {printf(open %s failed, errno:%d(%s)\n, devname, errno, strerror(errno));return -1;}printf([%s] OK.\n, devname);desc_length read(udev.usbdev, devdesc, sizeof(devdesc));printf(desc_length is %zu,read length is %zu\r\n, sizeof(devdesc), desc_length);for (len0; lendesc_length;){struct usb_descriptor_header *h (struct usb_descriptor_header *)(devdesc len);if (h-bLength sizeof(struct usb_device_descriptor) h-bDescriptorType USB_DT_DEVICE){struct usb_device_descriptor *device (struct usb_device_descriptor *)h;printf(P: idVendor: %04x idProduct:%04x\n, device-idVendor, device-idProduct);}else if (h-bLength sizeof(struct usb_config_descriptor) h-bDescriptorType USB_DT_CONFIG){struct usb_config_descriptor *config (struct usb_config_descriptor *)h;printf(C: bNumInterfaces: %d\n, config-bNumInterfaces);}else if (h-bLength sizeof(struct usb_interface_descriptor) h-bDescriptorType USB_DT_INTERFACE){struct usb_interface_descriptor *interface (struct usb_interface_descriptor *)h;printf(I: If# %d Alt %d #EPs %d Cls%02x Sub%02x Prot%02x\n,interface-bInterfaceNumber, interface-bAlternateSetting, interface-bNumEndpoints,interface-bInterfaceClass, interface-bInterfaceSubClass, interface-bInterfaceProtocol);bInterfaceNumber interface-bInterfaceNumber;}else if (h-bLength USB_DT_ENDPOINT_SIZE h-bDescriptorType USB_DT_ENDPOINT){struct usb_endpoint_descriptor *endpoint (struct usb_endpoint_descriptor *)h;if ( (endpoint-bmAttributes USB_ENDPOINT_XFERTYPE_MASK) USB_ENDPOINT_XFER_BULK){if (endpoint-bEndpointAddress USB_ENDPOINT_DIR_MASK) {udev.bulk_ep_in endpoint-bEndpointAddress;printf(bulk_ep_in:0x%02X\n, udev.bulk_ep_in);} else {udev.bulk_ep_out endpoint-bEndpointAddress;printf(bulk_ep_out:0x%02X\n, udev.bulk_ep_out);}udev.wMaxPacketSize endpoint-wMaxPacketSize;printf(wMaxPacketSize:%d\n, endpoint-wMaxPacketSize);}}len h-bLength;}return 0;
}int main(int argc, char * * argv)
{int vid_hex,pid_hex;if(argc !3 ){printf(Usage: usb_read_device_info USB_VID USB_PID \r\n);return -1;}sscanf(argv[1], %x, vid_hex);sscanf(argv[2], %x, pid_hex);printf(USB VID %4x, PID is %4x\r\n, vid_hex, pid_hex);usb_dev_open(vid_hex,pid_hex);
}
实例测试
插入一个VID PID为2cb7 0001的USB设备运行上面的测试程序编译过程省略main函数入口参数传入VID 2CB7及 PID 0001运行如下
bookVostro:~/Joy/Test$ sudo ./USB_read_device_info 2cb7 0001
USB VID 2cb7, PID is 1
----------------------------------
idVendor: 2cb7
idProduct: 0001
bNumInterfaces: 7
bConfigurationValue: 1
busname: bus/usb/001/116
----------------------------------
[/dev/bus/usb/001/116] OK.
desc_length is 1024,read length is 221
P: idVendor: 2cb7 idProduct:0001
C: bNumInterfaces: 7
I: If# 0 Alt 0 #EPs 1 Cls02 Sub06 Prot00
I: If# 1 Alt 0 #EPs 0 Cls0a Sub00 Prot00
I: If# 1 Alt 1 #EPs 2 Cls0a Sub00 Prot00
bulk_ep_in:0x81
wMaxPacketSize:512
bulk_ep_out:0x01
wMaxPacketSize:512
I: If# 2 Alt 0 #EPs 2 Clsff Subff Protff
bulk_ep_in:0x82
wMaxPacketSize:512
bulk_ep_out:0x02
wMaxPacketSize:512
I: If# 3 Alt 0 #EPs 2 Clsff Subff Protff
bulk_ep_in:0x83
wMaxPacketSize:512
bulk_ep_out:0x03
wMaxPacketSize:512
I: If# 4 Alt 0 #EPs 2 Clsff Subff Protff
bulk_ep_in:0x84
wMaxPacketSize:512
bulk_ep_out:0x04
wMaxPacketSize:512
I: If# 5 Alt 0 #EPs 2 Clsff Subff Protff
bulk_ep_in:0x85
wMaxPacketSize:512
bulk_ep_out:0x05
wMaxPacketSize:512
I: If# 6 Alt 0 #EPs 2 Clsff Sub42 Prot01
bulk_ep_in:0x86
wMaxPacketSize:512
bulk_ep_out:0x06
wMaxPacketSize:512
可以看到通过解析read函数读取的相关信息打印出了该USB设备的configuration、interface、endpoint等信息。
应用层通过endpoint进行数据读写
使用USB的endpoint进行数据读写需要了解每个endpoint的地址并且endpoint为单向的对于USB设备每interface下面可以有多个endpoint这些endpoint可以是输入也可以是输出下面实例的设备节点USB_DEV_PATH 是由上面应用程序获取通讯具体的endpoint地址也是由上面应用程序获取这里直接写死对应数值以便测试
#include stdio.h
#include stdlib.h
#include fcntl.h
#include unistd.h
#include string.h
#include errno.h
#include sys/ioctl.h
#include linux/usbdevice_fs.h// USB设备节点路径可通过上部分应用层实例代码获取某VID PID 对应的usb设备节点
#define USB_DEV_PATH /dev/bus/usb/001/018 int usbfs_bulk_write(int fd, char *data, size_t dataLen)
{int ret;struct usbdevfs_urb urb_write;struct usbdevfs_urb *urb NULL;memset(urb_write, 0, sizeof(urb_write));urb_write.type USBDEVFS_URB_TYPE_BULK;urb_write.endpoint 0x05;urb_write.status -1;urb_write.buffer (void *)data;urb_write.buffer_length dataLen;urb_write.usercontext urb_write;printf(endpoint is %d, buffer_length is %d\r\n, urb_write.endpoint, urb_write.buffer_length);do {ret ioctl(fd, USBDEVFS_SUBMITURB, urb_write);} while ((ret 0) (errno EINTR));if (ret ! 0) {printf(USBDEVFS_SUBMITURB failed, ret: %d, errno:%d(%s)\n, ret, errno, strerror(errno));return -1;}do {urb NULL;ret ioctl(fd, USBDEVFS_REAPURB, urb);} while ((ret 0) (errno EINTR));if (ret 0 urb urb-status 0 urb-actual_length) {return urb-actual_length;}return -1;
}int usbfs_bulk_read(int fd, char *data, size_t dataLen)
{int ret -1;struct usbdevfs_bulktransfer bulk;bulk.ep 0x85;bulk.len dataLen;bulk.data data;bulk.timeout 3000;do {ret ioctl(fd, USBDEVFS_BULK, bulk);} while ((ret 0) (errno EINTR));return ret;
}int main()
{// 准备要写入的数据unsigned char data[] {0x01,0xaa,0xaa,0xaa,0x01,0x55,0x73,0x01,0x14,0x00,0x00,0x00,0x06,0x67,0xbb,0xbb,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x44,0x09,0x7e};size_t dataLen sizeof(data);int ret;int fd open(USB_DEV_PATH, O_RDWR | O_NOCTTY); // 打开USB设备文件描述符if (fd -1) {perror(Failed to open USB device);return -1;}ret usbfs_bulk_write(fd, data, dataLen);printf(usbfs_bulk_write ret is %d\r\n, ret);ret usbfs_bulk_read(fd, data, dataLen);printf(usbfs_bulk_read ret is %d\r\n, ret);return 0;
}
上述代码实际测试结果如下
root:/home/Joy/Test# ./usb_bulk_write_read
endpoint is 5, buffer_length is 35
usbfs_bulk_write ret is 35
usbfs_bulk_read ret is 10