u1

https://blog.csdn.net/baidu_19348579/article/details/126096687

设备树

这里就不需要设备树参与了,就像IIC一样,是挂载到现有的总线上,所以这里只需要注册usb设备就可以了。
代码框架(HID)

先来看一个通用的框架

#include <linux/init.h>
#include <linux/module.h>
#include <linux/usb.h>
 
 
//定义USB的IDTAB
static const struct usb_device_id my_usb_ids[] = 
{
    {USB_DEVICE(0x093a,0x2510)},
    {USB_DEVICE(0x0c45,0x760b)},
    {}
};
 
/*
MODULE_DEVICE_TABLE 有两个功能。
一是:将设备加入到外设队列中,
二是告诉程序阅读者该设备是热插拔设备或是说该设备支持热插拔功能。
该宏定义在<linux/module.h>下
这个宏有两个参数,第一个参数设备名,第二个参数该设备加入到模块中时对应产生的设备搜索符号,这个宏生成了一个名为__mod_pci_device_table
局部变量,这个变量指向第二个参数
*/
MODULE_DEVICE_TABLE (usb,my_usb_ids);
 
//USB设备信息与驱动端匹配成功的时候调用。
static int myusb_probe(struct usb_interface *intf,const struct usb_device_id *id)  //资源探索函数
{
    printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
    return 0;
}
 
//USB断开的时候调用
static void myusb_disconnect(struct usb_interface *intf)
{
    printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
}
 
//定义USB驱动结构体 
static struct usb_driver myusb_driver = 
{
    .name = "myusb_drv",
    .id_table = my_usb_ids,
    .probe = myusb_probe,
    .disconnect = myusb_disconnect
};
 
static int __init myusb_init(void)
{
    //注册USB设备驱动
    printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
    usb_register(&myusb_driver);
    return 0;
}
 
static void __exit myusb_exit(void)
{
     //注销USB设备驱动
     printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
     usb_deregister(&myusb_driver);
}
 
module_init(myusb_init);
module_exit(myusb_exit);
MODULE_AUTHOR("PGG");
MODULE_LICENSE("GPL");
注册中断

修改probe函数

static int size;
static unsigned char *buf =NULL;
static struct urb *myurb=NULL;
static dma_addr_t buf_phy;

static int myusb_probe(struct usb_interface *intf,const struct usb_device_id *id)  //资源探索函数
{
    struct usb_device *dev = NULL;
    struct usb_host_interface *interface = NULL;
    struct usb_endpoint_descriptor *endpoint = NULL;
    int pipe;

    printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
    printk("USB驱动匹配成功! ID: 0x%X,0x%X\n",id->idVendor,id->idProduct);
     
    /*通过接口获取设备信息*/
    dev = interface_to_usbdev(intf);
    /*获取当前接口设置*/
    interface=intf->cur_altsetting;
    /*获取端点描述符*/
    endpoint = &interface->endpoint[0].desc;

    
    /*中断传输:创建输入管道*/
    pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
    /*从端点描述符中获取传输的数据大小 */
    size = endpoint->wMaxPacketSize;
    printk("设备传输数据包大小:%d\n",size);
    /*分配数据传输缓冲区*/
    buf = usb_alloc_coherent(dev,size,GFP_ATOMIC,&buf_phy);

    
    /*分配新的urb,urb是usb设备驱动中用来描述与usb设备通信所用的基本载体和核心数据结构*/
    myurb = usb_alloc_urb(0,GFP_KERNEL);
    /*中断方式初始化urb*/
    usb_fill_int_urb(myurb,dev,pipe,buf,size,usb_complete,NULL,endpoint->bInterval);
    myurb->transfer_dma = buf_phy;
    myurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
    
    /*为端点提交异步传输请求*/
    usb_submit_urb(myurb, GFP_KERNEL);    
    
    return 0;
}
当中断设备有数据发送上来的时候,会触发中断,数据就在缓冲区中。
可以在回调中查看数据,按照缓存大小,输出一下数据看一下。

static void usb_irq_work(struct urb *urb)
{
    int i;
    for(i=0;i<size;i++)
    {
        printk("0x%x ",buf[i]);
    }
    printk("\n");
    /* 重新提交异步请求*/
    usb_submit_urb(myurb, GFP_KERNEL);
}

然后断开的时候会调用disconnect函数,需要释放资源

static void myusb_disconnect(struct usb_interface *intf)
{
    printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
    
    struct usb_device *dev = interface_to_usbdev(intf);
    usb_kill_urb(myurb);
    usb_free_urb(myurb);
    usb_free_coherent(dev,size,buf, buf_phy);
    printk("USB 设备释放成功!\n"); 

}

然后测试一下模块驱动。
先装载驱动,再插上usb鼠标

root@raspberrypi:/home/pgg/work/driver# insmod myusbmouse.ko 
root@raspberrypi:/home/pgg/work/driver# dmesg 
[ 5684.233197] drivers/char/myusbmouse.c myusb_init 116
[ 5684.233391] usbcore: registered new interface driver myusb_drv
root@raspberrypi:/home/pgg/work/driver# dmesg 
[ 5684.233197] drivers/char/myusbmouse.c myusb_init 116
[ 5684.233391] usbcore: registered new interface driver myusb_drv
[ 5702.442546] usb 1-1.3: new low-speed USB device number 8 using dwc_otg
[ 5702.577376] usb 1-1.3: New USB device found, idVendor=093a, idProduct=2510, bcdDevice= 1.00
[ 5702.577413] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 5702.577433] usb 1-1.3: Product: USB Optical Mouse
[ 5702.577450] usb 1-1.3: Manufacturer: PixArt
[ 5702.578716] drivers/char/myusbmouse.c myusb_probe 56
[ 5702.578738] USB驱动匹配成功! ID: 0x93A,0x2510
[ 5702.578752] 设备传输数据包大小:4

可以看到驱动匹配成功,数据包大小为4。

移动一下鼠标看看。打印了很多数据。

[ 5771.634961] 0x0 
[ 5771.635024] 0xff 
[ 5771.635044] 0xff 
[ 5771.635061] 0x0 

[ 5771.683970] 0x0 
[ 5771.684017] 0xff 
[ 5771.684036] 0xff 
[ 5771.684053] 0x0 

[ 5772.644962] 0x0 
[ 5772.645013] 0xfe 
[ 5772.645033] 0x0 
[ 5772.645050] 0x0 

[ 5773.925960] 0x0 
[ 5773.926013] 0xff 
[ 5773.926033] 0x0 
[ 5773.926050] 0x0 

[ 5796.702962] 0x0 
[ 5796.703014] 0xff 
[ 5796.703035] 0xff 
[ 5796.703052] 0x0 

 

posted @ 2022-12-14 20:48  cnchengv  阅读(393)  评论(0编辑  收藏  举报