linux中USB鼠标的驱动和应用代码示例

USB驱动的基本注册等操作可以参考:https://blog.csdn.net/u010299133/article/details/103741672

USB驱动:

参考:https://blog.csdn.net/weixin_30580341/article/details/98156443

note:要使用这个请配置这两个选项。需要取消内核中自带的USB驱动。

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/hid.h>

/* for apple IDs */
#ifdef CONFIG_USB_HID_MODULE
#include "../hid-ids.h"
#endif

/*
 * Version Information
 */
#define DRIVER_VERSION "v1.6"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB HID Boot Protocol mouse driver"
#define DRIVER_LICENSE "GPL"

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);

struct usb_mouse {
    char name[128];
    char phys[64];
    struct usb_device *usbdev;
    struct input_dev *dev;
    struct urb *irq;

    signed char *data;
    dma_addr_t data_dma;
};

static void usb_mouse_irq(struct urb *urb)
{
    struct usb_mouse *mouse = urb->context;
    signed char *data = mouse->data;
    struct input_dev *dev = mouse->dev;
    int status;

    switch (urb->status) {
        case 0:         /* success */
            break;
        case -ECONNRESET:   /* unlink */
        case -ENOENT:
        case -ESHUTDOWN:
            return;
            /* -EPIPE:  should clear the halt */
        default:        /* error */
            goto resubmit;
    }
    //HID协议中的鼠标数据说明 
    input_report_key(dev, BTN_LEFT,   data[0] & 0x01);
    input_report_key(dev, BTN_RIGHT,  data[0] & 0x02);
    input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);
    input_report_key(dev, BTN_SIDE,   data[0] & 0x08);
    input_report_key(dev, BTN_EXTRA,  data[0] & 0x10);

    input_report_rel(dev, REL_X,     data[1]);
    input_report_rel(dev, REL_Y,     data[2]);
    input_report_rel(dev, REL_WHEEL, data[3]);

    input_sync(dev);
resubmit:
    status = usb_submit_urb (urb, GFP_ATOMIC);
    if (status)
        dev_err(&mouse->usbdev->dev,
                "can't resubmit intr, %s-%s/input0, status %d\n",
                mouse->usbdev->bus->bus_name,
                mouse->usbdev->devpath, status);
}

static int usb_mouse_open(struct input_dev *dev)
{
    struct usb_mouse *mouse = input_get_drvdata(dev);

    mouse->irq->dev = mouse->usbdev;
    if (usb_submit_urb(mouse->irq, GFP_KERNEL))
        return -EIO;

    return 0;
}

static void usb_mouse_close(struct input_dev *dev)
{
    struct usb_mouse *mouse = input_get_drvdata(dev);

    usb_kill_urb(mouse->irq);
}

static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
    struct usb_device *dev = interface_to_usbdev(intf);
    struct usb_host_interface *interface;
    struct usb_endpoint_descriptor *endpoint;
    struct usb_mouse *mouse;
    struct input_dev *input_dev;
    int pipe, maxp;
    int error = -ENOMEM;

    interface = intf->cur_altsetting;
    //因鼠标就只有一个端点
    if (interface->desc.bNumEndpoints != 1)
        return -ENODEV;
    
    endpoint = &interface->endpoint[0].desc;
    if (!usb_endpoint_is_int_in(endpoint))
        return -ENODEV;

    pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
    maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));

    mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL);
    input_dev = input_allocate_device();
    if (!mouse || !input_dev)
        goto fail1;

    mouse->data = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &mouse->data_dma);
    if (!mouse->data)
        goto fail1;

    mouse->irq = usb_alloc_urb(0, GFP_KERNEL);
    if (!mouse->irq)
        goto fail2;

    mouse->usbdev = dev;
    mouse->dev = input_dev;

    if (dev->manufacturer)
        strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name));

    if (dev->product) {
        if (dev->manufacturer)
            strlcat(mouse->name, " ", sizeof(mouse->name));
        strlcat(mouse->name, dev->product, sizeof(mouse->name));
    }

    if (!strlen(mouse->name))
        snprintf(mouse->name, sizeof(mouse->name),
                 "USB HIDBP Mouse %04x:%04x",
                 le16_to_cpu(dev->descriptor.idVendor),
                 le16_to_cpu(dev->descriptor.idProduct));

    usb_make_path(dev, mouse->phys, sizeof(mouse->phys));
    strlcat(mouse->phys, "/input0", sizeof(mouse->phys));

    input_dev->name = mouse->name;
    input_dev->phys = mouse->phys;
    usb_to_input_id(dev, &input_dev->id);
    input_dev->dev.parent = &intf->dev;

    input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
    input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
            BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);

    input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
    input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
            BIT_MASK(BTN_EXTRA);

    input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);

    input_set_drvdata(input_dev, mouse);

    input_dev->open  = usb_mouse_open;
    input_dev->close = usb_mouse_close;

    usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,
                     (maxp > 8 ? 8 : maxp),
                     usb_mouse_irq, mouse, endpoint->bInterval);
    mouse->irq->transfer_dma = mouse->data_dma;
    mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

    error = input_register_device(mouse->dev);
    if (error)
        goto fail3;

    usb_set_intfdata(intf, mouse);
    return 0;
    
fail3:
    usb_free_urb(mouse->irq);
fail2:
    usb_free_coherent(dev, 8, mouse->data, mouse->data_dma);
fail1:
    input_free_device(input_dev);
    kfree(mouse);
    return error;
}

