usb设备驱动程序(二)

1.lsusb

lsusb -v -d 0x2bdf:   查看usb描述符等信息 (Ubuntu中使用)2bdf为ID号

2.usb驱动程序框架

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 



static struct video_device *myuvc_vdev;


static struct usb_device_id myuvc_ids[] = {
	/* Generic USB Video Class */
		{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },/*vdieocontral interface*/
		{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 2, 0) },
		{}
};

/*A2 确定他是否是视频设备*/
static int vidioc_querycap(struct file *file, void *priv,
					struct v4l2_capability *v)
{


	return 0;
}
/* A3 列举支持哪种格式*/
static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
											   struct v4l2_fmtdesc *f)
{
	
	return 0;
							
}
/*A4 返回当前所使用的格式*/
static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
										struct v4l2_format *f)
{

return 0;
}
/*A5 测试驱动程序是否支持某种格式*/
static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
									struct v4l2_format *f)
{
	return 0;

}
/*A6*/
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
				struct v4l2_format *f)
{
	return 0;

}
/*A7 APP调用该ioctl让驱动分配若干个缓存,APP将从这些缓存里面读取视频数据*/
int vb2_ioctl_reqbufs(struct file *file, void *priv,
			  struct v4l2_requestbuffers *p)
{
	return 0;

}
/*A8 查询缓存状态,比如地址信息(APP可以用)*/
int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
{

return 0;
}
/*A10 把缓冲区放入队列,底层硬件操作函数将会把数据放入这个队列的缓存*/
int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
{
	return 0;

}
/*A13 APP通过poll/select确定有数据之后,把缓存从队列中取出来*/
/*A14 之前已经通过mmap映射了缓存,APP可以直接读取数据*/
/*A15 在此调用vb2_ioctl_qbuf把缓存放入队列*/
/*A16 调用poll*/
/*又进入A13,开始进行循环,直到vb2_ioctl_streamoff 退出*/
int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
{
	return 0;
}

/*A11 启动传输*/
int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
{
	return 0;
}
			
/*A17 停止*/
int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
{
	return 0;
}


static const struct v4l2_ioctl_ops myuvc_fops ={
		// 表示他是一个摄像头设备
		.vidioc_querycap			= vidioc_querycap,

		/*用于列举,获得,测试,设置摄像头的数据的格式*/
		.vidioc_enum_fmt_vid_cap	= vidioc_enum_fmt_vid_cap,
		.vidioc_g_fmt_vid_cap		= vidioc_g_fmt_vid_cap,
		.vidioc_try_fmt_vid_cap 	= vidioc_try_fmt_vid_cap,
		.vidioc_s_fmt_vid_cap		= vidioc_s_fmt_vid_cap,
		/*缓冲区操作:申请,查询,放入队列,取出队列*/
		.vidioc_reqbufs 			= vb2_ioctl_reqbufs,
		.vidioc_querybuf			= vb2_ioctl_querybuf,
		.vidioc_qbuf				= vb2_ioctl_qbuf,
		.vidioc_dqbuf				= vb2_ioctl_dqbuf,

	     /*启动,停止*/
		.vidioc_streamon			= vb2_ioctl_streamon,
		.vidioc_streamoff			= vb2_ioctl_streamoff,
	
	};

static int myuvc_release(struct video_device *vdev)
{
	return 0;
}
/*A1*/
static int myuvc_open(struct file *filp)
{
	return 0;
}
/*A18 关闭*/
static int myuvc_close(struct file *filp)
{
	return 0;
}

/*A9 把缓存映射到APP的空间,以后APP就可以直接操作了*/
static int myuvc_mmap(struct file *file, struct vm_area_struct *vma)
{

	return 0;
}
/*A12 APP调用poll/select 来确定缓存是有就绪(有数据)*/
unsigned int myuvc_poll(struct file *file, poll_table *wait)
{
	
	return 0;
}

static const struct v4l2_file_operations myuvc_fops = {
		.owner		= THIS_MODULE,
		.open		= myuvc_open,
		.close      = myuvc_close,
		.release	= myuvc_release,
		.ioctl      = video_ioctl2,
		.mmap		= myuvc_mmap,
		.poll		= myuvc_poll,
};

static int myuvc_probe(struct usb_interface *intf,const struct usb_device_id *id)   //usb_interface->usb_host_interface
{
	int m,j
	struct usb_device *udev = interface_to_usbdev(intf); /*可在结构体usb_device获得设备描述符:struct usb_device_descriptor descriptor;*/
	struct usb_device_descriptor *descriptor = &udev->descriptor;
	/*获取IAD*/
	struct usb_interface_assoc_descriptor *assoc_desc;
	assoc_desc = udev->actconfig->intf_assoc[0];
	/*视频流接口中包括一个接口和与其对应的多个转换设置接口(Alternate Setting)。打印接口描述符*/
	struct usb_interface_descriptor	*interface;
	struct usb_endpoint_descriptor	*endpoint;
	static int count = 0;
	printk("disconnect %d\n",count++);

    if (count==2)  /*因为ids里面有两个 probe会被调用两次*/
    {
	/*1. 分配一个 video_device结构体*/
		myuvc_vdev = video_device_alloc();

	/*2. 设置*/

	/*3. 注册*/
		video_register_device(myuvc_vdev, VFL_TYPE_GRABBER,-1)/*-1则为自动分配次设备号*/;
    }
	
	return 0;
};
static void myuvc_disconnect(struct usb_interface *intf)
{
	static int count = 0;
	printk("disconnect %d\n",count++);
	if (count==2)  /*因为ids里面有两个 probe会被调用两次*/
    {
		video_unregister_device(myuvc_vdev);

		myuvc_vdev = video_device_release();

    }
};


struct usb_driver myuvc_driver = {
		.name		= "my_uvcvideo",
		.probe		= myuvc_probe,
		.disconnect	= myuvc_disconnect,
		//.suspend	= uvc_suspend,
		//.resume		= uvc_resume,
		//.reset_resume	= uvc_reset_resume,
		.id_table	= myuvc_ids,
		//.supports_autosuspend = 1,
};



static int  myuvc_init(void)
{
	int ret ;
	ret = usb_register(&myuvc_driver);
	if (ret < 0) {
		return ret;
	}
	return 0;
}

static void  myuvc_cleanup(void)
{
	usb_deregister(&myuvc_driver);
}

module_init(myuvc_init);
module_exit(myuvc_cleanup);
MODULE_LICENSE("GPL");















你可能感兴趣的:(linux,c语言)