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, &reg12_19[3], 2);	/* compression register */	reg_w(gspca_dev, 0x18, &reg12_19[6], 1);	/* H_start */	reg_w(gspca_dev, 0x12, &reg12_19[0], 1);	/* V_START */	reg_w(gspca_dev, 0x13, &reg12_19[1], 1);	/* reset 0x17 SensorClk enable inv Clk 0x60 */				/*fixme: ov7630 [17]=68 8f (+20 if 102)*/	reg_w(gspca_dev, 0x17, &reg12_19[5], 1);	/*MCKSIZE ->3 */	/*fixme: not ov7630*/	reg_w(gspca_dev, 0x19, &reg12_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, &reg12_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 + -
显示快捷键?