spca501.c
来自「trident tm5600的linux驱动」· C语言 代码 · 共 2,185 行 · 第 1/4 页
C
2,185 行
{0x05, 0x0033, 0x0001}, {0x05, 0x0023, 0x0000}, {0x05, 0x0034, 0x0001}, {0x05, 0x0002, 0x0000}, {0x05, 0x0050, 0x0001}, {0x05, 0x0000, 0x0000}, {0x05, 0x0051, 0x0001}, {0x05, 0x0000, 0x0000}, {0x05, 0x0052, 0x0001}, {0x05, 0x0000, 0x0000}, {0x05, 0x0054, 0x0001}, {0x05, 0x0001, 0x0000}, {}};/* Based on snoops from Ori Cohen */static const __u16 spca501c_mysterious_init_data[][3] = {/* Part 3 *//* TG registers *//* {0x00, 0x0000, 0x0000}, */ {0x00, 0x0000, 0x0001}, {0x00, 0x0000, 0x0002}, {0x00, 0x0006, 0x0003}, {0x00, 0x0000, 0x0004}, {0x00, 0x0090, 0x0005}, {0x00, 0x0000, 0x0006}, {0x00, 0x0040, 0x0007}, {0x00, 0x00c0, 0x0008}, {0x00, 0x004a, 0x0009}, {0x00, 0x0000, 0x000a}, {0x00, 0x0000, 0x000b}, {0x00, 0x0001, 0x000c}, {0x00, 0x0001, 0x000d}, {0x00, 0x0000, 0x000e}, {0x00, 0x0002, 0x000f}, {0x00, 0x0001, 0x0010}, {0x00, 0x0000, 0x0011}, {0x00, 0x0001, 0x0012}, {0x00, 0x0002, 0x0020}, {0x00, 0x0080, 0x0021}, /* 640 */ {0x00, 0x0001, 0x0022}, {0x00, 0x00e0, 0x0023}, /* 480 */ {0x00, 0x0000, 0x0024}, /* Offset H hight */ {0x00, 0x00d3, 0x0025}, /* low */ {0x00, 0x0000, 0x0026}, /* Offset V */ {0x00, 0x000d, 0x0027}, /* low */ {0x00, 0x0000, 0x0046}, {0x00, 0x0000, 0x0047}, {0x00, 0x0000, 0x0048}, {0x00, 0x0000, 0x0049}, {0x00, 0x0008, 0x004a},/* DSP Registers */ {0x01, 0x00a6, 0x0000}, {0x01, 0x0028, 0x0001}, {0x01, 0x0000, 0x0002}, {0x01, 0x000a, 0x0003}, /* Level Calc bit7 ->1 Auto */ {0x01, 0x0040, 0x0004}, {0x01, 0x0066, 0x0007}, {0x01, 0x000f, 0x0008}, /* A11 Color correction coeff */ {0x01, 0x002d, 0x0009}, /* A12 */ {0x01, 0x0005, 0x000a}, /* A13 */ {0x01, 0x0023, 0x000b}, /* A21 */ {0x01, 0x00e0, 0x000c}, /* A22 */ {0x01, 0x00fd, 0x000d}, /* A23 */ {0x01, 0x00f4, 0x000e}, /* A31 */ {0x01, 0x00e4, 0x000f}, /* A32 */ {0x01, 0x0028, 0x0010}, /* A33 */ {0x01, 0x00ff, 0x0015}, /* Reserved */ {0x01, 0x0001, 0x0016}, /* Reserved */ {0x01, 0x0032, 0x0017}, /* Win1 Start begin */ {0x01, 0x0023, 0x0018}, {0x01, 0x00ce, 0x0019}, {0x01, 0x0023, 0x001a}, {0x01, 0x0032, 0x001b}, {0x01, 0x008d, 0x001c}, {0x01, 0x00ce, 0x001d}, {0x01, 0x008d, 0x001e}, {0x01, 0x0000, 0x001f}, {0x01, 0x0000, 0x0020}, /* Win1 Start end */ {0x01, 0x00ff, 0x003e}, /* Reserved begin */ {0x01, 0x0002, 0x003f}, {0x01, 0x0000, 0x0040}, {0x01, 0x0035, 0x0041}, {0x01, 0x0053, 0x0042}, {0x01, 0x0069, 0x0043}, {0x01, 0x007c, 0x0044}, {0x01, 0x008c, 0x0045}, {0x01, 0x009a, 0x0046}, {0x01, 0x00a8, 0x0047}, {0x01, 0x00b4, 0x0048}, {0x01, 0x00bf, 0x0049}, {0x01, 0x00ca, 0x004a}, {0x01, 0x00d4, 0x004b}, {0x01, 0x00dd, 0x004c}, {0x01, 0x00e7, 0x004d}, {0x01, 0x00ef, 0x004e}, {0x01, 0x00f8, 0x004f}, {0x01, 0x00ff, 0x0050}, {0x01, 0x0003, 0x0056}, /* Reserved end */ {0x01, 0x0060, 0x0057}, /* Edge Gain */ {0x01, 0x0040, 0x0058}, {0x01, 0x0011, 0x0059}, /* Edge Bandwidth */ {0x01, 0x0001, 0x005a}, {0x02, 0x0007, 0x0005}, {0x02, 0xa048, 0x0000}, {0x02, 0x0007, 0x0005}, {0x02, 0x0015, 0x0006}, {0x02, 0x200a, 0x0007}, {0x02, 0xa048, 0x0000}, {0x02, 0xc000, 0x0001}, {0x02, 0x000f, 0x0005}, {0x02, 0xa048, 0x0000}, {0x05, 0x0022, 0x0004}, {0x05, 0x0025, 0x0001}, {0x05, 0x0000, 0x0000},/* Part 4 */ {0x05, 0x0026, 0x0001}, {0x05, 0x0001, 0x0000}, {0x05, 0x0027, 0x0001}, {0x05, 0x0000, 0x0000}, {0x05, 0x0001, 0x0001}, {0x05, 0x0000, 0x0000}, {0x05, 0x0021, 0x0001}, {0x05, 0x00d2, 0x0000}, {0x05, 0x0020, 0x0001}, {0x05, 0x0000, 0x0000}, {0x00, 0x0090, 0x0005}, {0x01, 0x00a6, 0x0000}, {0x02, 0x0000, 0x0005}, {0x05, 0x0026, 0x0001}, {0x05, 0x0001, 0x0000}, {0x05, 0x0027, 0x0001}, {0x05, 0x004e, 0x0000},/* Part 5 */ {0x01, 0x0003, 0x003f}, {0x01, 0x0001, 0x0056}, {0x01, 0x000f, 0x0008}, {0x01, 0x002d, 0x0009}, {0x01, 0x0005, 0x000a}, {0x01, 0x0023, 0x000b}, {0x01, 0xffe0, 0x000c}, {0x01, 0xfffd, 0x000d}, {0x01, 0xfff4, 0x000e}, {0x01, 0xffe4, 0x000f}, {0x01, 0x0028, 0x0010}, {0x01, 0x00a8, 0x0001}, {0x01, 0x0066, 0x0007}, {0x01, 0x0032, 0x0017}, {0x01, 0x0023, 0x0018}, {0x01, 0x00ce, 0x0019}, {0x01, 0x0023, 0x001a}, {0x01, 0x0032, 0x001b}, {0x01, 0x008d, 0x001c}, {0x01, 0x00ce, 0x001d}, {0x01, 0x008d, 0x001e}, {0x01, 0x00c8, 0x0015}, /* c8 Poids fort Luma */ {0x01, 0x0032, 0x0016}, /* 32 */ {0x01, 0x0016, 0x0011}, /* R 00 */ {0x01, 0x0016, 0x0012}, /* G 00 */ {0x01, 0x0016, 0x0013}, /* B 00 */ {0x01, 0x000a, 0x0003}, {0x02, 0xc002, 0x0001}, {0x02, 0x0007, 0x0005}, {}};static int reg_write(struct usb_device *dev, __u16 req, __u16 index, __u16 value){ int ret; ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), req, USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, NULL, 0, 500); PDEBUG(D_USBO, "reg write: 0x%02x 0x%02x 0x%02x", req, index, value); if (ret < 0) PDEBUG(D_ERR, "reg write: error %d", ret); return ret;}/* returns: negative is error, pos or zero is data */static int reg_read(struct gspca_dev *gspca_dev, __u16 req, /* bRequest */ __u16 index, /* wIndex */ __u16 length) /* wLength (1 or 2 only) */{ int ret; gspca_dev->usb_buf[1] = 0; ret = usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, /* value */ index, gspca_dev->usb_buf, length, 500); /* timeout */ if (ret < 0) { PDEBUG(D_ERR, "reg_read err %d", ret); return -1; } return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];}static int write_vector(struct gspca_dev *gspca_dev, const __u16 data[][3]){ struct usb_device *dev = gspca_dev->dev; int ret, i = 0; while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) { ret = reg_write(dev, data[i][0], data[i][2], data[i][1]); if (ret < 0) { PDEBUG(D_ERR, "Reg write failed for 0x%02x,0x%02x,0x%02x", data[i][0], data[i][1], data[i][2]); return ret; } i++; } return 0;}static void setbrightness(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x11, sd->brightness); reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x12, sd->brightness); reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x13, sd->brightness);}static void getbrightness(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; __u16 brightness; brightness = reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x11, 2); sd->brightness = brightness << 1;}static void setcontrast(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; reg_write(gspca_dev->dev, 0x00, 0x00, (sd->contrast >> 8) & 0xff); reg_write(gspca_dev->dev, 0x00, 0x01, sd->contrast & 0xff);}static void getcontrast(struct gspca_dev *gspca_dev){#if 0 __u8 byte = 0; byte = (reg_read(gspca_dev, 0x00, 0x00, 1) & 0xff) << 8; ss->contrast = byte | (reg_read(gspca_dev, 0x00, 0x01, 1) & 0xff);#endif/* spca50x->contrast = 0xaa01; */}static void setcolors(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x0c, sd->colors);}static void getcolors(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; sd->colors = reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x0c, 2);/* sd->hue = (reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x13, *//* 2) & 0xFF) << 8; */}/* this function is called at probe time */static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id){ struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; cam = &gspca_dev->cam; cam->epaddr = 0x01; cam->cam_mode = vga_mode; cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; sd->subtype = id->driver_info; sd->brightness = sd_ctrls[MY_BRIGHTNESS].qctrl.default_value; sd->contrast = sd_ctrls[MY_CONTRAST].qctrl.default_value; sd->colors = sd_ctrls[MY_COLOR].qctrl.default_value; switch (sd->subtype) { case Arowana300KCMOSCamera: case SmileIntlCamera: /* Arowana 300k CMOS Camera data */ if (write_vector(gspca_dev, spca501c_arowana_init_data)) goto error; break; case MystFromOriUnknownCamera: /* UnKnow Ori CMOS Camera data */ if (write_vector(gspca_dev, spca501c_mysterious_open_data)) goto error; break; default: /* generic spca501 init data */ if (write_vector(gspca_dev, spca501_init_data)) goto error; break; } return 0;error: return -EINVAL;}/* this function is called at probe and resume time */static int sd_init(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; switch (sd->subtype) { case ThreeComHomeConnectLite: /* Special handling for 3com data */ write_vector(gspca_dev, spca501_3com_open_data); break; case Arowana300KCMOSCamera: case SmileIntlCamera: /* Arowana 300k CMOS Camera data */ write_vector(gspca_dev, spca501c_arowana_open_data); break; case MystFromOriUnknownCamera: /* UnKnow CMOS Camera data */ write_vector(gspca_dev, spca501c_mysterious_init_data); break; default: /* Generic 501 open data */ write_vector(gspca_dev, spca501_open_data); } PDEBUG(D_STREAM, "Initializing SPCA501 finished"); return 0;}static int sd_start(struct gspca_dev *gspca_dev){ struct usb_device *dev = gspca_dev->dev; int mode; /* memorize the wanted pixel format */ mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; /* Enable ISO packet machine CTRL reg=2, * index=1 bitmask=0x2 (bit ordinal 1) */ reg_write(dev, SPCA50X_REG_USB, 0x6, 0x94); switch (mode) { case 0: /* 640x480 */ reg_write(dev, SPCA50X_REG_USB, 0x07, 0x004a); break; case 1: /* 320x240 */ reg_write(dev, SPCA50X_REG_USB, 0x07, 0x104a); break; default:/* case 2: * 160x120 */ reg_write(dev, SPCA50X_REG_USB, 0x07, 0x204a); break; } reg_write(dev, SPCA501_REG_CTLRL, 0x01, 0x02); /* HDG atleast the Intel CreateAndShare needs to have one of its * brightness / contrast / color set otherwise it assumes what seems * max contrast. Note that strange enough setting any of these is * enough to fix the max contrast problem, to be sure we set all 3 */ setbrightness(gspca_dev); setcontrast(gspca_dev); setcolors(gspca_dev); return 0;}static void sd_stopN(struct gspca_dev *gspca_dev){ /* Disable ISO packet * machine CTRL reg=2, index=1 bitmask=0x0 (bit ordinal 1) */ reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00);}static void sd_stop0(struct gspca_dev *gspca_dev){ reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);}static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ int len) /* iso packet length */{ switch (data[0]) { case 0: /* start of frame */ frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); data += SPCA501_OFFSET_DATA; len -= SPCA501_OFFSET_DATA; gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); return; case 0xff: /* drop *//* gspca_dev->last_packet_type = DISCARD_PACKET; */ return; } data++; len--; gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);}static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val){ struct sd *sd = (struct sd *) gspca_dev; sd->brightness = val; if (gspca_dev->streaming) setbrightness(gspca_dev); return 0;}static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val){ struct sd *sd = (struct sd *) gspca_dev; getbrightness(gspca_dev); *val = sd->brightness; return 0;}static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val){ struct sd *sd = (struct sd *) gspca_dev; sd->contrast = val; if (gspca_dev->streaming) setcontrast(gspca_dev); return 0;}static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val){ struct sd *sd = (struct sd *) gspca_dev; getcontrast(gspca_dev); *val = sd->contrast; return 0;}static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val){ struct sd *sd = (struct sd *) gspca_dev; sd->colors = val; if (gspca_dev->streaming) setcolors(gspca_dev); return 0;}static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val){ struct sd *sd = (struct sd *) gspca_dev; getcolors(gspca_dev); *val = sd->colors; return 0;}/* sub-driver description */static const struct sd_desc sd_desc = { .name = MODULE_NAME, .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, .init = sd_init, .start = sd_start, .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan,};/* -- module initialisation -- */static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x040a, 0x0002), .driver_info = KodakDVC325}, {USB_DEVICE(0x0497, 0xc001), .driver_info = SmileIntlCamera}, {USB_DEVICE(0x0506, 0x00df), .driver_info = ThreeComHomeConnectLite}, {USB_DEVICE(0x0733, 0x0401), .driver_info = IntelCreateAndShare}, {USB_DEVICE(0x0733, 0x0402), .driver_info = ViewQuestM318B}, {USB_DEVICE(0x1776, 0x501c), .driver_info = Arowana300KCMOSCamera}, {USB_DEVICE(0x0000, 0x0000), .driver_info = MystFromOriUnknownCamera}, {}};MODULE_DEVICE_TABLE(usb, device_table);/* -- device connect -- */static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id){ return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), THIS_MODULE);}static struct usb_driver sd_driver = { .name = MODULE_NAME, .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect,#ifdef CONFIG_PM .suspend = gspca_suspend, .resume = gspca_resume,#endif};/* -- module insert / remove -- */static int __init sd_mod_init(void){ if (usb_register(&sd_driver) < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0;}static void __exit sd_mod_exit(void){ usb_deregister(&sd_driver); PDEBUG(D_PROBE, "deregistered");}module_init(sd_mod_init);module_exit(sd_mod_exit);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?