diff --git a/IMX6ULL/doc_pic/12_USB/07_使用libusb读取鼠标数据.md b/IMX6ULL/doc_pic/12_USB/07_使用libusb读取鼠标数据.md index eb6e9de..6b7b396 100644 --- a/IMX6ULL/doc_pic/12_USB/07_使用libusb读取鼠标数据.md +++ b/IMX6ULL/doc_pic/12_USB/07_使用libusb读取鼠标数据.md @@ -208,7 +208,149 @@ USB规范里为每个按键定义了16位的按键值,注意:它是16位的 ### 2.1 编写源码 ```c +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int err; + libusb_device *dev, **devs; + int num_devices; + int endpoint; + int interface_num; + int found = 0; + int transferred; + int count = 0; + unsigned char buffer[16]; + struct libusb_config_descriptor *config_desc; + struct libusb_device_handle *dev_handle = NULL; + + /* libusb_init */ + + err = libusb_init(NULL); + if (err < 0) { + fprintf(stderr, "failed to initialise libusb %d - %s\n", err, libusb_strerror(err)); + exit(1); + } + + /* get device list */ + if ((num_devices = libusb_get_device_list(NULL, &devs)) < 0) { + fprintf(stderr, "libusb_get_device_list() failed\n"); + libusb_exit(NULL); + exit(1); + } + fprintf(stdout, "libusb_get_device_list() ok\n"); + + /* for each device, get config descriptor */ + for (int i = 0; i < num_devices; i++) { + dev = devs[i]; + + /* parse interface descriptor, find usb mouse */ + err = libusb_get_config_descriptor(dev, 0, &config_desc); + if (err) { + fprintf(stderr, "could not get configuration descriptor\n"); + continue; + } + fprintf(stdout, "libusb_get_config_descriptor() ok\n"); + + for (int interface = 0; interface < config_desc->bNumInterfaces; interface++) { + const struct libusb_interface_descriptor *intf_desc = &config_desc->interface[interface].altsetting[0]; + interface_num = intf_desc->bInterfaceNumber; + + if (intf_desc->bInterfaceClass != 3 || intf_desc->bInterfaceProtocol != 2) + continue; + else + { + /* 找到了USB鼠标 */ + fprintf(stdout, "find usb mouse ok\n"); + for (int ep = 0; ep < intf_desc->bNumEndpoints; ep++) + { + if ((intf_desc->endpoint[ep].bmAttributes & 3) == LIBUSB_TRANSFER_TYPE_INTERRUPT || + (intf_desc->endpoint[ep].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) { + /* 找到了输入的中断端点 */ + fprintf(stdout, "find in int endpoint\n"); + endpoint = intf_desc->endpoint[ep].bEndpointAddress; + found = 1; + break; + } + + } + } + + if (found) + break; + } + + libusb_free_config_descriptor(config_desc); + + if (found) + break; + } + + if (!found) + { + /* free device list */ + libusb_free_device_list(devs, 1); + libusb_exit(NULL); + exit(1); + } + + if (found) + { + /* libusb_open */ + err = libusb_open(dev, &dev_handle); + if (err) + { + fprintf(stderr, "failed to open usb mouse\n"); + exit(1); + } + fprintf(stdout, "libusb_open ok\n"); + } + + /* free device list */ + libusb_free_device_list(devs, 1); + + /* claim interface */ + libusb_set_auto_detach_kernel_driver(dev_handle, 1); + err = libusb_claim_interface(dev_handle, interface_num); + if (err) + { + fprintf(stderr, "failed to libusb_claim_interface\n"); + exit(1); + } + fprintf(stdout, "libusb_claim_interface ok\n"); + + /* libusb_interrupt_transfer */ + while (1) + { + err = libusb_interrupt_transfer(dev_handle, endpoint, buffer, 16, &transferred, 5000); + if (!err) { + /* parser data */ + printf("%04d datas: ", count++); + for (int i = 0; i < transferred; i++) + { + printf("%02x ", buffer[i]); + } + printf("\n"); + } else if (err == LIBUSB_ERROR_TIMEOUT){ + fprintf(stderr, "libusb_interrupt_transfer timout\n"); + } else { + fprintf(stderr, "libusb_interrupt_transfer err : %d\n", err); + //exit(1); + } + + } + + /* libusb_close */ + libusb_release_interface(dev_handle, interface_num); + libusb_close(dev_handle); + libusb_exit(NULL); +} ``` @@ -230,7 +372,7 @@ gcc -o readmouse readmouse.c -lusb-1.0 -#### 2.2.2 在开发板上实验 +#### 2.2.2 在IMX6ULL开发板上实验 @@ -269,13 +411,295 @@ gcc -o readmouse readmouse.c -lusb-1.0 * 交叉编译app ```shell - arm-buildroot-linux-gnueabihf-gcc -o readmouse readmouse.c -lusb-1.0 + arm-buildroot-linux-gnueabihf-gcc -o readmouse.c -lusb-1.0 + ``` + + +* 在开发板上插入USB鼠标,执行命令 + + ```shell + ./readmouse ``` +#### 2.2.3 在STM32MP157开发板上实验 + +* STM32MP157的工具链里已经含有libusb,所以无需交叉编译、安装libusb + +* 交叉编译app + + ```shell + arm-buildroot-linux-gnueabihf-gcc -o readmouse readmouse.c -lusb-1.0 + ``` + +* 在开发板上插入USB鼠标,执行命令 + + ```shell + ./readmouse + ``` + + + + + +## 3. 使用异步接口读取鼠标数据 + +源码在GIT仓库如下位置: + +![image-20220929092859668](pic/61_libusb_async_usbmouse_src.png) + +### 3.1 编写源码 + +```c +#include +#include +#include +#include +#include + +#include + +struct usb_mouse { + struct libusb_device_handle *handle; + int interface; + int endpoint; + unsigned char buf[16]; + int transferred; + struct libusb_transfer *transfer; + struct usb_mouse *next; +}; + +static struct usb_mouse *usb_mouse_list; + + +void free_usb_mouses(struct usb_mouse *usb_mouse_list) +{ + struct usb_mouse *pnext; + while (usb_mouse_list) + { + pnext = usb_mouse_list->next; + free(usb_mouse_list); + usb_mouse_list = pnext; + } +} + + +/* */ +int get_usb_mouses(libusb_device **devs, int num_devices, struct usb_mouse **usb_mouse_list) +{ + int err; + libusb_device *dev; + int endpoint; + int interface_num; + struct libusb_config_descriptor *config_desc; + struct libusb_device_handle *dev_handle = NULL; + struct usb_mouse *pmouse; + struct usb_mouse *list = NULL; + int mouse_cnt = 0; + + /* for each device, get config descriptor */ + for (int i = 0; i < num_devices; i++) { + dev = devs[i]; + + /* parse interface descriptor, find usb mouse */ + err = libusb_get_config_descriptor(dev, 0, &config_desc); + if (err) { + fprintf(stderr, "could not get configuration descriptor\n"); + continue; + } + fprintf(stdout, "libusb_get_config_descriptor() ok\n"); + + for (int interface = 0; interface < config_desc->bNumInterfaces; interface++) { + const struct libusb_interface_descriptor *intf_desc = &config_desc->interface[interface].altsetting[0]; + interface_num = intf_desc->bInterfaceNumber; + + if (intf_desc->bInterfaceClass != 3 || intf_desc->bInterfaceProtocol != 2) + continue; + else + { + /* 找到了USB鼠标 */ + fprintf(stdout, "find usb mouse ok\n"); + for (int ep = 0; ep < intf_desc->bNumEndpoints; ep++) + { + if ((intf_desc->endpoint[ep].bmAttributes & 3) == LIBUSB_TRANSFER_TYPE_INTERRUPT || + (intf_desc->endpoint[ep].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) { + /* 找到了输入的中断端点 */ + fprintf(stdout, "find in int endpoint\n"); + endpoint = intf_desc->endpoint[ep].bEndpointAddress; + + /* libusb_open */ + err = libusb_open(dev, &dev_handle); + if (err) + { + fprintf(stderr, "failed to open usb mouse\n"); + return -1; + } + fprintf(stdout, "libusb_open ok\n"); + + /* 记录下来: 放入链表 */ + pmouse = malloc(sizeof(struct usb_mouse)); + if (!pmouse) + { + fprintf(stderr, "can not malloc\n"); + return -1; + } + pmouse->endpoint = endpoint; + pmouse->interface = interface_num; + pmouse->handle = dev_handle; + pmouse->next = NULL; + + if (!list) + list = pmouse; + else + { + pmouse->next = list; + list = pmouse; + } + mouse_cnt++; + break; + } + + } + } + + } + + libusb_free_config_descriptor(config_desc); + } + + *usb_mouse_list = list; + return mouse_cnt; +} + + +static void mouse_irq(struct libusb_transfer *transfer) +{ + static int count = 0; + if (transfer->status == LIBUSB_TRANSFER_COMPLETED) + { + /* parser data */ + printf("%04d datas: ", count++); + for (int i = 0; i < transfer->actual_length; i++) + { + printf("%02x ", transfer->buffer[i]); + } + printf("\n"); + + } + + if (libusb_submit_transfer(transfer) < 0) + { + fprintf(stderr, "libusb_submit_transfer err\n"); + } +} + +int main(int argc, char **argv) +{ + int err; + libusb_device **devs; + int num_devices, num_mouse; + struct usb_mouse *pmouse; + + /* libusb_init */ + + err = libusb_init(NULL); + if (err < 0) { + fprintf(stderr, "failed to initialise libusb %d - %s\n", err, libusb_strerror(err)); + exit(1); + } + + /* get device list */ + if ((num_devices = libusb_get_device_list(NULL, &devs)) < 0) { + fprintf(stderr, "libusb_get_device_list() failed\n"); + libusb_exit(NULL); + exit(1); + } + fprintf(stdout, "libusb_get_device_list() ok\n"); + + /* get usb mouse */ + num_mouse = get_usb_mouses(devs, num_devices, &usb_mouse_list); + + if (num_mouse <= 0) + { + /* free device list */ + libusb_free_device_list(devs, 1); + libusb_exit(NULL); + exit(1); + } + fprintf(stdout, "get %d mouses\n", num_mouse); + + /* free device list */ + libusb_free_device_list(devs, 1); + + /* claim interface */ + pmouse = usb_mouse_list; + while (pmouse) + { + libusb_set_auto_detach_kernel_driver(pmouse->handle, 1); + err = libusb_claim_interface(pmouse->handle, pmouse->interface); + if (err) + { + fprintf(stderr, "failed to libusb_claim_interface\n"); + exit(1); + } + pmouse = pmouse->next; + } + fprintf(stdout, "libusb_claim_interface ok\n"); + + /* for each mouse, alloc transfer, fill transfer, submit transfer */ + pmouse = usb_mouse_list; + while (pmouse) + { + /* alloc transfer */ + pmouse->transfer = libusb_alloc_transfer(0); + + /* fill transfer */ + libusb_fill_interrupt_transfer(pmouse->transfer, pmouse->handle, pmouse->endpoint, pmouse->buf, + sizeof(pmouse->buf), mouse_irq, pmouse, 0); + + /* submit transfer */ + libusb_submit_transfer(pmouse->transfer); + + pmouse = pmouse->next; + } + + /* handle events */ + while (1) { + struct timeval tv = { 5, 0 }; + int r; + + r = libusb_handle_events_timeout(NULL, &tv); + if (r < 0) { + fprintf(stderr, "libusb_handle_events_timeout err\n"); + break; + } + } + + + /* libusb_close */ + pmouse = usb_mouse_list; + while (pmouse) + { + libusb_release_interface(pmouse->handle, pmouse->interface); + libusb_close(pmouse->handle); + pmouse = pmouse->next; + } + + free_usb_mouses(usb_mouse_list); + + libusb_exit(NULL); +} +``` + + + + + +### 3.2 在开发板上实验 + diff --git a/IMX6ULL/doc_pic/12_USB/07_使用libusb读取鼠标数据.tif b/IMX6ULL/doc_pic/12_USB/07_使用libusb读取鼠标数据.tif deleted file mode 100644 index 7def9ca..0000000 Binary files a/IMX6ULL/doc_pic/12_USB/07_使用libusb读取鼠标数据.tif and /dev/null differ diff --git a/IMX6ULL/doc_pic/12_USB/pic/61_libusb_async_usbmouse_src.png b/IMX6ULL/doc_pic/12_USB/pic/61_libusb_async_usbmouse_src.png new file mode 100644 index 0000000..9beb121 Binary files /dev/null and b/IMX6ULL/doc_pic/12_USB/pic/61_libusb_async_usbmouse_src.png differ diff --git a/IMX6ULL/source/12_USB/02_libusb_mouse_sync/readmouse.c b/IMX6ULL/source/12_USB/02_libusb_mouse_sync/readmouse.c index eb4605e..4550ca1 100644 --- a/IMX6ULL/source/12_USB/02_libusb_mouse_sync/readmouse.c +++ b/IMX6ULL/source/12_USB/02_libusb_mouse_sync/readmouse.c @@ -8,8 +8,8 @@ int main(int argc, char **argv) { - int err; - libusb_device *dev, **devs; + int err; + libusb_device *dev, **devs; int num_devices; int endpoint; int interface_num; @@ -22,11 +22,11 @@ int main(int argc, char **argv) /* libusb_init */ - err = libusb_init(NULL); - if (err < 0) { - fprintf(stderr, "failed to initialise libusb %d - %s\n", err, libusb_strerror(err)); - exit(1); - } + err = libusb_init(NULL); + if (err < 0) { + fprintf(stderr, "failed to initialise libusb %d - %s\n", err, libusb_strerror(err)); + exit(1); + } /* get device list */ if ((num_devices = libusb_get_device_list(NULL, &devs)) < 0) { @@ -37,7 +37,7 @@ int main(int argc, char **argv) fprintf(stdout, "libusb_get_device_list() ok\n"); /* for each device, get config descriptor */ - for (int i = 0; i < num_devices; i++) { + for (int i = 0; i < num_devices; i++) { dev = devs[i]; /* parse interface descriptor, find usb mouse */ @@ -80,7 +80,7 @@ int main(int argc, char **argv) if (found) break; - } + } if (!found) { @@ -118,21 +118,21 @@ int main(int argc, char **argv) /* libusb_interrupt_transfer */ while (1) { - err = libusb_interrupt_transfer(dev_handle, endpoint, buffer, 16, &transferred, 5000); - if (!err) { - /* parser data */ + err = libusb_interrupt_transfer(dev_handle, endpoint, buffer, 16, &transferred, 5000); + if (!err) { + /* parser data */ printf("%04d datas: ", count++); for (int i = 0; i < transferred; i++) { printf("%02x ", buffer[i]); } printf("\n"); - } else if (err == LIBUSB_ERROR_TIMEOUT){ + } else if (err == LIBUSB_ERROR_TIMEOUT){ fprintf(stderr, "libusb_interrupt_transfer timout\n"); - } else { + } else { fprintf(stderr, "libusb_interrupt_transfer err : %d\n", err); //exit(1); - } + } } diff --git a/IMX6ULL/source/12_USB/03_libusb_mouse_async/readmouse.c b/IMX6ULL/source/12_USB/03_libusb_mouse_async/readmouse.c new file mode 100644 index 0000000..7459eab --- /dev/null +++ b/IMX6ULL/source/12_USB/03_libusb_mouse_async/readmouse.c @@ -0,0 +1,240 @@ +#include +#include +#include +#include +#include + +#include + +struct usb_mouse { + struct libusb_device_handle *handle; + int interface; + int endpoint; + unsigned char buf[16]; + int transferred; + struct libusb_transfer *transfer; + struct usb_mouse *next; +}; + +static struct usb_mouse *usb_mouse_list; + + +void free_usb_mouses(struct usb_mouse *usb_mouse_list) +{ + struct usb_mouse *pnext; + while (usb_mouse_list) + { + pnext = usb_mouse_list->next; + free(usb_mouse_list); + usb_mouse_list = pnext; + } +} + + +/* */ +int get_usb_mouses(libusb_device **devs, int num_devices, struct usb_mouse **usb_mouse_list) +{ + int err; + libusb_device *dev; + int endpoint; + int interface_num; + struct libusb_config_descriptor *config_desc; + struct libusb_device_handle *dev_handle = NULL; + struct usb_mouse *pmouse; + struct usb_mouse *list = NULL; + int mouse_cnt = 0; + + /* for each device, get config descriptor */ + for (int i = 0; i < num_devices; i++) { + dev = devs[i]; + + /* parse interface descriptor, find usb mouse */ + err = libusb_get_config_descriptor(dev, 0, &config_desc); + if (err) { + fprintf(stderr, "could not get configuration descriptor\n"); + continue; + } + fprintf(stdout, "libusb_get_config_descriptor() ok\n"); + + for (int interface = 0; interface < config_desc->bNumInterfaces; interface++) { + const struct libusb_interface_descriptor *intf_desc = &config_desc->interface[interface].altsetting[0]; + interface_num = intf_desc->bInterfaceNumber; + + if (intf_desc->bInterfaceClass != 3 || intf_desc->bInterfaceProtocol != 2) + continue; + else + { + /* 找到了USB鼠标 */ + fprintf(stdout, "find usb mouse ok\n"); + for (int ep = 0; ep < intf_desc->bNumEndpoints; ep++) + { + if ((intf_desc->endpoint[ep].bmAttributes & 3) == LIBUSB_TRANSFER_TYPE_INTERRUPT || + (intf_desc->endpoint[ep].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) { + /* 找到了输入的中断端点 */ + fprintf(stdout, "find in int endpoint\n"); + endpoint = intf_desc->endpoint[ep].bEndpointAddress; + + /* libusb_open */ + err = libusb_open(dev, &dev_handle); + if (err) + { + fprintf(stderr, "failed to open usb mouse\n"); + return -1; + } + fprintf(stdout, "libusb_open ok\n"); + + /* 记录下来: 放入链表 */ + pmouse = malloc(sizeof(struct usb_mouse)); + if (!pmouse) + { + fprintf(stderr, "can not malloc\n"); + return -1; + } + pmouse->endpoint = endpoint; + pmouse->interface = interface_num; + pmouse->handle = dev_handle; + pmouse->next = NULL; + + if (!list) + list = pmouse; + else + { + pmouse->next = list; + list = pmouse; + } + mouse_cnt++; + break; + } + + } + } + + } + + libusb_free_config_descriptor(config_desc); + } + + *usb_mouse_list = list; + return mouse_cnt; +} + + +static void mouse_irq(struct libusb_transfer *transfer) +{ + static int count = 0; + if (transfer->status == LIBUSB_TRANSFER_COMPLETED) + { + /* parser data */ + printf("%04d datas: ", count++); + for (int i = 0; i < transfer->actual_length; i++) + { + printf("%02x ", transfer->buffer[i]); + } + printf("\n"); + + } + + if (libusb_submit_transfer(transfer) < 0) + { + fprintf(stderr, "libusb_submit_transfer err\n"); + } +} + +int main(int argc, char **argv) +{ + int err; + libusb_device **devs; + int num_devices, num_mouse; + struct usb_mouse *pmouse; + + /* libusb_init */ + + err = libusb_init(NULL); + if (err < 0) { + fprintf(stderr, "failed to initialise libusb %d - %s\n", err, libusb_strerror(err)); + exit(1); + } + + /* get device list */ + if ((num_devices = libusb_get_device_list(NULL, &devs)) < 0) { + fprintf(stderr, "libusb_get_device_list() failed\n"); + libusb_exit(NULL); + exit(1); + } + fprintf(stdout, "libusb_get_device_list() ok\n"); + + /* get usb mouse */ + num_mouse = get_usb_mouses(devs, num_devices, &usb_mouse_list); + + if (num_mouse <= 0) + { + /* free device list */ + libusb_free_device_list(devs, 1); + libusb_exit(NULL); + exit(1); + } + fprintf(stdout, "get %d mouses\n", num_mouse); + + /* free device list */ + libusb_free_device_list(devs, 1); + + /* claim interface */ + pmouse = usb_mouse_list; + while (pmouse) + { + libusb_set_auto_detach_kernel_driver(pmouse->handle, 1); + err = libusb_claim_interface(pmouse->handle, pmouse->interface); + if (err) + { + fprintf(stderr, "failed to libusb_claim_interface\n"); + exit(1); + } + pmouse = pmouse->next; + } + fprintf(stdout, "libusb_claim_interface ok\n"); + + /* for each mouse, alloc transfer, fill transfer, submit transfer */ + pmouse = usb_mouse_list; + while (pmouse) + { + /* alloc transfer */ + pmouse->transfer = libusb_alloc_transfer(0); + + /* fill transfer */ + libusb_fill_interrupt_transfer(pmouse->transfer, pmouse->handle, pmouse->endpoint, pmouse->buf, + sizeof(pmouse->buf), mouse_irq, pmouse, 0); + + /* submit transfer */ + libusb_submit_transfer(pmouse->transfer); + + pmouse = pmouse->next; + } + + /* handle events */ + while (1) { + struct timeval tv = { 5, 0 }; + int r; + + r = libusb_handle_events_timeout(NULL, &tv); + if (r < 0) { + fprintf(stderr, "libusb_handle_events_timeout err\n"); + break; + } + } + + + /* libusb_close */ + pmouse = usb_mouse_list; + while (pmouse) + { + libusb_release_interface(pmouse->handle, pmouse->interface); + libusb_close(pmouse->handle); + pmouse = pmouse->next; + } + + free_usb_mouses(usb_mouse_list); + + libusb_exit(NULL); +} + + diff --git a/README.md b/README.md index d55d88e..8c488f2 100644 --- a/README.md +++ b/README.md @@ -675,6 +675,13 @@ git clone https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git 07.5_上机实验3_在板上实验 ``` +* 2022.09.28 发布"USB子系统" + + ```shell + 07.6_使用libusb异步函数读取USB鼠标 + 07.7_异步方式上机实验 + ``` + diff --git a/STM32MP157/doc_pic/12_USB/07_使用libusb读取鼠标数据.md b/STM32MP157/doc_pic/12_USB/07_使用libusb读取鼠标数据.md index eb6e9de..6b7b396 100644 --- a/STM32MP157/doc_pic/12_USB/07_使用libusb读取鼠标数据.md +++ b/STM32MP157/doc_pic/12_USB/07_使用libusb读取鼠标数据.md @@ -208,7 +208,149 @@ USB规范里为每个按键定义了16位的按键值,注意:它是16位的 ### 2.1 编写源码 ```c +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int err; + libusb_device *dev, **devs; + int num_devices; + int endpoint; + int interface_num; + int found = 0; + int transferred; + int count = 0; + unsigned char buffer[16]; + struct libusb_config_descriptor *config_desc; + struct libusb_device_handle *dev_handle = NULL; + + /* libusb_init */ + + err = libusb_init(NULL); + if (err < 0) { + fprintf(stderr, "failed to initialise libusb %d - %s\n", err, libusb_strerror(err)); + exit(1); + } + + /* get device list */ + if ((num_devices = libusb_get_device_list(NULL, &devs)) < 0) { + fprintf(stderr, "libusb_get_device_list() failed\n"); + libusb_exit(NULL); + exit(1); + } + fprintf(stdout, "libusb_get_device_list() ok\n"); + + /* for each device, get config descriptor */ + for (int i = 0; i < num_devices; i++) { + dev = devs[i]; + + /* parse interface descriptor, find usb mouse */ + err = libusb_get_config_descriptor(dev, 0, &config_desc); + if (err) { + fprintf(stderr, "could not get configuration descriptor\n"); + continue; + } + fprintf(stdout, "libusb_get_config_descriptor() ok\n"); + + for (int interface = 0; interface < config_desc->bNumInterfaces; interface++) { + const struct libusb_interface_descriptor *intf_desc = &config_desc->interface[interface].altsetting[0]; + interface_num = intf_desc->bInterfaceNumber; + + if (intf_desc->bInterfaceClass != 3 || intf_desc->bInterfaceProtocol != 2) + continue; + else + { + /* 找到了USB鼠标 */ + fprintf(stdout, "find usb mouse ok\n"); + for (int ep = 0; ep < intf_desc->bNumEndpoints; ep++) + { + if ((intf_desc->endpoint[ep].bmAttributes & 3) == LIBUSB_TRANSFER_TYPE_INTERRUPT || + (intf_desc->endpoint[ep].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) { + /* 找到了输入的中断端点 */ + fprintf(stdout, "find in int endpoint\n"); + endpoint = intf_desc->endpoint[ep].bEndpointAddress; + found = 1; + break; + } + + } + } + + if (found) + break; + } + + libusb_free_config_descriptor(config_desc); + + if (found) + break; + } + + if (!found) + { + /* free device list */ + libusb_free_device_list(devs, 1); + libusb_exit(NULL); + exit(1); + } + + if (found) + { + /* libusb_open */ + err = libusb_open(dev, &dev_handle); + if (err) + { + fprintf(stderr, "failed to open usb mouse\n"); + exit(1); + } + fprintf(stdout, "libusb_open ok\n"); + } + + /* free device list */ + libusb_free_device_list(devs, 1); + + /* claim interface */ + libusb_set_auto_detach_kernel_driver(dev_handle, 1); + err = libusb_claim_interface(dev_handle, interface_num); + if (err) + { + fprintf(stderr, "failed to libusb_claim_interface\n"); + exit(1); + } + fprintf(stdout, "libusb_claim_interface ok\n"); + + /* libusb_interrupt_transfer */ + while (1) + { + err = libusb_interrupt_transfer(dev_handle, endpoint, buffer, 16, &transferred, 5000); + if (!err) { + /* parser data */ + printf("%04d datas: ", count++); + for (int i = 0; i < transferred; i++) + { + printf("%02x ", buffer[i]); + } + printf("\n"); + } else if (err == LIBUSB_ERROR_TIMEOUT){ + fprintf(stderr, "libusb_interrupt_transfer timout\n"); + } else { + fprintf(stderr, "libusb_interrupt_transfer err : %d\n", err); + //exit(1); + } + + } + + /* libusb_close */ + libusb_release_interface(dev_handle, interface_num); + libusb_close(dev_handle); + libusb_exit(NULL); +} ``` @@ -230,7 +372,7 @@ gcc -o readmouse readmouse.c -lusb-1.0 -#### 2.2.2 在开发板上实验 +#### 2.2.2 在IMX6ULL开发板上实验 @@ -269,13 +411,295 @@ gcc -o readmouse readmouse.c -lusb-1.0 * 交叉编译app ```shell - arm-buildroot-linux-gnueabihf-gcc -o readmouse readmouse.c -lusb-1.0 + arm-buildroot-linux-gnueabihf-gcc -o readmouse.c -lusb-1.0 + ``` + + +* 在开发板上插入USB鼠标,执行命令 + + ```shell + ./readmouse ``` +#### 2.2.3 在STM32MP157开发板上实验 + +* STM32MP157的工具链里已经含有libusb,所以无需交叉编译、安装libusb + +* 交叉编译app + + ```shell + arm-buildroot-linux-gnueabihf-gcc -o readmouse readmouse.c -lusb-1.0 + ``` + +* 在开发板上插入USB鼠标,执行命令 + + ```shell + ./readmouse + ``` + + + + + +## 3. 使用异步接口读取鼠标数据 + +源码在GIT仓库如下位置: + +![image-20220929092859668](pic/61_libusb_async_usbmouse_src.png) + +### 3.1 编写源码 + +```c +#include +#include +#include +#include +#include + +#include + +struct usb_mouse { + struct libusb_device_handle *handle; + int interface; + int endpoint; + unsigned char buf[16]; + int transferred; + struct libusb_transfer *transfer; + struct usb_mouse *next; +}; + +static struct usb_mouse *usb_mouse_list; + + +void free_usb_mouses(struct usb_mouse *usb_mouse_list) +{ + struct usb_mouse *pnext; + while (usb_mouse_list) + { + pnext = usb_mouse_list->next; + free(usb_mouse_list); + usb_mouse_list = pnext; + } +} + + +/* */ +int get_usb_mouses(libusb_device **devs, int num_devices, struct usb_mouse **usb_mouse_list) +{ + int err; + libusb_device *dev; + int endpoint; + int interface_num; + struct libusb_config_descriptor *config_desc; + struct libusb_device_handle *dev_handle = NULL; + struct usb_mouse *pmouse; + struct usb_mouse *list = NULL; + int mouse_cnt = 0; + + /* for each device, get config descriptor */ + for (int i = 0; i < num_devices; i++) { + dev = devs[i]; + + /* parse interface descriptor, find usb mouse */ + err = libusb_get_config_descriptor(dev, 0, &config_desc); + if (err) { + fprintf(stderr, "could not get configuration descriptor\n"); + continue; + } + fprintf(stdout, "libusb_get_config_descriptor() ok\n"); + + for (int interface = 0; interface < config_desc->bNumInterfaces; interface++) { + const struct libusb_interface_descriptor *intf_desc = &config_desc->interface[interface].altsetting[0]; + interface_num = intf_desc->bInterfaceNumber; + + if (intf_desc->bInterfaceClass != 3 || intf_desc->bInterfaceProtocol != 2) + continue; + else + { + /* 找到了USB鼠标 */ + fprintf(stdout, "find usb mouse ok\n"); + for (int ep = 0; ep < intf_desc->bNumEndpoints; ep++) + { + if ((intf_desc->endpoint[ep].bmAttributes & 3) == LIBUSB_TRANSFER_TYPE_INTERRUPT || + (intf_desc->endpoint[ep].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) { + /* 找到了输入的中断端点 */ + fprintf(stdout, "find in int endpoint\n"); + endpoint = intf_desc->endpoint[ep].bEndpointAddress; + + /* libusb_open */ + err = libusb_open(dev, &dev_handle); + if (err) + { + fprintf(stderr, "failed to open usb mouse\n"); + return -1; + } + fprintf(stdout, "libusb_open ok\n"); + + /* 记录下来: 放入链表 */ + pmouse = malloc(sizeof(struct usb_mouse)); + if (!pmouse) + { + fprintf(stderr, "can not malloc\n"); + return -1; + } + pmouse->endpoint = endpoint; + pmouse->interface = interface_num; + pmouse->handle = dev_handle; + pmouse->next = NULL; + + if (!list) + list = pmouse; + else + { + pmouse->next = list; + list = pmouse; + } + mouse_cnt++; + break; + } + + } + } + + } + + libusb_free_config_descriptor(config_desc); + } + + *usb_mouse_list = list; + return mouse_cnt; +} + + +static void mouse_irq(struct libusb_transfer *transfer) +{ + static int count = 0; + if (transfer->status == LIBUSB_TRANSFER_COMPLETED) + { + /* parser data */ + printf("%04d datas: ", count++); + for (int i = 0; i < transfer->actual_length; i++) + { + printf("%02x ", transfer->buffer[i]); + } + printf("\n"); + + } + + if (libusb_submit_transfer(transfer) < 0) + { + fprintf(stderr, "libusb_submit_transfer err\n"); + } +} + +int main(int argc, char **argv) +{ + int err; + libusb_device **devs; + int num_devices, num_mouse; + struct usb_mouse *pmouse; + + /* libusb_init */ + + err = libusb_init(NULL); + if (err < 0) { + fprintf(stderr, "failed to initialise libusb %d - %s\n", err, libusb_strerror(err)); + exit(1); + } + + /* get device list */ + if ((num_devices = libusb_get_device_list(NULL, &devs)) < 0) { + fprintf(stderr, "libusb_get_device_list() failed\n"); + libusb_exit(NULL); + exit(1); + } + fprintf(stdout, "libusb_get_device_list() ok\n"); + + /* get usb mouse */ + num_mouse = get_usb_mouses(devs, num_devices, &usb_mouse_list); + + if (num_mouse <= 0) + { + /* free device list */ + libusb_free_device_list(devs, 1); + libusb_exit(NULL); + exit(1); + } + fprintf(stdout, "get %d mouses\n", num_mouse); + + /* free device list */ + libusb_free_device_list(devs, 1); + + /* claim interface */ + pmouse = usb_mouse_list; + while (pmouse) + { + libusb_set_auto_detach_kernel_driver(pmouse->handle, 1); + err = libusb_claim_interface(pmouse->handle, pmouse->interface); + if (err) + { + fprintf(stderr, "failed to libusb_claim_interface\n"); + exit(1); + } + pmouse = pmouse->next; + } + fprintf(stdout, "libusb_claim_interface ok\n"); + + /* for each mouse, alloc transfer, fill transfer, submit transfer */ + pmouse = usb_mouse_list; + while (pmouse) + { + /* alloc transfer */ + pmouse->transfer = libusb_alloc_transfer(0); + + /* fill transfer */ + libusb_fill_interrupt_transfer(pmouse->transfer, pmouse->handle, pmouse->endpoint, pmouse->buf, + sizeof(pmouse->buf), mouse_irq, pmouse, 0); + + /* submit transfer */ + libusb_submit_transfer(pmouse->transfer); + + pmouse = pmouse->next; + } + + /* handle events */ + while (1) { + struct timeval tv = { 5, 0 }; + int r; + + r = libusb_handle_events_timeout(NULL, &tv); + if (r < 0) { + fprintf(stderr, "libusb_handle_events_timeout err\n"); + break; + } + } + + + /* libusb_close */ + pmouse = usb_mouse_list; + while (pmouse) + { + libusb_release_interface(pmouse->handle, pmouse->interface); + libusb_close(pmouse->handle); + pmouse = pmouse->next; + } + + free_usb_mouses(usb_mouse_list); + + libusb_exit(NULL); +} +``` + + + + + +### 3.2 在开发板上实验 + diff --git a/STM32MP157/doc_pic/12_USB/07_使用libusb读取鼠标数据.tif b/STM32MP157/doc_pic/12_USB/07_使用libusb读取鼠标数据.tif deleted file mode 100644 index 7def9ca..0000000 Binary files a/STM32MP157/doc_pic/12_USB/07_使用libusb读取鼠标数据.tif and /dev/null differ diff --git a/STM32MP157/doc_pic/12_USB/pic/61_libusb_async_usbmouse_src.png b/STM32MP157/doc_pic/12_USB/pic/61_libusb_async_usbmouse_src.png new file mode 100644 index 0000000..9beb121 Binary files /dev/null and b/STM32MP157/doc_pic/12_USB/pic/61_libusb_async_usbmouse_src.png differ diff --git a/STM32MP157/source/A7/12_USB/02_libusb_mouse_sync/readmouse.c b/STM32MP157/source/A7/12_USB/02_libusb_mouse_sync/readmouse.c index eb4605e..4550ca1 100644 --- a/STM32MP157/source/A7/12_USB/02_libusb_mouse_sync/readmouse.c +++ b/STM32MP157/source/A7/12_USB/02_libusb_mouse_sync/readmouse.c @@ -8,8 +8,8 @@ int main(int argc, char **argv) { - int err; - libusb_device *dev, **devs; + int err; + libusb_device *dev, **devs; int num_devices; int endpoint; int interface_num; @@ -22,11 +22,11 @@ int main(int argc, char **argv) /* libusb_init */ - err = libusb_init(NULL); - if (err < 0) { - fprintf(stderr, "failed to initialise libusb %d - %s\n", err, libusb_strerror(err)); - exit(1); - } + err = libusb_init(NULL); + if (err < 0) { + fprintf(stderr, "failed to initialise libusb %d - %s\n", err, libusb_strerror(err)); + exit(1); + } /* get device list */ if ((num_devices = libusb_get_device_list(NULL, &devs)) < 0) { @@ -37,7 +37,7 @@ int main(int argc, char **argv) fprintf(stdout, "libusb_get_device_list() ok\n"); /* for each device, get config descriptor */ - for (int i = 0; i < num_devices; i++) { + for (int i = 0; i < num_devices; i++) { dev = devs[i]; /* parse interface descriptor, find usb mouse */ @@ -80,7 +80,7 @@ int main(int argc, char **argv) if (found) break; - } + } if (!found) { @@ -118,21 +118,21 @@ int main(int argc, char **argv) /* libusb_interrupt_transfer */ while (1) { - err = libusb_interrupt_transfer(dev_handle, endpoint, buffer, 16, &transferred, 5000); - if (!err) { - /* parser data */ + err = libusb_interrupt_transfer(dev_handle, endpoint, buffer, 16, &transferred, 5000); + if (!err) { + /* parser data */ printf("%04d datas: ", count++); for (int i = 0; i < transferred; i++) { printf("%02x ", buffer[i]); } printf("\n"); - } else if (err == LIBUSB_ERROR_TIMEOUT){ + } else if (err == LIBUSB_ERROR_TIMEOUT){ fprintf(stderr, "libusb_interrupt_transfer timout\n"); - } else { + } else { fprintf(stderr, "libusb_interrupt_transfer err : %d\n", err); //exit(1); - } + } } diff --git a/STM32MP157/source/A7/12_USB/03_libusb_mouse_async/readmouse.c b/STM32MP157/source/A7/12_USB/03_libusb_mouse_async/readmouse.c new file mode 100644 index 0000000..7459eab --- /dev/null +++ b/STM32MP157/source/A7/12_USB/03_libusb_mouse_async/readmouse.c @@ -0,0 +1,240 @@ +#include +#include +#include +#include +#include + +#include + +struct usb_mouse { + struct libusb_device_handle *handle; + int interface; + int endpoint; + unsigned char buf[16]; + int transferred; + struct libusb_transfer *transfer; + struct usb_mouse *next; +}; + +static struct usb_mouse *usb_mouse_list; + + +void free_usb_mouses(struct usb_mouse *usb_mouse_list) +{ + struct usb_mouse *pnext; + while (usb_mouse_list) + { + pnext = usb_mouse_list->next; + free(usb_mouse_list); + usb_mouse_list = pnext; + } +} + + +/* */ +int get_usb_mouses(libusb_device **devs, int num_devices, struct usb_mouse **usb_mouse_list) +{ + int err; + libusb_device *dev; + int endpoint; + int interface_num; + struct libusb_config_descriptor *config_desc; + struct libusb_device_handle *dev_handle = NULL; + struct usb_mouse *pmouse; + struct usb_mouse *list = NULL; + int mouse_cnt = 0; + + /* for each device, get config descriptor */ + for (int i = 0; i < num_devices; i++) { + dev = devs[i]; + + /* parse interface descriptor, find usb mouse */ + err = libusb_get_config_descriptor(dev, 0, &config_desc); + if (err) { + fprintf(stderr, "could not get configuration descriptor\n"); + continue; + } + fprintf(stdout, "libusb_get_config_descriptor() ok\n"); + + for (int interface = 0; interface < config_desc->bNumInterfaces; interface++) { + const struct libusb_interface_descriptor *intf_desc = &config_desc->interface[interface].altsetting[0]; + interface_num = intf_desc->bInterfaceNumber; + + if (intf_desc->bInterfaceClass != 3 || intf_desc->bInterfaceProtocol != 2) + continue; + else + { + /* 找到了USB鼠标 */ + fprintf(stdout, "find usb mouse ok\n"); + for (int ep = 0; ep < intf_desc->bNumEndpoints; ep++) + { + if ((intf_desc->endpoint[ep].bmAttributes & 3) == LIBUSB_TRANSFER_TYPE_INTERRUPT || + (intf_desc->endpoint[ep].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) { + /* 找到了输入的中断端点 */ + fprintf(stdout, "find in int endpoint\n"); + endpoint = intf_desc->endpoint[ep].bEndpointAddress; + + /* libusb_open */ + err = libusb_open(dev, &dev_handle); + if (err) + { + fprintf(stderr, "failed to open usb mouse\n"); + return -1; + } + fprintf(stdout, "libusb_open ok\n"); + + /* 记录下来: 放入链表 */ + pmouse = malloc(sizeof(struct usb_mouse)); + if (!pmouse) + { + fprintf(stderr, "can not malloc\n"); + return -1; + } + pmouse->endpoint = endpoint; + pmouse->interface = interface_num; + pmouse->handle = dev_handle; + pmouse->next = NULL; + + if (!list) + list = pmouse; + else + { + pmouse->next = list; + list = pmouse; + } + mouse_cnt++; + break; + } + + } + } + + } + + libusb_free_config_descriptor(config_desc); + } + + *usb_mouse_list = list; + return mouse_cnt; +} + + +static void mouse_irq(struct libusb_transfer *transfer) +{ + static int count = 0; + if (transfer->status == LIBUSB_TRANSFER_COMPLETED) + { + /* parser data */ + printf("%04d datas: ", count++); + for (int i = 0; i < transfer->actual_length; i++) + { + printf("%02x ", transfer->buffer[i]); + } + printf("\n"); + + } + + if (libusb_submit_transfer(transfer) < 0) + { + fprintf(stderr, "libusb_submit_transfer err\n"); + } +} + +int main(int argc, char **argv) +{ + int err; + libusb_device **devs; + int num_devices, num_mouse; + struct usb_mouse *pmouse; + + /* libusb_init */ + + err = libusb_init(NULL); + if (err < 0) { + fprintf(stderr, "failed to initialise libusb %d - %s\n", err, libusb_strerror(err)); + exit(1); + } + + /* get device list */ + if ((num_devices = libusb_get_device_list(NULL, &devs)) < 0) { + fprintf(stderr, "libusb_get_device_list() failed\n"); + libusb_exit(NULL); + exit(1); + } + fprintf(stdout, "libusb_get_device_list() ok\n"); + + /* get usb mouse */ + num_mouse = get_usb_mouses(devs, num_devices, &usb_mouse_list); + + if (num_mouse <= 0) + { + /* free device list */ + libusb_free_device_list(devs, 1); + libusb_exit(NULL); + exit(1); + } + fprintf(stdout, "get %d mouses\n", num_mouse); + + /* free device list */ + libusb_free_device_list(devs, 1); + + /* claim interface */ + pmouse = usb_mouse_list; + while (pmouse) + { + libusb_set_auto_detach_kernel_driver(pmouse->handle, 1); + err = libusb_claim_interface(pmouse->handle, pmouse->interface); + if (err) + { + fprintf(stderr, "failed to libusb_claim_interface\n"); + exit(1); + } + pmouse = pmouse->next; + } + fprintf(stdout, "libusb_claim_interface ok\n"); + + /* for each mouse, alloc transfer, fill transfer, submit transfer */ + pmouse = usb_mouse_list; + while (pmouse) + { + /* alloc transfer */ + pmouse->transfer = libusb_alloc_transfer(0); + + /* fill transfer */ + libusb_fill_interrupt_transfer(pmouse->transfer, pmouse->handle, pmouse->endpoint, pmouse->buf, + sizeof(pmouse->buf), mouse_irq, pmouse, 0); + + /* submit transfer */ + libusb_submit_transfer(pmouse->transfer); + + pmouse = pmouse->next; + } + + /* handle events */ + while (1) { + struct timeval tv = { 5, 0 }; + int r; + + r = libusb_handle_events_timeout(NULL, &tv); + if (r < 0) { + fprintf(stderr, "libusb_handle_events_timeout err\n"); + break; + } + } + + + /* libusb_close */ + pmouse = usb_mouse_list; + while (pmouse) + { + libusb_release_interface(pmouse->handle, pmouse->interface); + libusb_close(pmouse->handle); + pmouse = pmouse->next; + } + + free_usb_mouses(usb_mouse_list); + + libusb_exit(NULL); +} + +