• Linux---应用层获取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与我们要找寻的一致:

    root@Vostro:/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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    在找到对应目录后,读取该目录下面的uevent节点,会获取到该USB设备对应的主设备号,次设备号,设备名称、设备类型等相关信息,如下图:

    root@Vostro:/sys/bus/usb/devices/1-4# cat uevent 
    MAJOR=189
    MINOR=115
    DEVNAME=bus/usb/001/116
    DEVTYPE=usb_device
    DRIVER=usb
    PRODUCT=2cb7/1/100
    TYPE=0/0/0
    BUSNUM=001
    DEVNUM=116
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    这里我们需要获取的是DEVNAME=bus/usb/001/116这个信息,该信息表示在/dev设备目录下/dev/bus/usb/001/116为该USB设备的节点,我们后续读取USB设备信息以及数据读写操作都是通过这个节点进行的,如下图我们可以看到/dev/bus/usb/001/目录下有多个USB设备,其中116为我们需要的设备节点:

    root@Vostro:/sys/bus/usb/devices/1-4# cd /dev/bus/usb/001/
    root@Vostro:/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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    找到该节点后,通过应用层的open函数打开设备,通过read函数读取并解析设备的相关信息,即可获得USB设备的配置,端点,端口等信息。


    🌈应用层代码实例

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    
    #define BUF_SIZE 512
    #define MAX_PATH_LEN 512
    #define USB_DIR_BASE    "/sys/bus/usb/devices"
    
    
    typedef 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_LEN+128] = {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 (len=0; len<desc_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);
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273

    🌈实例测试

    插入一个VID PID为2cb7 0001的USB设备,运行上面的测试程序(编译过程省略),main函数入口参数传入VID 2CB7及 PID 0001运行如下:

    book@Vostro:~/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 Cls=02 Sub=06 Prot=00
    I: If#= 1 Alt= 0 #EPs= 0 Cls=0a Sub=00 Prot=00
    I: If#= 1 Alt= 1 #EPs= 2 Cls=0a Sub=00 Prot=00
    bulk_ep_in:0x81
    wMaxPacketSize:512
    bulk_ep_out:0x01
    wMaxPacketSize:512
    I: If#= 2 Alt= 0 #EPs= 2 Cls=ff Sub=ff Prot=ff
    bulk_ep_in:0x82
    wMaxPacketSize:512
    bulk_ep_out:0x02
    wMaxPacketSize:512
    I: If#= 3 Alt= 0 #EPs= 2 Cls=ff Sub=ff Prot=ff
    bulk_ep_in:0x83
    wMaxPacketSize:512
    bulk_ep_out:0x03
    wMaxPacketSize:512
    I: If#= 4 Alt= 0 #EPs= 2 Cls=ff Sub=ff Prot=ff
    bulk_ep_in:0x84
    wMaxPacketSize:512
    bulk_ep_out:0x04
    wMaxPacketSize:512
    I: If#= 5 Alt= 0 #EPs= 2 Cls=ff Sub=ff Prot=ff
    bulk_ep_in:0x85
    wMaxPacketSize:512
    bulk_ep_out:0x05
    wMaxPacketSize:512
    I: If#= 6 Alt= 0 #EPs= 2 Cls=ff Sub=42 Prot=01
    bulk_ep_in:0x86
    wMaxPacketSize:512
    bulk_ep_out:0x06
    wMaxPacketSize:512
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    可以看到通过解析read函数读取的相关信息,打印出了该USB设备的configuration、interface、endpoint等信息。

    🌈应用层通过endpoint进行数据读写

    使用USB的endpoint进行数据读写,需要了解每个endpoint的地址,并且endpoint为单向的,对于USB设备每interface下面可以有多个endpoint,这些endpoint可以是输入,也可以是输出,下面实例的设备节点USB_DEV_PATH 是由上面应用程序获取,通讯具体的endpoint地址也是由上面应用程序获取,这里直接写死对应数值以便测试:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    // 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;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87

    上述代码实际测试结果如下:

    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
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    【Pytorch with fastai】第 20 章 :结语与问题
    MySQL之库表设计篇:一、二、三、四、五范式、BC范式与反范式详解!
    紫光展锐荣评“5G技术创新力企业”,5G赋能千行百业
    svg之全局组件,配合雪碧图解决vue2的svg优化问题
    java毕业生设计在线选课系统设计计算机源码+系统+mysql+调试部署+lw
    【Java面试】谈谈你对HashMap的理解(Map接口)
    MIT6.5830 Lab1-Go tutorial实验记录(一
    【《高性能 MySQL》摘录】第 8 章 优化服务器设置
    UVM项目实战(1)
    SPI通信实验
  • 原文地址:https://blog.csdn.net/lihuan680680/article/details/132348084