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 + -
显示快捷键?