usbvideo.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,283 行 · 第 1/5 页
C
2,283 行
usbvideo_OverlayString(uvd, frame, x, y, tmp); y += y_diff; sprintf(tmp, "%8d", uvd->vpic.whiteness >> 8); usbvideo_OverlayString(uvd, frame, x, y, tmp); y += y_diff;}/* * usbvideo_ReportStatistics() * * This procedure prints packet and transfer statistics. * * History: * 14-Jan-2000 Corrected default multiplier. */static void usbvideo_ReportStatistics(const struct uvd *uvd){ if ((uvd != NULL) && (uvd->stats.urb_count > 0)) { unsigned long allPackets, badPackets, goodPackets, percent; allPackets = uvd->stats.urb_count * CAMERA_URB_FRAMES; badPackets = uvd->stats.iso_skip_count + uvd->stats.iso_err_count; goodPackets = allPackets - badPackets; /* Calculate percentage wisely, remember integer limits */ assert(allPackets != 0); if (goodPackets < (((unsigned long)-1)/100)) percent = (100 * goodPackets) / allPackets; else percent = goodPackets / (allPackets / 100); info("Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%", allPackets, badPackets, percent); if (uvd->iso_packet_len > 0) { unsigned long allBytes, xferBytes; char multiplier = ' '; allBytes = allPackets * uvd->iso_packet_len; xferBytes = uvd->stats.data_count; assert(allBytes != 0); if (xferBytes < (((unsigned long)-1)/100)) percent = (100 * xferBytes) / allBytes; else percent = xferBytes / (allBytes / 100); /* Scale xferBytes for easy reading */ if (xferBytes > 10*1024) { xferBytes /= 1024; multiplier = 'K'; if (xferBytes > 10*1024) { xferBytes /= 1024; multiplier = 'M'; if (xferBytes > 10*1024) { xferBytes /= 1024; multiplier = 'G'; if (xferBytes > 10*1024) { xferBytes /= 1024; multiplier = 'T'; } } } } info("Transfer Statistics: Transferred=%lu%cB Usage=%lu%%", xferBytes, multiplier, percent); } }}/* * usbvideo_DrawLine() * * A standard implementation of Bresenham's line drawing algorithm. * This procedure is provided primarily for debugging or demo * purposes. */void usbvideo_DrawLine( struct usbvideo_frame *frame, int x1, int y1, int x2, int y2, unsigned char cr, unsigned char cg, unsigned char cb){ int i, dx, dy, np, d; int dinc1, dinc2, x, xinc1, xinc2, y, yinc1, yinc2; if ((dx = x2 - x1) < 0) dx = -dx; if ((dy = y2 - y1) < 0) dy = -dy; if (dx >= dy) { np = dx + 1; d = (2 * dy) - dx; dinc1 = dy << 1; dinc2 = (dy - dx) << 1; xinc1 = 1; xinc2 = 1; yinc1 = 0; yinc2 = 1; } else { np = dy + 1; d = (2 * dx) - dy; dinc1 = dx << 1; dinc2 = (dx - dy) << 1; xinc1 = 0; xinc2 = 1; yinc1 = 1; yinc2 = 1; } /* Make sure x and y move in the right directions */ if (x1 > x2) { xinc1 = -xinc1; xinc2 = -xinc2; } if (y1 > y2) { yinc1 = -yinc1; yinc2 = -yinc2; } for (i=0, x=x1, y=y1; i < np; i++) { if (frame->palette == VIDEO_PALETTE_RGB24) {/* TODO */ RGB24_PUTPIXEL(frame, x, y, cr, cg, cb); } if (d < 0) { d += dinc1; x += xinc1; y += yinc1; } else { d += dinc2; x += xinc2; y += yinc2; } }}EXPORT_SYMBOL(usbvideo_DrawLine);/* * usbvideo_TestPattern() * * Procedure forms a test pattern (yellow grid on blue background). * * Parameters: * fullframe: if TRUE then entire frame is filled, otherwise the procedure * continues from the current scanline. * pmode 0: fill the frame with solid blue color (like on VCR or TV) * 1: Draw a colored grid * * History: * 01-Feb-2000 Created. */void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode){ struct usbvideo_frame *frame; int num_cell = 0; int scan_length = 0; static int num_pass = 0; if (uvd == NULL) { err("%s: uvd == NULL", __FUNCTION__); return; } if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { err("%s: uvd->curframe=%d.", __FUNCTION__, uvd->curframe); return; } /* Grab the current frame */ frame = &uvd->frame[uvd->curframe]; /* Optionally start at the beginning */ if (fullframe) { frame->curline = 0; frame->seqRead_Length = 0; }#if 0 { /* For debugging purposes only */ char tmp[20]; usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request); info("testpattern: frame=%s", tmp); }#endif /* Form every scan line */ for (; frame->curline < VIDEOSIZE_Y(frame->request); frame->curline++) { int i; unsigned char *f = frame->data + (VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL * frame->curline); for (i=0; i < VIDEOSIZE_X(frame->request); i++) { unsigned char cb=0x80; unsigned char cg = 0; unsigned char cr = 0; 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);/* * 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);/* Debugging aid */void usbvideo_SayAndWait(const char *what){ wait_queue_head_t wq; init_waitqueue_head(&wq); info("Say: %s", what); interruptible_sleep_on_timeout (&wq, HZ*3); /* Timeout */}EXPORT_SYMBOL(usbvideo_SayAndWait);/* ******************************************************************** *//* XXX: this piece of crap really wants some error handling.. */static void usbvideo_ClientIncModCount(struct uvd *uvd){ if (uvd == NULL) { err("%s: uvd == NULL", __FUNCTION__); return; } if (uvd->handle == NULL) { err("%s: uvd->handle == NULL", __FUNCTION__); return; } if (uvd->handle->md_module == NULL) { err("%s: uvd->handle->md_module == NULL", __FUNCTION__); return; } if (!try_module_get(uvd->handle->md_module)) { err("%s: try_module_get() == 0", __FUNCTION__); return; }}static void usbvideo_ClientDecModCount(struct uvd *uvd){ if (uvd == NULL) { err("%s: uvd == NULL", __FUNCTION__); return; } if (uvd->handle == NULL) { err("%s: uvd->handle == NULL", __FUNCTION__); return; } if (uvd->handle->md_module == NULL) { err("%s: uvd->handle->md_module == NULL", __FUNCTION__); 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", __FUNCTION__); return -EINVAL; } /* Check registration callback - must be set! */ if (cbTbl->probe == NULL) { err("%s: probe() is required!", __FUNCTION__); return -EINVAL; } base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo); cams = (struct usbvideo *) kmalloc(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", __FUNCTION__, cams, base_size, num_cams); memset(cams, 0, base_size); /* 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; if (cams->md_module == NULL) warn("%s: module == NULL!", __FUNCTION__); init_MUTEX(&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 = (char *) kmalloc(up->user_size, GFP_KERNEL); if (up->user_data == NULL) { err("%s: Failed to allocate user_data (%d. bytes)", __FUNCTION__, 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)", __FUNCTION__, 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", __FUNCTION__); return; } cams = *pCams; if (cams == NULL) { err("%s: cams == NULL", __FUNCTION__); return; } dbg("%s: Deregistering %s driver.", __FUNCTION__, cams->drvName); usb_deregister(&cams->usbdrv); dbg("%s: Deallocating cams=$%p (%d. cameras)", __FUNCTION__, 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.", __FUNCTION__, up->user_data, up->user_size); } else { dbg("%s: Freeing %d. $%p->user_data=$%p", __FUNCTION__, i, up, up->user_data); kfree(up->user_data); } } /* Whole array was allocated in one chunk */ dbg("%s: Freed %d uvd structures", __FUNCTION__, cams->num_cameras); kfree(cams); *pCams = NULL;}EXPORT_SYMBOL(usbvideo_Deregister);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?