static void usb_mouse_disconnect(struct usb_interface *intf)
{
    struct usb_mouse *mouse = usb_get_intfdata (intf);

    usb_set_intfdata(intf, NULL);
    if (mouse) {
        usb_kill_urb(mouse->irq);
        input_unregister_device(mouse->dev);
        usb_free_urb(mouse->irq);
        usb_free_coherent(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);
        kfree(mouse);
    }
}

static struct usb_device_id usb_mouse_id_table [] = {
    {
        USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
        USB_INTERFACE_PROTOCOL_MOUSE)
    },
    { } /* Terminating entry */
};

MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);

static struct usb_driver usb_mouse_driver = {
    .name       = "usbmouse",
    .probe      = usb_mouse_probe,
    .disconnect = usb_mouse_disconnect,
    .id_table   = usb_mouse_id_table,
};

module_usb_driver(usb_mouse_driver);

应用层的USB测试代码:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>

#define  MACH_NAME          "mouse"    //匹配的名字
#define  EVENT_X_FORMAT     "/dev/event%d"   //dev目录下设备文件路径
int test_mouse(char *mousedev);
//根据设备名查找输入设备的下标
int get_event_x(char *mach_name);


int main(void)
{
    int ret = 0;
    int x   = 0;
    char file_path_buffer[100]= {0};

    x = get_event_x(MACH_NAME);
    if(x<0) {
        printf("%s不存在!\n",MACH_NAME);
        exit(0);
    }
    sprintf(file_path_buffer,EVENT_X_FORMAT,x);
    ret = test_mouse(file_path_buffer);

    return ret;
}



int init_device(char *dev)
{
    int fd;
    if((fd = open(dev, O_RDONLY)) < 0) {
        printf("Error open %s\n\n", dev);
        return -1;
    }

    return fd;
}

int test_mouse(char *mousedev)
{
    static struct input_event data;
    int fd;
    fd=init_device(mousedev);
    if( fd < 0) {
        return -1;
    }

    while(1) {
        read(fd, &data, sizeof(data));
        if (data.type == EV_KEY) {
            printf("type = EV_KEY, code = %s, value = %d\n",
                   data.code == BTN_LEFT ? "MOUSE_LEFT" :
                   data.code == BTN_RIGHT ? "MOUSE_RIGHT" :
                   data.code == BTN_MIDDLE ? "MOUSE_MIDDLE" :
                   data.code == BTN_SIDE ? "MOUSE_SIDE" :
                   "Unkonw", data.value);
				   
        } else if(data.type == EV_REL) {
            printf("type = EV_REL, code = %s, value = %d\n",
                   data.code == REL_X ? "REL_X" :
                   data.code == REL_Y ? "REL_Y" :
                   data.code == ABS_WHEEL ? "MOUSE_WHEEL" :
                   data.code == ABS_PRESSURE ? "ABS_PRESSURE" :
                   "Unkown", data.value);
				   
        }
    }
    return 0;
}


//判断文件是否存
int file_is_exist(char *filepath)
{
    int ret;
    if((access(filepath,F_OK))!=-1) {
        printf("文件 %s 存在.\n",filepath);
        ret = 0;
    } else {
        printf("%s不存在!\n",filepath);
        ret = -1;
    }
    return ret;
}


//根据设备名查找输入设备的下标
int get_event_x(char *mach_name)
{
//搜索路径
#define EVENT_FILE_FORMAT  "/sys/class/input/event%d/device/name"
    int i= 0;
    int j;
	size_t len = 0;
	ssize_t read;
    FILE * flip;
	char *line;
    char file_path_buffer[100]= {0};
    char file_data_buffer[100]= {0};
    char tem_mach_name[100]= {0};
    for(i=0; i<32; i++) {
        sprintf(file_path_buffer,EVENT_FILE_FORMAT,i);
        if(!file_is_exist(file_path_buffer)) {
            flip = fopen(file_path_buffer, "r");
            if(flip==NULL) {
                printf("cant open the file\n");
                continue;
            }

            //fread(file_data_buffer,100,1,flip);
		   read = getline(&line, &len, flip);
			if(read == -1)
			{
				printf("read the file error\n");
				return -1;
			}
			
			stpncpy(file_data_buffer,line,read );
			if (line)
				free(line);

			printf("%s\n",file_data_buffer);
			
            j = 0;
            while(file_data_buffer[j++]) {
                file_data_buffer[j] = tolower(file_data_buffer[j]);
            }

            j = 0;
            while(tem_mach_name[j++]) {
                tem_mach_name[j] = tolower(mach_name[j]);
            }

            if(strstr(file_data_buffer,mach_name)) {
                return i;
            }
        }
    }

    return -1;
}

int file_permission(char *filepath)
{
    if((access(filepath,F_OK))!=-1) {
        printf("文件 %s 存在.\n",filepath);
    } else {
        printf("%s不存在!\n",filepath);
    }

    if(access(filepath,R_OK)!=-1) {
        printf("%s 有可读权限\n",filepath);
    } else {
        printf("test.c 不可读.\n");
    }

    if(access(filepath,W_OK)!=-1) {
        printf("%s 有可写权限\n",filepath);
    } else {
        printf("%s 不可写.\n",filepath);
    }
    if(access(filepath,X_OK)!=-1) {
        printf("%s 有可执行权限\n",filepath);
    } else {
        printf("%s 不可执行.\n",filepath);
    }
}

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值