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

📄 qcamvc.c

📁 VC编写的USB QuickCam驱动程序,实现四种视频格式在linux下的编码,信号来自摄像源
💻 C
📖 第 1 页 / 共 3 页
字号:
  printk("QuickCam VC:8bpc bigbuffer read, len=%d, ",sizeof(buffer));   for (i=1 ; i < BIGBUFFER_SIZE ;  i+=2)     {      if (a != *(bigbuffer + i)) 	{ printk (" 0x%02x ", *(bigbuffer + i)); a=*(bigbuffer + i);}    }  printk("\n");  //buffer[0]=0x00; qcamvc->ops->qcamvc_set_reg(qcamvc->lowlevel_data, 0x0e, buffer, 1);  //buffer[0]=0x00; qcamvc->ops->qcamvc_set_reg(qcamvc->lowlevel_data, QCAM_VC_SET_MISC, buffer, 1);  //buffer[0]=0x78; qcamvc->ops->qcamvc_set_reg(qcamvc->lowlevel_data, 0x0f, buffer, 1);  //buffer[0]=0x00; qcamvc->ops->qcamvc_set_reg(qcamvc->lowlevel_data, QCAM_VC_SET_MISC, buffer, 1);  //buffer[0]=0x58; qcamvc->ops->qcamvc_set_reg(qcamvc->lowlevel_data, 0x0f, buffer, 1);  //qcamvc_set_brightness(qcamvc, qcamvc->brightness);  //qcamvc_set_exposure(qcamvc, qcamvc->exposure);  //buffer[0]=0x11; qcamvc->ops->qcamvc_set_reg(qcamvc->lowlevel_data, 0x0a, buffer, 1);  //buffer[0]=0x11; qcamvc->ops->qcamvc_set_reg(qcamvc->lowlevel_data, 0x0a, buffer, 1);  qcamvc_set_topmost_row     (qcamvc, firstrow[qcamvc->res]);  qcamvc_set_leftmost_column (qcamvc, firstcolumn[qcamvc->res]);  qcamvc_set_bottommost_row  (qcamvc, lastrow[qcamvc->res]);  qcamvc_set_rightmost_column(qcamvc, lastcolumn[qcamvc->res]);  buffer[0] = mulfactor[qcamvc->res];   qcamvc->ops->qcamvc_set_reg(qcamvc->lowlevel_data, 0x0a, buffer, 1);  printk("h\n");  kfree(bigbuffer);  return 0;}static int qcamvc_camera_init(struct qcamvc *qcamvc){  FIRST_ROW; LAST_ROW;  FIRST_COL; LAST_COL;  MUL_FACTOR; ISO_LEN;  int ret=-1;  switch(qcamvc->bpc)    {    case bpc6:      {        ret = bpc6_init(qcamvc);	break;      }        case bpc8:      {	ret = bpc8_init(qcamvc);	break;      }          }  qcamvc->packet_len = iso_len[qcamvc->bpc][qcamvc->res];  qcamvc->height =   lastrow[qcamvc->res] -    firstrow[qcamvc->res];  qcamvc->width = lastcolumn[qcamvc->res] - firstcolumn[qcamvc->res];   if (!(mulfactor[qcamvc->res] & 0x02))     {      qcamvc->height*=2;      qcamvc->width*=2;    }  qcamvc->ops->qcamvc_set_reg(qcamvc->lowlevel_data, QCAM_VC_GET_FRAME, NULL, 0);  qcamvc->streaming=1;  qcamvc->hue_calc=0;#ifdef DBG_CAM  printk("QuickCam VC:Init at %dx%d\n", qcamvc->width, qcamvc->height);#endif  return ret;}static void bpc6_parse(struct qcamvc *qcamvc, unsigned char *inbuf, unsigned char *outbuf, size_t count){  size_t i,q;  unsigned char *temp=kmalloc(qcamvc->width*qcamvc->height, GFP_KERNEL);  for( i = q = 0 ; i < qcamvc->width * qcamvc->height; i+=4,q+=3 )    {      if ((q + 2) < qcamvc->packet_len) *(temp+i+3) = *((inbuf+2) + q + 2) & 0xfc;      if ((q + 2) < qcamvc->packet_len) *(temp+i+2) = (((*((inbuf+2) + q + 1) >> 4) & 0x0f)|((*((inbuf+2)+ q + 2) <<4) & 0x30))<<2;      if ((q + 1) < qcamvc->packet_len) *(temp+i+1) = (((*((inbuf+2) + q)>>6)&0x03)|((*((inbuf+2)+ q + 1)&0x0f)<<2))<<2;      if (q < qcamvc->packet_len)       *(temp+i+0) = (*((inbuf+2) + q)&0x3f)<<2;     }  codec(qcamvc, temp, outbuf);  kfree(temp);}static void bpc8_parse(struct qcamvc *qcamvc, unsigned char *inbuf, unsigned char *outbuf, size_t count){  unsigned char *temp=kmalloc(qcamvc->width*qcamvc->height, GFP_KERNEL);  memcpy(outbuf, inbuf, qcamvc->packet_len);  kfree(temp);}static void qcamvc_parse(struct qcamvc *qcamvc, unsigned char *inbuf, unsigned char *outbuf, size_t count){  switch(qcamvc->bpc)    {    case bpc6:      {	bpc6_parse(qcamvc, inbuf, outbuf, count);	break;      }        case bpc8:      {	bpc8_parse(qcamvc, inbuf, outbuf, count);	break;      }          }}static int qcamvc_set_res(struct qcamvc *qcamvc, int res){  if (res == qcamvc->res)    return -1;  qcamvc->res = res;  qcamvc_camera_init(qcamvc);  return qcamvc->res;}/**************************************************************************** * * /proc interface * ***************************************************************************/#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)static struct proc_dir_entry *qcamvc_proc_entry = NULL;extern struct proc_dir_entry *video_proc_entry;#define YES_NO(x) ((x) ? "yes" : "no")/****************************************************************************/static int qcamvc_read_proc(char *page, char **start, off_t off, int count,			   int *eof, void *data){	char *out = page;	int len;	struct qcamvc *qcamvc = data;		// Stay under PAGE_SIZE or bad things will happen :(	out+=sprintf(out, "driver_version   : %s\n", QCAMVCVERSION);	out+=sprintf(out, "model            : %s\n", qcamvc->vcap.name);        out+=sprintf(out, "max resolution   : %dx%d\n", qcamvc->vcap.maxwidth, qcamvc->vcap.maxheight);        out+=sprintf(out, "min resolution   : %dx%d\n\n", qcamvc->vcap.minwidth, qcamvc->vcap.minheight);        out+=sprintf(out, "Settings\n");        out+=sprintf(out, "resolution       : %dx%d\n", qcamvc->width, qcamvc->height);	out+=sprintf(out, "bit per component: %d\n", (qcamvc->bpc==bpc6)? 6 : 8);        out+=sprintf(out, "brightness       : %d\n", qcamvc->brightness);        out+=sprintf(out, "exposure         : %d\n", (int)qcamvc->exposure);        out+=sprintf(out, "red hue          : %d\n", (int)qcamvc->red_hue);        out+=sprintf(out, "blue hue         : %d\n", (int)qcamvc->blue_hue);        out+=sprintf(out, "santrast         : %d\n", (int)qcamvc->santrast);	out+=sprintf(out, "\n");		len = out - page;	len -= off;	if (len < count) {		*eof = 1;		if (len <= 0) return 0;	} else		len = count;	*start = page + off;		return len;	}/****************************************************************************/static int qcamvc_write_proc(struct file *file, const char *buffer, 			    unsigned long count, void *data){	return -EINVAL;}/*************************************************************************** This routine is called when a quickcam is registered*/static void create_proc_qcamvc (struct qcamvc *qcamvc){	char name[7];	struct proc_dir_entry *ent;	    printk("Quickcam VC: Creating a camera entry in proc quickcam.\n");     printk("Quickcam dev struct in create_proc_qcamvc %p\n",qcamvc);	if (!qcamvc_proc_entry || !qcamvc)		return;	sprintf (name, "video%d", qcamvc->vdev.minor);	ent = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR,				qcamvc_proc_entry);	if (!ent)		return;	ent->data = qcamvc;	ent->read_proc = qcamvc_read_proc;	ent->write_proc = qcamvc_write_proc;	qcamvc->proc_entry = ent;}/*************************************************************************** This routine is called when a quickcam is unregistered */static void destroy_proc_qcamvc (struct qcamvc *qcamvc){	/* One to much, just to be sure :) */	char name[9];    printk("Quickcam VC: Destroying a camera entry in proc quickcam.\n"); 	if (!qcamvc || !qcamvc->proc_entry)		return;		sprintf(name, "video%d", qcamvc->vdev.minor);	remove_proc_entry(name, qcamvc_proc_entry);	qcamvc->proc_entry = NULL;}/*************************************************************************** This routine is called when the driver is placed in memory* by an insmod.*/static void proc_qcamvc_create(void){    printk("QuickCam VC: Making a quickcam directory in /proc.\n"); 	if (video_proc_entry == NULL) {		printk("/proc/video/ doesn't exist");		return;	}	qcamvc_proc_entry=create_proc_entry("qcamvc", S_IFDIR, video_proc_entry);	if (qcamvc_proc_entry)		qcamvc_proc_entry->owner = THIS_MODULE;	else		printk("Unable to initialize /proc/video/qcamvc");}/*************************************************************************** This routine is called when the driver is removed from memory* by an rmmod command.*/static void proc_quickcam_destroy(void){    printk("Quickcam VC: Destroying a quickcam directory in /proc.\n"); 	if (qcamvc_proc_entry == NULL)		return;	remove_proc_entry("qcamvc", video_proc_entry);}#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS *//****************************************************************************/static int qcamvc_init_done(struct video_device *dev){    #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)        create_proc_qcamvc(dev->priv);        printk("qcamvc dev struct in qcamvc_init_done %p\n",dev);    #endif    return 0;}/*****************************************************************************//*                                                                           *//* Video 4 Linux                                                             *//*                                                                           *//*                                                                           *//*****************************************************************************/static long qcamvc_vread(struct video_device *dev, char *buf, unsigned long count, int noblock){   struct qcamvc *qcamvc = dev->priv;   unsigned char *tempbuf = kmalloc(qcamvc->packet_len, GFP_KERNEL);  if (down_interruptible(&qcamvc->busy))    return -EINTR;    if (!buf) {    up(&qcamvc->busy);    return -EINVAL;  }    if (!count) {    up(&qcamvc->busy);    return 0;  }    if (!qcamvc->ops) {    up(&qcamvc->busy);    return -ENODEV;  }#ifdef DBG_CAM  printk("USB QuickCam quickcam_read count=%ld\n",count);#endif  qcamvc->ops->qcamvc_stream_read(qcamvc->lowlevel_data, tempbuf, qcamvc->packet_len);  qcamvc_parse(qcamvc, tempbuf, buf, count);  kfree(tempbuf);  up(&qcamvc->busy);  return count;}static long qcamvc_vwrite(struct video_device *dev, const char *buf, unsigned long count, int noblock){  struct qcamvc *qcamvc = dev->priv;  if (down_interruptible(&qcamvc->busy))    return -EINTR;  up(&qcamvc->busy);  return -EINVAL;}#ifdef USE_MMAPstatic int qcamvc_vmmap(struct video_device *dev, const char *adr,                     unsigned long size){  unsigned long start = (unsigned long) adr;  unsigned long page, pos;  int retval;  struct qcamvc *qcamvc = dev->priv;   if (down_interruptible(&qcamvc->busy))    return -EINTR;  if (!qcamvc->frame_buf) {    if ((retval = allocate_frame_buf(qcamvc))) {      return 0;    }  }    pos = (unsigned long)(qcamvc->frame_buf);  while (size > 0) {    page = kvirt_to_pa(pos);    if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {      up(&qcamvc->busy);      return -EAGAIN;    }    start += PAGE_SIZE;    pos += PAGE_SIZE;    if (size > PAGE_SIZE)      size -= PAGE_SIZE;    else      size = 0;  }  up(&qcamvc->busy);  return 0;  }/********************************************************************** * * Memory management * * This is a shameless copy from the USB-cpia driver (linux kernel * version 2.3.29 or so, I have no idea what this code actually does ;). * Actually it seems to be a copy of a shameless copy of the bttv-driver. * Or that is a copy of a shameless copy of ... (To the powers: is there * no generic kernel-function to do this sort of stuff?) * * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says * there will be one, but apparentely not yet - jerdfelt * **********************************************************************//* Given PGD from the address space's page table, return the kernel * virtual mapping of the physical memory mapped at ADR. */static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr){  unsigned long ret = 0UL;  pmd_t *pmd;  pte_t *ptep, pte;    if (!pgd_none(*pgd)) {    pmd = pmd_offset(pgd, adr);    if (!pmd_none(*pmd)) {			ptep = pte_offset(pmd, adr);			pte = *ptep;			if (pte_present(pte)) {			  ret = (unsigned long) page_address(pte_page(pte));			  ret |= (adr & (PAGE_SIZE-1));			}    }  }  return ret;}#if LINUX_VERSION_CODE < 0x020400#define virt_to_page(kaddr) (MAP_NR(kaddr))#endifstatic void *rvmalloc(unsigned long size){	void *mem;	unsigned long adr, page;	size += (PAGE_SIZE - 1);	size &= ~(PAGE_SIZE - 1);	mem = vmalloc_32(size);	if (!mem)		return NULL;	memset(mem, 0, size);	adr = (unsigned long) mem;	while (size > 0) {		page = kvirt_to_pa(adr);		mem_map_reserve(virt_to_page(__va(page)));		adr += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	return mem;}static void rvfree(void *mem, unsigned long size){  unsigned long adr, page;  if (!mem)    return;    size += (PAGE_SIZE - 1);  size &= ~(PAGE_SIZE - 1);    adr = (unsigned long) mem;  while (size > 0) {    page = kvirt_to_pa(adr);    mem_map_unreserve(virt_to_page(__va(page)));    adr += PAGE_SIZE;    if (size > PAGE_SIZE)      size -= PAGE_SIZE;    else      size = 0;  }	vfree(mem);}static int allocate_frame_buf(struct qcamvc *qcamvc){  int i;  qcamvc->frame_buf = rvmalloc(QUICKCAM_NUMFRAMES * QUICKCAM_MAX_SIZE);  if (!qcamvc->frame_buf)    return -ENOBUFS;    for (i = 0; i < QUICKCAM_NUMFRAMES; i++)    qcamvc->frame[i].data = qcamvc->frame_buf + i * QUICKCAM_MAX_SIZE;    return 0;}static int free_frame_buf(struct  qcamvc *qcamvc){  int i;	  rvfree(qcamvc->frame_buf, QUICKCAM_NUMFRAMES * QUICKCAM_MAX_SIZE);  qcamvc->frame_buf = 0;  for (i=0; i < QUICKCAM_NUMFRAMES; i++)    qcamvc->frame[i].data = NULL;  return 0;}static void inline free_frames(struct qcamvc_frame frame[QUICKCAM_NUMFRAMES]){	int i;	for (i=0; i < QUICKCAM_NUMFRAMES; i++)		frame[i].state = FRAME_UNUSED;	return;}/* Here we want the physical address of the memory. * This is used when initializing the contents of the * area and marking the pages as reserved. */static inline unsigned long kvirt_to_pa(unsigned long adr){  unsigned long va, kva, ret;    va = VMALLOC_VMADDR(adr);  kva = uvirt_to_kva(pgd_offset_k(va), va);  ret = __pa(kva);  return ret;}#endif /* USE_MMAP */static int qcamvc_vioctl(struct video_device *dev, unsigned int cmd, void *arg){  struct qcamvc *qcamvc = dev->priv;  if (down_interruptible(&qcamvc->busy))    return -EINTR;  switch(cmd)    {            /* Return capability */    case VIDIOCGCAP:      {	if (copy_to_user(arg, &qcamvc->vcap, sizeof(struct video_capability)))	  {	    up(&qcamvc->busy);	    return -EFAULT;	  }	up(&qcamvc->busy);	return 0;      }      

⌨️ 快捷键说明

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