usbvideo.c
来自「trident tm5600的linux驱动」· C语言 代码 · 共 2,244 行 · 第 1/4 页
C
2,244 行
if (pmode == 1) { if (frame->curline % 32 == 0) cb = 0, cg = cr = 0xFF; else if (i % 32 == 0) { if (frame->curline % 32 == 1) num_cell++; cb = 0, cg = cr = 0xFF; } else { cb = ((num_cell*7) + num_pass) & 0xFF; cg = ((num_cell*5) + num_pass*2) & 0xFF; cr = ((num_cell*3) + num_pass*3) & 0xFF; } } else { /* Just the blue screen */ } *f++ = cb; *f++ = cg; *f++ = cr; scan_length += 3; } } frame->frameState = FrameState_Done; frame->seqRead_Length += scan_length; ++num_pass; /* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */ usbvideo_OverlayStats(uvd, frame);}EXPORT_SYMBOL(usbvideo_TestPattern);#ifdef DEBUG/* * usbvideo_HexDump() * * A debugging tool. Prints hex dumps. * * History: * 29-Jul-2000 Added printing of offsets. */void usbvideo_HexDump(const unsigned char *data, int len){ const int bytes_per_line = 32; char tmp[128]; /* 32*3 + 5 */ int i, k; for (i=k=0; len > 0; i++, len--) { if (i > 0 && ((i % bytes_per_line) == 0)) { printk("%s\n", tmp); k=0; } if ((i % bytes_per_line) == 0) k += sprintf(&tmp[k], "%04x: ", i); k += sprintf(&tmp[k], "%02x ", data[i]); } if (k > 0) printk("%s\n", tmp);}EXPORT_SYMBOL(usbvideo_HexDump);#endif/* ******************************************************************** *//* XXX: this piece of crap really wants some error handling.. */static int usbvideo_ClientIncModCount(struct uvd *uvd){ if (uvd == NULL) { err("%s: uvd == NULL", __func__); return -EINVAL; } if (uvd->handle == NULL) { err("%s: uvd->handle == NULL", __func__); return -EINVAL; } if (!try_module_get(uvd->handle->md_module)) { err("%s: try_module_get() == 0", __func__); return -ENODEV; } return 0;}static void usbvideo_ClientDecModCount(struct uvd *uvd){ if (uvd == NULL) { err("%s: uvd == NULL", __func__); return; } if (uvd->handle == NULL) { err("%s: uvd->handle == NULL", __func__); return; } if (uvd->handle->md_module == NULL) { err("%s: uvd->handle->md_module == NULL", __func__); return; } module_put(uvd->handle->md_module);}int usbvideo_register( struct usbvideo **pCams, const int num_cams, const int num_extra, const char *driverName, const struct usbvideo_cb *cbTbl, struct module *md, const struct usb_device_id *id_table){ struct usbvideo *cams; int i, base_size, result; /* Check parameters for sanity */ if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) { err("%s: Illegal call", __func__); return -EINVAL; } /* Check registration callback - must be set! */ if (cbTbl->probe == NULL) { err("%s: probe() is required!", __func__); return -EINVAL; } base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo); cams = kzalloc(base_size, GFP_KERNEL); if (cams == NULL) { err("Failed to allocate %d. bytes for usbvideo struct", base_size); return -ENOMEM; } dbg("%s: Allocated $%p (%d. bytes) for %d. cameras", __func__, cams, base_size, num_cams); /* Copy callbacks, apply defaults for those that are not set */ memmove(&cams->cb, cbTbl, sizeof(cams->cb)); if (cams->cb.getFrame == NULL) cams->cb.getFrame = usbvideo_GetFrame; if (cams->cb.disconnect == NULL) cams->cb.disconnect = usbvideo_Disconnect; if (cams->cb.startDataPump == NULL) cams->cb.startDataPump = usbvideo_StartDataPump; if (cams->cb.stopDataPump == NULL) cams->cb.stopDataPump = usbvideo_StopDataPump; cams->num_cameras = num_cams; cams->cam = (struct uvd *) &cams[1]; cams->md_module = md; mutex_init(&cams->lock); /* to 1 == available */ for (i = 0; i < num_cams; i++) { struct uvd *up = &cams->cam[i]; up->handle = cams; /* Allocate user_data separately because of kmalloc's limits */ if (num_extra > 0) { up->user_size = num_cams * num_extra; up->user_data = kmalloc(up->user_size, GFP_KERNEL); if (up->user_data == NULL) { err("%s: Failed to allocate user_data (%d. bytes)", __func__, up->user_size); while (i) { up = &cams->cam[--i]; kfree(up->user_data); } kfree(cams); return -ENOMEM; } dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)", __func__, i, up->user_data, up->user_size); } } /* * Register ourselves with USB stack. */ strcpy(cams->drvName, (driverName != NULL) ? driverName : "Unknown"); cams->usbdrv.name = cams->drvName; cams->usbdrv.probe = cams->cb.probe; cams->usbdrv.disconnect = cams->cb.disconnect; cams->usbdrv.id_table = id_table; /* * Update global handle to usbvideo. This is very important * because probe() can be called before usb_register() returns. * If the handle is not yet updated then the probe() will fail. */ *pCams = cams; result = usb_register(&cams->usbdrv); if (result) { for (i = 0; i < num_cams; i++) { struct uvd *up = &cams->cam[i]; kfree(up->user_data); } kfree(cams); } return result;}EXPORT_SYMBOL(usbvideo_register);/* * usbvideo_Deregister() * * Procedure frees all usbvideo and user data structures. Be warned that * if you had some dynamically allocated components in ->user field then * you should free them before calling here. */void usbvideo_Deregister(struct usbvideo **pCams){ struct usbvideo *cams; int i; if (pCams == NULL) { err("%s: pCams == NULL", __func__); return; } cams = *pCams; if (cams == NULL) { err("%s: cams == NULL", __func__); return; } dbg("%s: Deregistering %s driver.", __func__, cams->drvName); usb_deregister(&cams->usbdrv); dbg("%s: Deallocating cams=$%p (%d. cameras)", __func__, cams, cams->num_cameras); for (i=0; i < cams->num_cameras; i++) { struct uvd *up = &cams->cam[i]; int warning = 0; if (up->user_data != NULL) { if (up->user_size <= 0) ++warning; } else { if (up->user_size > 0) ++warning; } if (warning) { err("%s: Warning: user_data=$%p user_size=%d.", __func__, up->user_data, up->user_size); } else { dbg("%s: Freeing %d. $%p->user_data=$%p", __func__, i, up, up->user_data); kfree(up->user_data); } } /* Whole array was allocated in one chunk */ dbg("%s: Freed %d uvd structures", __func__, cams->num_cameras); kfree(cams); *pCams = NULL;}EXPORT_SYMBOL(usbvideo_Deregister);/* * usbvideo_Disconnect() * * This procedure stops all driver activity. Deallocation of * the interface-private structure (pointed by 'ptr') is done now * (if we don't have any open files) or later, when those files * are closed. After that driver should be removable. * * This code handles surprise removal. The uvd->user is a counter which * increments on open() and decrements on close(). If we see here that * this counter is not 0 then we have a client who still has us opened. * We set uvd->remove_pending flag as early as possible, and after that * all access to the camera will gracefully fail. These failures should * prompt client to (eventually) close the video device, and then - in * usbvideo_v4l_close() - we decrement uvd->uvd_used and usage counter. * * History: * 22-Jan-2000 Added polling of MOD_IN_USE to delay removal until all users gone. * 27-Jan-2000 Reworked to allow pending disconnects; see xxx_close() * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). * 19-Oct-2000 Moved to usbvideo module. */static void usbvideo_Disconnect(struct usb_interface *intf){ struct uvd *uvd = usb_get_intfdata (intf); int i; if (uvd == NULL) { err("%s($%p): Illegal call.", __func__, intf); return; } usb_set_intfdata (intf, NULL); usbvideo_ClientIncModCount(uvd); if (uvd->debug > 0) dev_info(&intf->dev, "%s(%p.)\n", __func__, intf); mutex_lock(&uvd->lock); uvd->remove_pending = 1; /* Now all ISO data will be ignored */ /* At this time we ask to cancel outstanding URBs */ GET_CALLBACK(uvd, stopDataPump)(uvd); for (i=0; i < USBVIDEO_NUMSBUF; i++) usb_free_urb(uvd->sbuf[i].urb); usb_put_dev(uvd->dev); uvd->dev = NULL; /* USB device is no more */ video_unregister_device(&uvd->vdev); if (uvd->debug > 0) dev_info(&intf->dev, "%s: Video unregistered.\n", __func__); if (uvd->user) dev_info(&intf->dev, "%s: In use, disconnect pending.\n", __func__); else usbvideo_CameraRelease(uvd); mutex_unlock(&uvd->lock); dev_info(&intf->dev, "USB camera disconnected.\n"); usbvideo_ClientDecModCount(uvd);}/* * usbvideo_CameraRelease() * * This code does final release of uvd. This happens * after the device is disconnected -and- all clients * closed their files. * * History: * 27-Jan-2000 Created. */static void usbvideo_CameraRelease(struct uvd *uvd){ if (uvd == NULL) { err("%s: Illegal call", __func__); return; } RingQueue_Free(&uvd->dp); if (VALID_CALLBACK(uvd, userFree)) GET_CALLBACK(uvd, userFree)(uvd); uvd->uvd_used = 0; /* This is atomic, no need to take mutex */}/* * usbvideo_find_struct() * * This code searches the array of preallocated (static) structures * and returns index of the first one that isn't in use. Returns -1 * if there are no free structures. * * History: * 27-Jan-2000 Created. */static int usbvideo_find_struct(struct usbvideo *cams){ int u, rv = -1; if (cams == NULL) { err("No usbvideo handle?"); return -1; } mutex_lock(&cams->lock); for (u = 0; u < cams->num_cameras; u++) { struct uvd *uvd = &cams->cam[u]; if (!uvd->uvd_used) /* This one is free */ { uvd->uvd_used = 1; /* In use now */ mutex_init(&uvd->lock); /* to 1 == available */ uvd->dev = NULL; rv = u; break; } } mutex_unlock(&cams->lock); return rv;}static const struct file_operations usbvideo_fops = { .owner = THIS_MODULE, .open = usbvideo_v4l_open, .release =usbvideo_v4l_close, .read = usbvideo_v4l_read, .mmap = usbvideo_v4l_mmap, .ioctl = usbvideo_v4l_ioctl,#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32,#endif .llseek = no_llseek,};static const struct video_device usbvideo_template = { .fops = &usbvideo_fops,};struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams){ int i, devnum; struct uvd *uvd = NULL; if (cams == NULL) { err("No usbvideo handle?"); return NULL; } devnum = usbvideo_find_struct(cams); if (devnum == -1) { err("IBM USB camera driver: Too many devices!"); return NULL; } uvd = &cams->cam[devnum]; dbg("Device entry #%d. at $%p", devnum, uvd); /* Not relying upon caller we increase module counter ourselves */ usbvideo_ClientIncModCount(uvd); mutex_lock(&uvd->lock); for (i=0; i < USBVIDEO_NUMSBUF; i++) { uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); if (uvd->sbuf[i].urb == NULL) { err("usb_alloc_urb(%d.) failed.", FRAMES_PER_DESC); uvd->uvd_used = 0; uvd = NULL; goto allocate_done; } } uvd->user=0; uvd->remove_pending = 0; uvd->last_error = 0; RingQueue_Initialize(&uvd->dp); /* Initialize video device structure */ uvd->vdev = usbvideo_template; sprintf(uvd->vdev.name, "%.20s USB Camera", cams->drvName); /* * The client is free to overwrite those because we * return control to the client's probe function right now. */allocate_done: mutex_unlock(&uvd->lock); usbvideo_ClientDecModCount(uvd); return uvd;}EXPORT_SYMBOL(usbvideo_AllocateDevice);int usbvideo_RegisterVideoDevice(struct uvd *uvd){ char tmp1[20], tmp2[20]; /* Buffers for printing */ if (uvd == NULL) { err("%s: Illegal call.", __func__); return -EINVAL; } if (uvd->video_endp == 0) { dev_info(&uvd->dev->dev, "%s: No video endpoint specified; data pump disabled.\n", __func__); } if (uvd->paletteBits == 0) { err("%s: No palettes specified!", __func__); return -EINVAL; } if (uvd->defaultPalette == 0) { dev_info(&uvd->dev->dev, "%s: No default palette!\n", __func__); } uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) * VIDEOSIZE_Y(uvd->canvas) * V4L_BYTES_PER_PIXEL; usbvideo_VideosizeToString(tmp1, sizeof(tmp1), uvd->videosize); usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas); if (uvd->debug > 0) { dev_info(&uvd->dev->dev, "%s: iface=%d. endpoint=$%02x paletteBits=$%08lx\n", __func__, uvd->iface, uvd->video_endp, uvd->paletteBits); } if (uvd->dev == NULL) { err("%s: uvd->dev == NULL", __func__); return -EINVAL; } uvd->vdev.parent = &uvd->dev->dev; uvd->vdev.release = video_device_release_empty; if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { err("%s: video_register_device failed", __func__); return -EPIPE; } if (uvd->debug > 1) { dev_info(&uvd->dev->dev, "%s: video_register_device() successful\n", __func__); } dev_info(&uvd->dev->dev, "%s on /dev/video%d: canvas=%s videosize=%s\n", (uvd->handle != NULL) ? uvd->handle->drvName : "???", uvd->vdev.num, tmp2, tmp1); usb_get_dev(uvd->dev); return 0;}EXPORT_SYMBOL(usbvideo_RegisterVideoDevice);/* ******************************************************************** */static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma){ struct uvd *uvd = file->private_data; unsigned long start = vma->vm_start; unsigned long size = vma->vm_end-vma->vm_start; unsigned long page, pos; if (!CAMERA_IS_OPERATIONAL(uvd)) return -EFAULT; if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) return -EINVAL; pos = (unsigned long) uvd->fbuf; while (size > 0) { page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) return -EAGAIN; start += PAGE_SIZE; pos += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; else size = 0; } return 0;}/* * usbvideo_v4l_open() * * This is part of Video 4 Linux API. The driver can be opened by one * client only (checks internal counter 'uvdser'). The procedure * then allocates buffers needed for video processing. * * History: * 22-Jan-2000 Rewrote, moved scratch buffer allocation here. Now the * camera is also initialized here (once per connect), at * expense of V4L client (it waits on open() call). * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). */static int usbvideo_v4l_open(struct inode *inode, struct file *file){ struct video_device *dev = video_devdata(file); struct uvd *uvd = (struct uvd *) dev; const int sb_size = FRAMES_PER_DESC * uvd->iso_packet_len; int i, errCode = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?