sonixb.c
来自「trident tm5600的linux驱动」· C语言 代码 · 共 1,309 行 · 第 1/3 页
C
1,309 行
}/* 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; reg_r(gspca_dev, 0x00); if (gspca_dev->usb_buf[0] != 0x10) return -ENODEV; /* copy the webcam info from the device id */ sd->sensor = id->driver_info >> 8; sd->bridge = id->driver_info & 0xff; gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis; cam = &gspca_dev->cam; cam->epaddr = 0x01; if (!(sensor_data[sd->sensor].flags & F_SIF)) { cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); } else { cam->cam_mode = sif_mode; cam->nmodes = ARRAY_SIZE(sif_mode); } sd->brightness = BRIGHTNESS_DEF; sd->gain = GAIN_DEF; sd->exposure = EXPOSURE_DEF; if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX)) sd->autogain = 0; /* Disable do_autogain callback */ else sd->autogain = AUTOGAIN_DEF; sd->freq = FREQ_DEF; return 0;}/* this function is called at probe and resume time */static int sd_init(struct gspca_dev *gspca_dev){ const __u8 stop = 0x09; /* Disable stream turn of LED */ reg_w(gspca_dev, 0x01, &stop, 1); return 0;}/* -- start the camera -- */static int sd_start(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; struct cam *cam = &gspca_dev->cam; int mode, l; const __u8 *sn9c10x; __u8 reg12_19[8]; mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07; sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge]; l = sensor_data[sd->sensor].bridge_init_size[sd->bridge]; memcpy(reg12_19, &sn9c10x[0x12 - 1], 8); reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4); /* Special cases where reg 17 and or 19 value depends on mode */ switch (sd->sensor) { case SENSOR_PAS202: reg12_19[5] = mode ? 0x24 : 0x20; break; case SENSOR_TAS5130CXX: /* probably not mode specific at all most likely the upper nibble of 0x19 is exposure (clock divider) just as with the tas5110, we need someone to test this. */ reg12_19[7] = mode ? 0x23 : 0x43; break; } /* Disable compression when the raw bayer format has been selected */ if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) reg12_19[6] &= ~0x80; /* Vga mode emulation on SIF sensor? */ if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) { reg12_19[0] += 16; /* 0x12: hstart adjust */ reg12_19[1] += 24; /* 0x13: vstart adjust */ reg12_19[3] = 320 / 16; /* 0x15: hsize */ reg12_19[4] = 240 / 16; /* 0x16: vsize */ } /* reg 0x01 bit 2 video transfert on */ reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1); /* reg 0x17 SensorClk enable inv Clk 0x60 */ reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1); /* Set the registers from the template */ reg_w(gspca_dev, 0x01, sn9c10x, l); /* Init the sensor */ i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init, sensor_data[sd->sensor].sensor_init_size); if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge]) i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_bridge_init[sd->bridge], sensor_data[sd->sensor].sensor_bridge_init_size[ sd->bridge]); /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ reg_w(gspca_dev, 0x15, ®12_19[3], 2); /* compression register */ reg_w(gspca_dev, 0x18, ®12_19[6], 1); /* H_start */ reg_w(gspca_dev, 0x12, ®12_19[0], 1); /* V_START */ reg_w(gspca_dev, 0x13, ®12_19[1], 1); /* reset 0x17 SensorClk enable inv Clk 0x60 */ /*fixme: ov7630 [17]=68 8f (+20 if 102)*/ reg_w(gspca_dev, 0x17, ®12_19[5], 1); /*MCKSIZE ->3 */ /*fixme: not ov7630*/ reg_w(gspca_dev, 0x19, ®12_19[7], 1); /* AE_STRX AE_STRY AE_ENDX AE_ENDY */ reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4); /* Enable video transfert */ reg_w(gspca_dev, 0x01, &sn9c10x[0], 1); /* Compression */ reg_w(gspca_dev, 0x18, ®12_19[6], 2); msleep(20); sd->reg11 = -1; setgain(gspca_dev); setbrightness(gspca_dev); setexposure(gspca_dev); setfreq(gspca_dev); sd->frames_to_drop = 0; sd->autogain_ignore_frames = 0; atomic_set(&sd->avg_lum, -1); return 0;}static void sd_stopN(struct gspca_dev *gspca_dev){ sd_init(gspca_dev);}static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ unsigned char *data, /* isoc packet */ int len) /* iso packet length */{ int i; struct sd *sd = (struct sd *) gspca_dev; struct cam *cam = &gspca_dev->cam; /* frames start with: * ff ff 00 c4 c4 96 synchro * 00 (unknown) * xx (frame sequence / size / compression) * (xx) (idem - extra byte for sn9c103) * ll mm brightness sum inside auto exposure * ll mm brightness sum outside auto exposure * (xx xx xx xx xx) audio values for snc103 */ if (len > 6 && len < 24) { for (i = 0; i < len - 6; i++) { if (data[0 + i] == 0xff && data[1 + i] == 0xff && data[2 + i] == 0x00 && data[3 + i] == 0xc4 && data[4 + i] == 0xc4 && data[5 + i] == 0x96) { /* start of frame */ int lum = -1; int pkt_type = LAST_PACKET; int fr_h_sz = (sd->bridge == BRIDGE_103) ? 18 : 12; if (len - i < fr_h_sz) { PDEBUG(D_STREAM, "packet too short to" " get avg brightness"); } else if (sd->bridge == BRIDGE_103) { lum = data[i + 9] + (data[i + 10] << 8); } else { lum = data[i + 8] + (data[i + 9] << 8); } /* When exposure changes midway a frame we get a lum of 0 in this case drop 2 frames as the frames directly after an exposure change have an unstable image. Sometimes lum *really* is 0 (cam used in low light with low exposure setting), so do not drop frames if the previous lum was 0 too. */ if (lum == 0 && sd->prev_avg_lum != 0) { lum = -1; sd->frames_to_drop = 2; sd->prev_avg_lum = 0; } else sd->prev_avg_lum = lum; atomic_set(&sd->avg_lum, lum); if (sd->frames_to_drop) { sd->frames_to_drop--; pkt_type = DISCARD_PACKET; } frame = gspca_frame_add(gspca_dev, pkt_type, frame, data, 0); data += i + fr_h_sz; len -= i + fr_h_sz; gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); return; } } } if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { /* In raw mode we sometimes get some garbage after the frame ignore this */ int used = frame->data_end - frame->data; int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage; if (used + len > size) len = size - used; } 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; *val = sd->brightness; return 0;}static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val){ struct sd *sd = (struct sd *) gspca_dev; sd->gain = val; if (gspca_dev->streaming) setgain(gspca_dev); return 0;}static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val){ struct sd *sd = (struct sd *) gspca_dev; *val = sd->gain; return 0;}static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val){ struct sd *sd = (struct sd *) gspca_dev; sd->exposure = val; if (gspca_dev->streaming) setexposure(gspca_dev); return 0;}static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val){ struct sd *sd = (struct sd *) gspca_dev; *val = sd->exposure; return 0;}static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val){ struct sd *sd = (struct sd *) gspca_dev; sd->autogain = val; /* when switching to autogain set defaults to make sure we are on a valid point of the autogain gain / exposure knee graph, and give this change time to take effect before doing autogain. */ if (sd->autogain) { sd->exposure = EXPOSURE_DEF; sd->gain = GAIN_DEF; if (gspca_dev->streaming) { sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; setexposure(gspca_dev); setgain(gspca_dev); } } return 0;}static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val){ struct sd *sd = (struct sd *) gspca_dev; *val = sd->autogain; return 0;}static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val){ struct sd *sd = (struct sd *) gspca_dev; sd->freq = val; if (gspca_dev->streaming) setfreq(gspca_dev); return 0;}static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val){ struct sd *sd = (struct sd *) gspca_dev; *val = sd->freq; return 0;}static int sd_querymenu(struct gspca_dev *gspca_dev, struct v4l2_querymenu *menu){ switch (menu->id) { case V4L2_CID_POWER_LINE_FREQUENCY: switch (menu->index) { case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ strcpy((char *) menu->name, "NoFliker"); return 0; case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ strcpy((char *) menu->name, "50 Hz"); return 0; case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ strcpy((char *) menu->name, "60 Hz"); return 0; } break; } return -EINVAL;}/* 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, .pkt_scan = sd_pkt_scan, .querymenu = sd_querymenu, .dq_callback = do_autogain,};/* -- module initialisation -- */#define SB(sensor, bridge) \ .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridgestatic __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */ {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)}, /* TAS5110D */ {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},#endif {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)}, {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)}, {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)}, {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},#endif {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},#endif {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},#endif {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)}, {}};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 + -
显示快捷键?