⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zc0301_urb.c

📁 适合用于嵌入式的zc301摄像头驱动。解压缩之后放在/driver/media/video/zc0301目录下
💻 C
字号:
/*	This file contains all operatinos for URB * *	It's created by WE.XCC at 2008.05.04 *
 *	Author's E-mail:84318391@163.com
 * */#include <linux/module.h>#include <linux/usb.h>#include <linux/types.h>#include <media/v4l2-common.h>#include <linux/videodev.h>#include "zc0301_debug.h"#include "zc0301_struct.h"#include "zc0301_descriptors.h"void zc0301_urb_complete(struct urb *urb){	struct zc0301_device *cam = NULL;	struct zc0301_frame *f = NULL;	u32 imagesize = 0;	static u32 data_length = 0;	u8 i = 0;	int err = 0;	if (urb == NULL)	{		debug_error("zc0301_urb_complete:urb is null\n");		return;	}	cam = urb->context;	if (urb->status == -ENOENT) //if uses kill, it will enable	{		debug_error("zc0301_urb_complete:status is -ENOENT\n");		return;	}		if (cam->d_state & DISCONNECTED)		return;	if (cam->d_state & MISCONFIGED)	{		wake_up_interruptible(&cam->wait_frame);		return;	}	if (cam->s_state == STREAM_OFF || list_empty(&cam->inqueue))		goto resubmit;	f = list_entry(cam->inqueue.next, struct zc0301_frame, queue);	imagesize = 640 * 480 * 8 / 8;	for (i = 0; i < ZC0301_PACKETS; i++)	{		unsigned int len = 0, status = 0;		void *pos = NULL;		u16 *soi = NULL;		u8 sof = 0;		len    = urb->iso_frame_desc[i].actual_length;		status = urb->iso_frame_desc[i].status;		pos    = urb->iso_frame_desc[i].offset + urb->transfer_buffer;		if (status)		{			debug_error("zc0301_urb_complete:urb's packet's status is wrong\n");			f->f_state = F_ERROR;			continue;		}		sof = (*(soi = pos) == 0xd8ff); //if I have manual, I can understand it/start_of_frame:		if (sof)		{			f->f_state = F_GRABBING;			do_gettimeofday(&f->buf.timestamp); //I don't know the function							    //if I clear it, the driver also works well		}		if (f->f_state == F_GRABBING)		{			if (sof && data_length)				goto end_of_frame;			if (data_length + len > imagesize)			{				debug_error("exceeded imagesize\n");				f->f_state = F_ERROR;				continue;			}			memcpy(f->bufmem + data_length, pos, len);			data_length += len;			if (data_length == imagesize)			{end_of_frame:				f->f_state = F_DONE;				f->buf.bytesused = data_length;				data_length = 0;				spin_lock(&cam->queue_lock);				list_move_tail(&f->queue, &cam->outqueue);				//this if-else is so classical, it can speed up the display				//the thought like DMA				if (list_empty(&cam->inqueue))					f = NULL;				else					f = list_entry(cam->inqueue.next, struct zc0301_frame, queue);				spin_unlock(&cam->queue_lock);				wake_up_interruptible_nr(&cam->wait_frame, 1);				if (f == NULL)					goto resubmit;				else					goto start_of_frame;			}		}	}resubmit:	urb->dev = cam->usbdev;	err = usb_submit_urb(urb, GFP_ATOMIC); //takes GFP_ATOMIC if in urb complete	if (err < 0)		debug_error("resubmit urb failed\n");	return;}int zc0301_urb_start(struct zc0301_device *cam){	struct usb_device *udev = NULL;	struct usb_host_interface *altsetting = NULL;	u16 psz = 0;	s8 i = 0, j = 0;	int err = 0, flag = 0;	if (cam == NULL)	{		debug_error("zc0301_urb_start:cam is null\n");		return -ENODEV;	}	//debug_param("%s\n", __FUNCTION__);	udev = cam->usbdev;	altsetting = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 7);	psz = le16_to_cpu(altsetting->endpoint[0].desc.wMaxPacketSize);	do {		for (i = 0; i < ZC0301_URBS; i++)		{			cam->transfer_buffer[i] = kzalloc(ZC0301_PACKETS * psz, GFP_KERNEL);			if (cam->transfer_buffer[i] == NULL)			{				debug_error("zc0301_urb_start:alloc transfer buffer failed\n");				err = -ENOMEM;				flag = 1;				break;			}		}		for (i = 0; i < ZC0301_URBS; i++)		{			cam->urb[i] = usb_alloc_urb(ZC0301_PACKETS, GFP_KERNEL);			if (cam->urb[i] == NULL)			{				debug_error("zc0301_urb_start:usb_alloc_urb failed\n");				err = -ENOMEM;				flag = 1;				break;			}			cam->urb[i]->dev = udev;			cam->urb[i]->context = cam;			cam->urb[i]->pipe = usb_rcvisocpipe(udev, 1);			cam->urb[i]->interval = 1;			cam->urb[i]->transfer_flags = URB_ISO_ASAP;			cam->urb[i]->transfer_buffer = cam->transfer_buffer[i];			cam->urb[i]->complete = zc0301_urb_complete;			cam->urb[i]->number_of_packets = ZC0301_PACKETS;			cam->urb[i]->transfer_buffer_length = ZC0301_PACKETS * psz;			for (j = 0; j < ZC0301_PACKETS; j++)			{				cam->urb[i]->iso_frame_desc[j].offset = j * psz;				cam->urb[i]->iso_frame_desc[j].length = psz;			}			//debug_info("zc0301_urb_start:urb[] alloc successed\n");		}		err = usb_set_interface(udev, 0, 7);		if (err)		{			debug_error("zc0301_urb_start:open usb interface failed\n");			flag = 1;			break;		}		for (i = 0; i < ZC0301_URBS; i++)		{			err = usb_submit_urb(cam->urb[i], GFP_KERNEL);			if (err)			{				debug_error("zc0301_urb_start:usb_submit_urb failed\n");				flag = 1;				break;			}		}	}while(0);	if (flag)	{		debug_error("zc0301_urb_start:There is some wrong with urb start!\n");		for (i = 0; i < ZC0301_URBS && cam->transfer_buffer[i]; i++)			kfree(cam->transfer_buffer[i]);		for (i = 0; i < ZC0301_URBS && cam->urb[i]; i++)			usb_free_urb(cam->urb[i]);		return err;	}	return 0;}int zc0301_urb_stop(struct zc0301_device *cam){	struct usb_device *udev = NULL;	s8 i = 0;	int err = 0;		if (cam == NULL)	{		debug_error("zc0301_urb_stop:cam is null\n");		return -ENODEV;	}	//debug_param("%s\n", __FUNCTION__);	udev = cam->usbdev;	if (cam->d_state & DISCONNECTED)	{		debug_info("zc0301_urb_stop:device has been disconnected\n");		return 0;	}	for (i = ZC0301_URBS-1; i >= 0; i--)	{		usb_kill_urb(cam->urb[i]); /*kill and unlink are so different...*/		//usb_unlink_urb(cam->urb[i]);		usb_free_urb(cam->urb[i]);		kfree(cam->transfer_buffer[i]);	}	err = usb_set_interface(udev, 0, 0);	if (err)	{		debug_error("zc0301_urb_stop:close usb interface failed\n");		return err;	}	return 0;}EXPORT_SYMBOL(zc0301_urb_complete);EXPORT_SYMBOL(zc0301_urb_start);EXPORT_SYMBOL(zc0301_urb_stop);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -