📄 konicawc.c
字号:
/* Unschedule all of the iso td's */ for (i=0; i < USBVIDEO_NUMSBUF; i++) { usb_kill_urb(uvd->sbuf[i].urb); usb_kill_urb(cam->sts_urb[i]); } if (!uvd->remove_pending) { /* Set packet size to 0 */ j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); if (j < 0) { err("usb_set_interface() error %d.", j); uvd->last_error = j; } }}static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame){ struct konicawc *cam = (struct konicawc *)uvd->user_data; int maxline = cam->maxline; int yplanesz = cam->yplanesz; assert(frame != NULL); DEBUG(5, "maxline = %d yplanesz = %d", maxline, yplanesz); DEBUG(3, "Frame state = %d", frame->scanstate); if(frame->scanstate == ScanState_Scanning) { int drop = 0; int curframe; int fdrops = 0; DEBUG(3, "Searching for marker, queue len = %d", RingQueue_GetLength(&uvd->dp)); while(RingQueue_GetLength(&uvd->dp) >= 4) { if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) && (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) && (RING_QUEUE_PEEK(&uvd->dp, 3) < 0x80)) { curframe = RING_QUEUE_PEEK(&uvd->dp, 3); if(cam->lastframe >= 0) { fdrops = (0x80 + curframe - cam->lastframe) & 0x7F; fdrops--; if(fdrops) { info("Dropped %d frames (%d -> %d)", fdrops, cam->lastframe, curframe); } } cam->lastframe = curframe; frame->curline = 0; frame->scanstate = ScanState_Lines; RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4); break; } RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); drop++; } if(drop) DEBUG(2, "dropped %d bytes looking for new frame", drop); } if(frame->scanstate == ScanState_Scanning) return; /* Try to move data from queue into frame buffer * We get data in blocks of 384 bytes made up of: * 256 Y, 64 U, 64 V. * This needs to be written out as a Y plane, a U plane and a V plane. */ while ( frame->curline < maxline && (RingQueue_GetLength(&uvd->dp) >= 384)) { /* Y */ RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256); /* U */ RingQueue_Dequeue(&uvd->dp, frame->data + yplanesz + (frame->curline * 64), 64); /* V */ RingQueue_Dequeue(&uvd->dp, frame->data + (5 * yplanesz)/4 + (frame->curline * 64), 64); frame->seqRead_Length += 384; frame->curline++; } /* See if we filled the frame */ if (frame->curline == maxline) { DEBUG(5, "got whole frame"); frame->frameState = FrameState_Done_Hold; frame->curline = 0; uvd->curframe = -1; uvd->stats.frame_num++; }}static int konicawc_find_fps(int size, int fps){ int i; fps *= 3; DEBUG(1, "konica_find_fps: size = %d fps = %d", size, fps); if(fps <= spd_to_fps[size][0]) return 0; if(fps >= spd_to_fps[size][MAX_SPEED]) return MAX_SPEED; for(i = 0; i < MAX_SPEED; i++) { if((fps >= spd_to_fps[size][i]) && (fps <= spd_to_fps[size][i+1])) { DEBUG(2, "fps %d between %d and %d", fps, i, i+1); if( (fps - spd_to_fps[size][i]) < (spd_to_fps[size][i+1] - fps)) return i; else return i+1; } } return MAX_SPEED+1;}static int konicawc_set_video_mode(struct uvd *uvd, struct video_window *vw){ struct konicawc *cam = (struct konicawc *)uvd->user_data; int newspeed = cam->speed; int newsize; int x = vw->width; int y = vw->height; int fps = vw->flags; if(x > 0 && y > 0) { DEBUG(2, "trying to find size %d,%d", x, y); for(newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) { if((camera_sizes[newsize].width == x) && (camera_sizes[newsize].height == y)) break; } } else { newsize = cam->size; } if(newsize > MAX_FRAME_SIZE) { DEBUG(1, "couldn't find size %d,%d", x, y); return -EINVAL; } if(fps > 0) { DEBUG(1, "trying to set fps to %d", fps); newspeed = konicawc_find_fps(newsize, fps); DEBUG(1, "find_fps returned %d (%d)", newspeed, spd_to_fps[newsize][newspeed]); } if(newspeed > MAX_SPEED) return -EINVAL; DEBUG(1, "setting size to %d speed to %d", newsize, newspeed); if((newsize == cam->size) && (newspeed == cam->speed)) { DEBUG(1, "Nothing to do"); return 0; } DEBUG(0, "setting to %dx%d @ %d fps", camera_sizes[newsize].width, camera_sizes[newsize].height, spd_to_fps[newsize][newspeed]/3); konicawc_stop_data(uvd); uvd->ifaceAltActive = spd_to_iface[newspeed]; DEBUG(1, "new interface = %d", uvd->ifaceAltActive); cam->speed = newspeed; if(cam->size != newsize) { cam->size = newsize; konicawc_set_camera_size(uvd); } /* Flush the input queue and clear any current frame in progress */ RingQueue_Flush(&uvd->dp); cam->lastframe = -2; if(uvd->curframe != -1) { uvd->frame[uvd->curframe].curline = 0; uvd->frame[uvd->curframe].seqRead_Length = 0; uvd->frame[uvd->curframe].seqRead_Index = 0; } konicawc_start_data(uvd); return 0;}static int konicawc_calculate_fps(struct uvd *uvd){ struct konicawc *cam = uvd->user_data; return spd_to_fps[cam->size][cam->speed]/3;}static void konicawc_configure_video(struct uvd *uvd){ struct konicawc *cam = (struct konicawc *)uvd->user_data; u8 buf[2]; memset(&uvd->vpic, 0, sizeof(uvd->vpic)); memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); RESTRICT_TO_RANGE(brightness, 0, MAX_BRIGHTNESS); RESTRICT_TO_RANGE(contrast, 0, MAX_CONTRAST); RESTRICT_TO_RANGE(saturation, 0, MAX_SATURATION); RESTRICT_TO_RANGE(sharpness, 0, MAX_SHARPNESS); RESTRICT_TO_RANGE(whitebal, 0, MAX_WHITEBAL); cam->brightness = brightness / 11; cam->contrast = contrast / 11; cam->saturation = saturation / 11; cam->sharpness = sharpness / 11; cam->white_bal = whitebal / 11; uvd->vpic.colour = 108; uvd->vpic.hue = 108; uvd->vpic.brightness = brightness; uvd->vpic.contrast = contrast; uvd->vpic.whiteness = whitebal; uvd->vpic.depth = 6; uvd->vpic.palette = VIDEO_PALETTE_YUV420P; memset(&uvd->vcap, 0, sizeof(uvd->vcap)); strcpy(uvd->vcap.name, "Konica Webcam"); uvd->vcap.type = VID_TYPE_CAPTURE; uvd->vcap.channels = 1; uvd->vcap.audios = 0; uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width; uvd->vcap.minheight = camera_sizes[SIZE_160X120].height; uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width; uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height; memset(&uvd->vchan, 0, sizeof(uvd->vchan)); uvd->vchan.flags = 0 ; uvd->vchan.tuners = 0; uvd->vchan.channel = 0; uvd->vchan.type = VIDEO_TYPE_CAMERA; strcpy(uvd->vchan.name, "Camera"); /* Talk to device */ DEBUG(1, "device init"); if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2)) DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]); if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2)) DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]); if(konicawc_set_misc(uvd, 0x2, 0, 0xd)) DEBUG(2, "2,0,d failed"); DEBUG(1, "setting initial values");}static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id *devid){ struct usb_device *dev = interface_to_usbdev(intf); struct uvd *uvd = NULL; int ix, i, nas; int actInterface=-1, inactInterface=-1, maxPS=0; unsigned char video_ep = 0; DEBUG(1, "konicawc_probe(%p)", intf); /* We don't handle multi-config cameras */ if (dev->descriptor.bNumConfigurations != 1) return -ENODEV; info("Konica Webcam (rev. 0x%04x)", le16_to_cpu(dev->descriptor.bcdDevice)); RESTRICT_TO_RANGE(speed, 0, MAX_SPEED); /* Validate found interface: must have one ISO endpoint */ nas = intf->num_altsetting; if (nas != 8) { err("Incorrect number of alternate settings (%d) for this camera!", nas); return -ENODEV; } /* Validate all alternate settings */ for (ix=0; ix < nas; ix++) { const struct usb_host_interface *interface; const struct usb_endpoint_descriptor *endpoint; interface = &intf->altsetting[ix]; i = interface->desc.bAlternateSetting; if (interface->desc.bNumEndpoints != 2) { err("Interface %d. has %u. endpoints!", interface->desc.bInterfaceNumber, (unsigned)(interface->desc.bNumEndpoints)); return -ENODEV; } endpoint = &interface->endpoint[1].desc; DEBUG(1, "found endpoint: addr: 0x%2.2x maxps = 0x%4.4x", endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize)); if (video_ep == 0) video_ep = endpoint->bEndpointAddress; else if (video_ep != endpoint->bEndpointAddress) { err("Alternate settings have different endpoint addresses!"); return -ENODEV; } if ((endpoint->bmAttributes & 0x03) != 0x01) { err("Interface %d. has non-ISO endpoint!", interface->desc.bInterfaceNumber); return -ENODEV; } if ((endpoint->bEndpointAddress & 0x80) == 0) { err("Interface %d. has ISO OUT endpoint!", interface->desc.bInterfaceNumber); return -ENODEV; } if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { if (inactInterface < 0) inactInterface = i; else { err("More than one inactive alt. setting!"); return -ENODEV; } } else { if (i == spd_to_iface[speed]) { /* This one is the requested one */ actInterface = i; } } if (le16_to_cpu(endpoint->wMaxPacketSize) > maxPS) maxPS = le16_to_cpu(endpoint->wMaxPacketSize); } if(actInterface == -1) { err("Cant find required endpoint"); return -ENODEV; } DEBUG(1, "Selecting requested active setting=%d. maxPS=%d.", actInterface, maxPS); uvd = usbvideo_AllocateDevice(cams); if (uvd != NULL) { struct konicawc *cam = (struct konicawc *)(uvd->user_data); /* Here uvd is a fully allocated uvd object */ for(i = 0; i < USBVIDEO_NUMSBUF; i++) { cam->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); if(cam->sts_urb[i] == NULL) { while(i--) { usb_free_urb(cam->sts_urb[i]); } err("can't allocate urbs"); return -ENOMEM; } } cam->speed = speed; RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240); cam->width = camera_sizes[size].width; cam->height = camera_sizes[size].height; cam->size = size; uvd->flags = 0; uvd->debug = debug; uvd->dev = dev; uvd->iface = intf->altsetting->desc.bInterfaceNumber; uvd->ifaceAltInactive = inactInterface; uvd->ifaceAltActive = actInterface; uvd->video_endp = video_ep; uvd->iso_packet_len = maxPS; uvd->paletteBits = 1L << VIDEO_PALETTE_YUV420P; uvd->defaultPalette = VIDEO_PALETTE_YUV420P; uvd->canvas = VIDEOSIZE(320, 240); uvd->videosize = VIDEOSIZE(cam->width, cam->height); /* Initialize konicawc specific data */ konicawc_configure_video(uvd); i = usbvideo_RegisterVideoDevice(uvd); uvd->max_frame_size = (320 * 240 * 3)/2; if (i != 0) { err("usbvideo_RegisterVideoDevice() failed."); uvd = NULL; }#ifdef CONFIG_INPUT /* Register input device for button */ memset(&cam->input, 0, sizeof(struct input_dev)); cam->input.name = "Konicawc snapshot button"; cam->input.private = cam; cam->input.evbit[0] = BIT(EV_KEY); cam->input.keybit[LONG(BTN_0)] = BIT(BTN_0); cam->input.id.bustype = BUS_USB; cam->input.id.vendor = le16_to_cpu(dev->descriptor.idVendor); cam->input.id.product = le16_to_cpu(dev->descriptor.idProduct); cam->input.id.version = le16_to_cpu(dev->descriptor.bcdDevice); input_register_device(&cam->input); usb_make_path(dev, cam->input_physname, 56); strcat(cam->input_physname, "/input0"); cam->input.phys = cam->input_physname; info("konicawc: %s on %s\n", cam->input.name, cam->input.phys);#endif } if (uvd) { usb_set_intfdata (intf, uvd); return 0; } return -EIO;}static void konicawc_free_uvd(struct uvd *uvd){ int i; struct konicawc *cam = (struct konicawc *)uvd->user_data;#ifdef CONFIG_INPUT input_unregister_device(&cam->input);#endif for (i=0; i < USBVIDEO_NUMSBUF; i++) { usb_free_urb(cam->sts_urb[i]); cam->sts_urb[i] = NULL; }}static struct usb_device_id id_table[] = { { USB_DEVICE(0x04c8, 0x0720) }, /* Intel YC 76 */ { } /* Terminating entry */};static int __init konicawc_init(void){ struct usbvideo_cb cbTbl; info(DRIVER_DESC " " DRIVER_VERSION); memset(&cbTbl, 0, sizeof(cbTbl)); cbTbl.probe = konicawc_probe; cbTbl.setupOnOpen = konicawc_setup_on_open; cbTbl.processData = konicawc_process_isoc; cbTbl.getFPS = konicawc_calculate_fps; cbTbl.setVideoMode = konicawc_set_video_mode; cbTbl.startDataPump = konicawc_start_data; cbTbl.stopDataPump = konicawc_stop_data; cbTbl.adjustPicture = konicawc_adjust_picture; cbTbl.userFree = konicawc_free_uvd; return usbvideo_register( &cams, MAX_CAMERAS, sizeof(struct konicawc), "konicawc", &cbTbl, THIS_MODULE, id_table);}static void __exit konicawc_cleanup(void){ usbvideo_Deregister(&cams);}MODULE_DEVICE_TABLE(usb, id_table);MODULE_LICENSE("GPL");MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");MODULE_DESCRIPTION(DRIVER_DESC);module_param(speed, int, 0);MODULE_PARM_DESC(speed, "Initial speed: 0 (slowest) - 6 (fastest)");module_param(size, int, 0);MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 160x136 2: 176x144 3: 320x240");module_param(brightness, int, 0);MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108");module_param(contrast, int, 0);MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108");module_param(saturation, int, 0);MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108");module_param(sharpness, int, 0);MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108");module_param(whitebal, int, 0);MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363");#ifdef CONFIG_USB_DEBUGmodule_param(debug, int, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");#endifmodule_init(konicawc_init);module_exit(konicawc_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -