- 论坛徽章:
- 0
|
前提:可以确定USB驱动程序已经成功注册。
将USB驱动程序编译成模块加载进Linux系统中,然后将U盘插入Linux系统中,结果并没有打印出skel_probe()函数中调试信息,
驱动程序如下:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h> /*kmalloc*/
#include <linux/kref.h> /*kref*/
#include <linux/usb.h>
#include <asm/uaccess.h> /*copy_to_user()*/
#include <linux/smp_lock.h> /*lock_kernel()*/
#define USB_SKEL_VENDOR_ID 0x058f //定义制造商ID
#define USB_SKEL_PRODUCT_ID 0x6387 //定义产品ID
//该驱动程序支持的设备列表
static struct usb_device_id skel_table[]={
/*根据制造商ID、产品ID生成usb_device_id结构体实例*/
{USB_DEVICE(USB_SKEL_VENDOR_ID,USB_SKEL_PRODUCT_ID)},
{}
};
MODULE_DEVICE_TABLE(usb,skel_table);//导出到用户空间
#define USB_SKEL_MINOR_BASE 192 //定义次设备号
struct usb_skel{
struct usb_device *udev;
struct usb_interface *interface; //设备的接口
unsigned char *bulk_in_buffer; //接收数据的缓冲区
size_t bulk_in_size; //缓冲区的大小
__u8 bulk_in_endpointAddr; //输入端点
__u8 bulk_out_endpointAddr; //输出端点
struct kref kref; //urb引用计数
};
#define to_skel_dev(d) container_of(d,struct usb_skel,kref)
static struct usb_driver skel_driver; //定义USB设备驱动
static void skel_delete(struct kref *kref)
{
struct usb_skel *dev=to_skel_dev(kref);
usb_put_dev(dev->udev); //减小usb_device的引用计数
kfree(dev->bulk_in_buffer); //释放数据的缓冲区
kfree(dev);
}
static int skel_open(struct inode *inode,struct file *file)
{
struct usb_skel *dev;
struct usb_interface *interface;
int subminor; //定义设备文件的次设备号
subminor=iminor(inode); //得到次设备号
//遍历USB驱动,找到与subminor相匹配的设备驱动
interface=usb_find_interface(&skel_driver,subminor);
if(!interface)
{
err("%s-error,can't find device for minor %d",__FUNCTION__,subminor);
return -ENODEV;
}
dev=usb_get_intfdata(interface); //获取数据
if(!dev)
return -ENODEV;
kref_get(&dev->kref); //将refcount加1
file->private_data=dev; //将dev保存在private_data中
return 0;
}
static int skel_release(struct inode *inode,struct file *file)
{
struct usb_skel *dev;
dev=(struct usb_skel *)file->private_data;//得到usb_skel
if(dev==NULL)
return -ENODEV;
kref_put(&dev->kref,skel_delete);
return 0;
}
static ssize_t skel_read(struct file *file,char __user *buffer,size_t count,loff_t *ppos)
{
struct usb_skel *dev;
int retval=0;
dev=(struct usb_skel *)file->private_data; //得到usb_skel
/*进行阻塞的批量读以从设备获取数据*/
//usb_rcvbulkpipe:把指定USB设备的指定端点号设置为一个批量IN端点
retval=usb_bulk_msg(dev->udev,usb_rcvbulkpipe(dev->udev,dev->bulk_in_endpointAddr),
dev->bulk_in_buffer,min(dev->bulk_in_size,count),&count,HZ*10);
if(!retval)
{
//如果读成功,复制数据到用户空间
if(copy_to_user(buffer,dev->bulk_in_buffer,count))
retval=-EFAULT;
else
retval=count;
}
return retval;
}
static void skel_write_bulk_callback(struct urb *urb,struct pt_regs *regs)
{
if(urb->status && !(urb->status==-ENOENT||urb->status==-ECONNRESET||urb->status==-ESHUTDOWN))
/*未能正确的传输*/
dbg("%s-nonzero write bulk status received: %d\n",__FUNCTION__,urb->status);
usb_buffer_free(urb->dev,urb->transfer_buffer_length,urb->transfer_buffer,urb->transfer_dma);
}
static ssize_t skel_write(struct file *file,const char __user *user_buffer,size_t count,loff_t *ppos)
{
struct usb_skel *dev;
int retval=0;
struct urb *urb=NULL;
char *buf=NULL;
dev=(struct usb_skel *)file->private_data;
if(count==0)
return count;
/*创建URB结构体*/
//0:表示不创建等时数据包
urb=usb_alloc_urb(0,GFP_KERNEL);
if(!urb)
{
return -ENOMEM;
}
buf=usb_buffer_alloc(dev->udev,count,GFP_KERNEL,&urb->transfer_dma);/*申请内存空间*/
if(!buf)
{
retval=-ENOMEM;
goto fail_buffer_alloc;
}
if(copy_from_user(buf,user_buffer,count))
{
retval=-EFAULT;
goto fail_copy;
}
/*正确地初始化urb*/
usb_fill_bulk_urb(urb,dev->udev,usb_sndbulkpipe(dev->udev,dev->bulk_out_endpointAddr),
buf,count,skel_write_bulk_callback,dev);
urb->transfer_flags |=URB_NO_TRANSFER_DMA_MAP; //即将传输DMA缓冲区
retval=usb_submit_urb(urb,GFP_KERNEL); //提交给USB核心
if(retval)
{
err("%s-failed submitting write urb,error %d",__FUNCTION__,retval);
goto fail_copy;
}
usb_free_urb(urb);
return count;
fail_copy:
usb_buffer_free(dev->udev,count,buf,urb->transfer_dma);//释放内存
kfree(buf);
fail_buffer_alloc:
usb_free_urb(urb);//释放分配的结构体
return retval;
}
static struct file_operations skel_fops={
.owner = THIS_MODULE,
.open = skel_open,
.release = skel_release,
.read = skel_read,
.write = skel_write,
};
static struct usb_class_driver skel_class={
.name = "usb/skel%d", //sysfs中用来描述设备名
.fops = &skel_fops, //文件操作结构体指针
.mode = S_IRUSR | S_IWUSR, //只提供了设备文件属主的读和写访问权限
.minor_base = USB_SKEL_MINOR_BASE, //开始次设备号
};
static int skel_probe(struct usb_interface *interface,const struct usb_device_id *id)
{
struct usb_skel *dev=NULL; //定义usb_skel
struct usb_host_interface *iface_desc; //表示设置
struct usb_endpoint_descriptor *endpoint; //表示端点描述
size_t buffer_size; //定义最大信息包的大小
int i;
int retval=-ENOMEM;
dev=kmalloc(sizeof(struct usb_skel),GFP_KERNEL); /*分配内存空间*/
if(dev==NULL)
{
err("Out of memory\n");
return -ENOMEM;
}
memset(dev,0x00,sizeof(*dev)); //将分配的内存空间清0
/*初始化usb_skel结构体*/
kref_init(&dev->kref); //初始化refcount为1
/*
*interface_to_usbdev:转换为usb_device结构体
*usb_get_dev:增加usb_device的引用计数
*/
dev->udev=usb_get_dev(interface_to_usbdev(interface));
dev->interface=interface;
/*设置端点信息*/
iface_desc=interface->cur_altsetting; //初始化该接口的当前活动设置
for(i=0;i<iface_desc->desc.bNumEndpoints;++i)
{
endpoint=&iface_desc->endpoint[i].desc; //初始化端点描述
if(!dev->bulk_in_endpointAddr&&(endpoint->bEndpointAddress&USB_DIR_IN)&&
((endpoint->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)==USB_ENDPOINT_XFER_BULK))
{
/*得到正确的端点类型*/
buffer_size=endpoint->wMaxPacketSize;
dev->bulk_in_size=buffer_size; //初始化最大信息包的大小
//初始化输入端点
dev->bulk_in_endpointAddr=endpoint->bEndpointAddress;
//初始化缓冲区
dev->bulk_in_buffer=kmalloc(buffer_size,GFP_KERNEL);
if(!dev->bulk_in_buffer)
{
err("Could not allocate bulk_in_buffer:\n");
goto error;
}
}
if(!dev->bulk_out_endpointAddr&&(endpoint->bEndpointAddress&USB_DIR_OUT)&&
((endpoint->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)==USB_ENDPOINT_XFER_BULK))
{
//初始化输出端口
dev->bulk_out_endpointAddr=endpoint->bEndpointAddress;
}
}
if(!(dev->bulk_in_endpointAddr&&dev->bulk_out_endpointAddr))
{
err("Could not find both bulk-in and bulk-out endpoints:\n");
goto error;
}
usb_set_intfdata(interface,dev); /*把数据指针保存到这个接口设备中*/
/*现在可以注册设备*/
retval=usb_register_dev(interface,&skel_class);
if(retval)
{
err("Not able to get a minor for this device.\n");
usb_set_intfdata(interface,NULL);
goto error;
}
printk(KERN_DEBUG"USB Skeleton device now attached to USB Skel-%d\n",interface->minor);
return 0;
error:
if(dev)
//skel_delete:函数指针,指向一个清理函数,不能为空
kref_put(&dev->kref,skel_delete);//将refcount减1
return retval;
}
static void skel_disconnect(struct usb_interface *interface)
{
struct usb_skel *dev;
int minor=interface->minor; //得到次设备号
lock_kernel(); //内核锁,相当于P操作
dev=usb_get_intfdata(interface); //访问dev
usb_set_intfdata(interface,NULL); //设置数据指针为NULL
unlock_kernel();//相当于V操作
kref_put(&dev->kref,skel_delete);
info("USB Skeleton #%d now disconnected",minor);
}
static struct usb_driver skel_driver={
.name = "skeleton",
.id_table = skel_table,
.probe = skel_probe,
.disconnect= skel_disconnect,
};
//模块加载函数
static int __init usb_skel_init(void)
{
int result;
/*把该驱动程序注册到USB子系统*/
result=usb_register(&skel_driver);
if(result)
err("usb_register failed.Error number %d",result);
return result;
}
//模块卸载函数
static void __exit usb_skel_exit(void)
{
/*把该驱动程序从USB子系统注销*/
usb_deregister(&skel_driver);
}
module_init(usb_skel_init);
module_exit(usb_skel_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("chenqi");
不知道问题出在哪里,希望好心人能帮助我解决这个问题,在此谢谢了!!!
|
|