mirror of
https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git
synced 2025-12-02 12:51:16 +08:00
使用libusb异步函数读取USB鼠标、上机实验
This commit is contained in:
@@ -208,7 +208,149 @@ USB规范里为每个按键定义了16位的按键值,注意:它是16位的
|
|||||||
### 2.1 编写源码
|
### 2.1 编写源码
|
||||||
|
|
||||||
```c
|
```c
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
|
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
|
* 交叉编译app
|
||||||
|
|
||||||
```shell
|
```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仓库如下位置:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 3.1 编写源码
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
|
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 在开发板上实验
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
BIN
IMX6ULL/doc_pic/12_USB/pic/61_libusb_async_usbmouse_src.png
Normal file
BIN
IMX6ULL/doc_pic/12_USB/pic/61_libusb_async_usbmouse_src.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.5 KiB |
240
IMX6ULL/source/12_USB/03_libusb_mouse_async/readmouse.c
Normal file
240
IMX6ULL/source/12_USB/03_libusb_mouse_async/readmouse.c
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -675,6 +675,13 @@ git clone https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git
|
|||||||
07.5_上机实验3_在板上实验
|
07.5_上机实验3_在板上实验
|
||||||
```
|
```
|
||||||
|
|
||||||
|
* 2022.09.28 发布"USB子系统"
|
||||||
|
|
||||||
|
```shell
|
||||||
|
07.6_使用libusb异步函数读取USB鼠标
|
||||||
|
07.7_异步方式上机实验
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -208,7 +208,149 @@ USB规范里为每个按键定义了16位的按键值,注意:它是16位的
|
|||||||
### 2.1 编写源码
|
### 2.1 编写源码
|
||||||
|
|
||||||
```c
|
```c
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
|
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
|
* 交叉编译app
|
||||||
|
|
||||||
```shell
|
```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仓库如下位置:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 3.1 编写源码
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
|
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 在开发板上实验
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
BIN
STM32MP157/doc_pic/12_USB/pic/61_libusb_async_usbmouse_src.png
Normal file
BIN
STM32MP157/doc_pic/12_USB/pic/61_libusb_async_usbmouse_src.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.5 KiB |
240
STM32MP157/source/A7/12_USB/03_libusb_mouse_async/readmouse.c
Normal file
240
STM32MP157/source/A7/12_USB/03_libusb_mouse_async/readmouse.c
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user