brintos

brintos / linux-shallow public Read only

0
0
Text · 13.0 KiB · 20b2468 Raw
538 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Jeilinj subdriver4 *5 * Supports some Jeilin dual-mode cameras which use bulk transport and6 * download raw JPEG data.7 *8 * Copyright (C) 2009 Theodore Kilgore9 *10 * Sportscam DV15 support and control settings are11 * Copyright (C) 2011 Patrice Chotard12 */13 14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt15 16#define MODULE_NAME "jeilinj"17 18#include <linux/slab.h>19#include "gspca.h"20#include "jpeg.h"21 22MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");23MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver");24MODULE_LICENSE("GPL");25 26/* Default timeouts, in ms */27#define JEILINJ_CMD_TIMEOUT 50028#define JEILINJ_CMD_DELAY 16029#define JEILINJ_DATA_TIMEOUT 100030 31/* Maximum transfer size to use. */32#define JEILINJ_MAX_TRANSFER 0x20033#define FRAME_HEADER_LEN 0x1034#define FRAME_START 0xFFFFFFFF35 36enum {37	SAKAR_57379,38	SPORTSCAM_DV15,39};40 41#define CAMQUALITY_MIN 0	/* highest cam quality */42#define CAMQUALITY_MAX 97	/* lowest cam quality  */43 44/* Structure to hold all of our device specific stuff */45struct sd {46	struct gspca_dev gspca_dev;	/* !! must be the first item */47	int blocks_left;48	const struct v4l2_pix_format *cap_mode;49	struct v4l2_ctrl *freq;50	struct v4l2_ctrl *jpegqual;51	/* Driver stuff */52	u8 type;53	u8 quality;				 /* image quality */54#define QUALITY_MIN 3555#define QUALITY_MAX 8556#define QUALITY_DEF 8557	u8 jpeg_hdr[JPEG_HDR_SZ];58};59 60struct jlj_command {61	unsigned char instruction[2];62	unsigned char ack_wanted;63	unsigned char delay;64};65 66/* AFAICT these cameras will only do 320x240. */67static struct v4l2_pix_format jlj_mode[] = {68	{ 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,69		.bytesperline = 320,70		.sizeimage = 320 * 240,71		.colorspace = V4L2_COLORSPACE_JPEG,72		.priv = 0},73	{ 640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,74		.bytesperline = 640,75		.sizeimage = 640 * 480,76		.colorspace = V4L2_COLORSPACE_JPEG,77		.priv = 0}78};79 80/*81 * cam uses endpoint 0x03 to send commands, 0x84 for read commands,82 * and 0x82 for bulk transfer.83 */84 85/* All commands are two bytes only */86static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)87{88	int retval;89 90	if (gspca_dev->usb_err < 0)91		return;92	memcpy(gspca_dev->usb_buf, command, 2);93	retval = usb_bulk_msg(gspca_dev->dev,94			usb_sndbulkpipe(gspca_dev->dev, 3),95			gspca_dev->usb_buf, 2, NULL, 500);96	if (retval < 0) {97		pr_err("command write [%02x] error %d\n",98		       gspca_dev->usb_buf[0], retval);99		gspca_dev->usb_err = retval;100	}101}102 103/* Responses are one byte only */104static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char *response)105{106	int retval;107 108	if (gspca_dev->usb_err < 0)109		return;110	retval = usb_bulk_msg(gspca_dev->dev,111	usb_rcvbulkpipe(gspca_dev->dev, 0x84),112				gspca_dev->usb_buf, 1, NULL, 500);113	*response = gspca_dev->usb_buf[0];114	if (retval < 0) {115		pr_err("read command [%02x] error %d\n",116		       gspca_dev->usb_buf[0], retval);117		gspca_dev->usb_err = retval;118	}119}120 121static void setfreq(struct gspca_dev *gspca_dev, s32 val)122{123	u8 freq_commands[][2] = {124		{0x71, 0x80},125		{0x70, 0x07}126	};127 128	freq_commands[0][1] |= val >> 1;129 130	jlj_write2(gspca_dev, freq_commands[0]);131	jlj_write2(gspca_dev, freq_commands[1]);132}133 134static void setcamquality(struct gspca_dev *gspca_dev, s32 val)135{136	u8 quality_commands[][2] = {137		{0x71, 0x1E},138		{0x70, 0x06}139	};140	u8 camquality;141 142	/* adapt camera quality from jpeg quality */143	camquality = ((QUALITY_MAX - val) * CAMQUALITY_MAX)144		/ (QUALITY_MAX - QUALITY_MIN);145	quality_commands[0][1] += camquality;146 147	jlj_write2(gspca_dev, quality_commands[0]);148	jlj_write2(gspca_dev, quality_commands[1]);149}150 151static void setautogain(struct gspca_dev *gspca_dev, s32 val)152{153	u8 autogain_commands[][2] = {154		{0x94, 0x02},155		{0xcf, 0x00}156	};157 158	autogain_commands[1][1] = val << 4;159 160	jlj_write2(gspca_dev, autogain_commands[0]);161	jlj_write2(gspca_dev, autogain_commands[1]);162}163 164static void setred(struct gspca_dev *gspca_dev, s32 val)165{166	u8 setred_commands[][2] = {167		{0x94, 0x02},168		{0xe6, 0x00}169	};170 171	setred_commands[1][1] = val;172 173	jlj_write2(gspca_dev, setred_commands[0]);174	jlj_write2(gspca_dev, setred_commands[1]);175}176 177static void setgreen(struct gspca_dev *gspca_dev, s32 val)178{179	u8 setgreen_commands[][2] = {180		{0x94, 0x02},181		{0xe7, 0x00}182	};183 184	setgreen_commands[1][1] = val;185 186	jlj_write2(gspca_dev, setgreen_commands[0]);187	jlj_write2(gspca_dev, setgreen_commands[1]);188}189 190static void setblue(struct gspca_dev *gspca_dev, s32 val)191{192	u8 setblue_commands[][2] = {193		{0x94, 0x02},194		{0xe9, 0x00}195	};196 197	setblue_commands[1][1] = val;198 199	jlj_write2(gspca_dev, setblue_commands[0]);200	jlj_write2(gspca_dev, setblue_commands[1]);201}202 203static int jlj_start(struct gspca_dev *gspca_dev)204{205	int i;206	int start_commands_size;207	u8 response = 0xff;208	struct sd *sd = (struct sd *) gspca_dev;209	struct jlj_command start_commands[] = {210		{{0x71, 0x81}, 0, 0},211		{{0x70, 0x05}, 0, JEILINJ_CMD_DELAY},212		{{0x95, 0x70}, 1, 0},213		{{0x71, 0x81 - gspca_dev->curr_mode}, 0, 0},214		{{0x70, 0x04}, 0, JEILINJ_CMD_DELAY},215		{{0x95, 0x70}, 1, 0},216		{{0x71, 0x00}, 0, 0},   /* start streaming ??*/217		{{0x70, 0x08}, 0, JEILINJ_CMD_DELAY},218		{{0x95, 0x70}, 1, 0},219#define SPORTSCAM_DV15_CMD_SIZE 9220		{{0x94, 0x02}, 0, 0},221		{{0xde, 0x24}, 0, 0},222		{{0x94, 0x02}, 0, 0},223		{{0xdd, 0xf0}, 0, 0},224		{{0x94, 0x02}, 0, 0},225		{{0xe3, 0x2c}, 0, 0},226		{{0x94, 0x02}, 0, 0},227		{{0xe4, 0x00}, 0, 0},228		{{0x94, 0x02}, 0, 0},229		{{0xe5, 0x00}, 0, 0},230		{{0x94, 0x02}, 0, 0},231		{{0xe6, 0x2c}, 0, 0},232		{{0x94, 0x03}, 0, 0},233		{{0xaa, 0x00}, 0, 0}234	};235 236	sd->blocks_left = 0;237	/* Under Windows, USB spy shows that only the 9 first start238	 * commands are used for SPORTSCAM_DV15 webcam239	 */240	if (sd->type == SPORTSCAM_DV15)241		start_commands_size = SPORTSCAM_DV15_CMD_SIZE;242	else243		start_commands_size = ARRAY_SIZE(start_commands);244 245	for (i = 0; i < start_commands_size; i++) {246		jlj_write2(gspca_dev, start_commands[i].instruction);247		if (start_commands[i].delay)248			msleep(start_commands[i].delay);249		if (start_commands[i].ack_wanted)250			jlj_read1(gspca_dev, &response);251	}252	setcamquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));253	msleep(2);254	setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));255	if (gspca_dev->usb_err < 0)256		gspca_err(gspca_dev, "Start streaming command failed\n");257	return gspca_dev->usb_err;258}259 260static void sd_pkt_scan(struct gspca_dev *gspca_dev,261			u8 *data, int len)262{263	struct sd *sd = (struct sd *) gspca_dev;264	int packet_type;265	u32 header_marker;266 267	gspca_dbg(gspca_dev, D_STREAM, "Got %d bytes out of %d for Block 0\n",268		  len, JEILINJ_MAX_TRANSFER);269	if (len != JEILINJ_MAX_TRANSFER) {270		gspca_dbg(gspca_dev, D_PACK, "bad length\n");271		goto discard;272	}273	/* check if it's start of frame */274	header_marker = ((u32 *)data)[0];275	if (header_marker == FRAME_START) {276		sd->blocks_left = data[0x0a] - 1;277		gspca_dbg(gspca_dev, D_STREAM, "blocks_left = 0x%x\n",278			  sd->blocks_left);279		/* Start a new frame, and add the JPEG header, first thing */280		gspca_frame_add(gspca_dev, FIRST_PACKET,281				sd->jpeg_hdr, JPEG_HDR_SZ);282		/* Toss line 0 of data block 0, keep the rest. */283		gspca_frame_add(gspca_dev, INTER_PACKET,284				data + FRAME_HEADER_LEN,285				JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN);286	} else if (sd->blocks_left > 0) {287		gspca_dbg(gspca_dev, D_STREAM, "%d blocks remaining for frame\n",288			  sd->blocks_left);289		sd->blocks_left -= 1;290		if (sd->blocks_left == 0)291			packet_type = LAST_PACKET;292		else293			packet_type = INTER_PACKET;294		gspca_frame_add(gspca_dev, packet_type,295				data, JEILINJ_MAX_TRANSFER);296	} else297		goto discard;298	return;299discard:300	/* Discard data until a new frame starts. */301	gspca_dev->last_packet_type = DISCARD_PACKET;302}303 304/* This function is called at probe time just before sd_init */305static int sd_config(struct gspca_dev *gspca_dev,306		const struct usb_device_id *id)307{308	struct cam *cam = &gspca_dev->cam;309	struct sd *dev  = (struct sd *) gspca_dev;310 311	dev->type = id->driver_info;312	dev->quality = QUALITY_DEF;313 314	cam->cam_mode = jlj_mode;315	cam->nmodes = ARRAY_SIZE(jlj_mode);316	cam->bulk = 1;317	cam->bulk_nurbs = 1;318	cam->bulk_size = JEILINJ_MAX_TRANSFER;319	return 0;320}321 322static void sd_stopN(struct gspca_dev *gspca_dev)323{324	int i;325	u8 *buf;326	static u8 stop_commands[][2] = {327		{0x71, 0x00},328		{0x70, 0x09},329		{0x71, 0x80},330		{0x70, 0x05}331	};332 333	for (;;) {334		/* get the image remaining blocks */335		usb_bulk_msg(gspca_dev->dev,336				gspca_dev->urb[0]->pipe,337				gspca_dev->urb[0]->transfer_buffer,338				JEILINJ_MAX_TRANSFER, NULL,339				JEILINJ_DATA_TIMEOUT);340 341		/* search for 0xff 0xd9  (EOF for JPEG) */342		i = 0;343		buf = gspca_dev->urb[0]->transfer_buffer;344		while ((i < (JEILINJ_MAX_TRANSFER - 1)) &&345			((buf[i] != 0xff) || (buf[i+1] != 0xd9)))346			i++;347 348		if (i != (JEILINJ_MAX_TRANSFER - 1))349			/* last remaining block found */350			break;351		}352 353	for (i = 0; i < ARRAY_SIZE(stop_commands); i++)354		jlj_write2(gspca_dev, stop_commands[i]);355}356 357/* this function is called at probe and resume time */358static int sd_init(struct gspca_dev *gspca_dev)359{360	return gspca_dev->usb_err;361}362 363/* Set up for getting frames. */364static int sd_start(struct gspca_dev *gspca_dev)365{366	struct sd *dev = (struct sd *) gspca_dev;367 368	/* create the JPEG header */369	jpeg_define(dev->jpeg_hdr, gspca_dev->pixfmt.height,370			gspca_dev->pixfmt.width,371			0x21);          /* JPEG 422 */372	jpeg_set_qual(dev->jpeg_hdr, dev->quality);373	gspca_dbg(gspca_dev, D_STREAM, "Start streaming at %dx%d\n",374		  gspca_dev->pixfmt.height, gspca_dev->pixfmt.width);375	jlj_start(gspca_dev);376	return gspca_dev->usb_err;377}378 379/* Table of supported USB devices */380static const struct usb_device_id device_table[] = {381	{USB_DEVICE(0x0979, 0x0280), .driver_info = SAKAR_57379},382	{USB_DEVICE(0x0979, 0x0270), .driver_info = SPORTSCAM_DV15},383	{}384};385 386MODULE_DEVICE_TABLE(usb, device_table);387 388static int sd_s_ctrl(struct v4l2_ctrl *ctrl)389{390	struct gspca_dev *gspca_dev =391		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);392	struct sd *sd = (struct sd *)gspca_dev;393 394	gspca_dev->usb_err = 0;395 396	if (!gspca_dev->streaming)397		return 0;398 399	switch (ctrl->id) {400	case V4L2_CID_POWER_LINE_FREQUENCY:401		setfreq(gspca_dev, ctrl->val);402		break;403	case V4L2_CID_RED_BALANCE:404		setred(gspca_dev, ctrl->val);405		break;406	case V4L2_CID_GAIN:407		setgreen(gspca_dev, ctrl->val);408		break;409	case V4L2_CID_BLUE_BALANCE:410		setblue(gspca_dev, ctrl->val);411		break;412	case V4L2_CID_AUTOGAIN:413		setautogain(gspca_dev, ctrl->val);414		break;415	case V4L2_CID_JPEG_COMPRESSION_QUALITY:416		jpeg_set_qual(sd->jpeg_hdr, ctrl->val);417		setcamquality(gspca_dev, ctrl->val);418		break;419	}420	return gspca_dev->usb_err;421}422 423static const struct v4l2_ctrl_ops sd_ctrl_ops = {424	.s_ctrl = sd_s_ctrl,425};426 427static int sd_init_controls(struct gspca_dev *gspca_dev)428{429	struct sd *sd = (struct sd *)gspca_dev;430	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;431	static const struct v4l2_ctrl_config custom_autogain = {432		.ops = &sd_ctrl_ops,433		.id = V4L2_CID_AUTOGAIN,434		.type = V4L2_CTRL_TYPE_INTEGER,435		.name = "Automatic Gain (and Exposure)",436		.max = 3,437		.step = 1,438		.def = 0,439	};440 441	gspca_dev->vdev.ctrl_handler = hdl;442	v4l2_ctrl_handler_init(hdl, 6);443	sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,444			V4L2_CID_POWER_LINE_FREQUENCY,445			V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,446			V4L2_CID_POWER_LINE_FREQUENCY_60HZ);447	v4l2_ctrl_new_custom(hdl, &custom_autogain, NULL);448	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,449			V4L2_CID_RED_BALANCE, 0, 3, 1, 2);450	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,451			V4L2_CID_GAIN, 0, 3, 1, 2);452	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,453			V4L2_CID_BLUE_BALANCE, 0, 3, 1, 2);454	sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,455			V4L2_CID_JPEG_COMPRESSION_QUALITY,456			QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);457 458	if (hdl->error) {459		pr_err("Could not initialize controls\n");460		return hdl->error;461	}462	return 0;463}464 465static int sd_set_jcomp(struct gspca_dev *gspca_dev,466			const struct v4l2_jpegcompression *jcomp)467{468	struct sd *sd = (struct sd *) gspca_dev;469 470	v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);471	return 0;472}473 474static int sd_get_jcomp(struct gspca_dev *gspca_dev,475			struct v4l2_jpegcompression *jcomp)476{477	struct sd *sd = (struct sd *) gspca_dev;478 479	memset(jcomp, 0, sizeof *jcomp);480	jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);481	jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT482			| V4L2_JPEG_MARKER_DQT;483	return 0;484}485 486 487/* sub-driver description */488static const struct sd_desc sd_desc_sakar_57379 = {489	.name   = MODULE_NAME,490	.config = sd_config,491	.init   = sd_init,492	.start  = sd_start,493	.stopN  = sd_stopN,494	.pkt_scan = sd_pkt_scan,495};496 497/* sub-driver description */498static const struct sd_desc sd_desc_sportscam_dv15 = {499	.name   = MODULE_NAME,500	.config = sd_config,501	.init   = sd_init,502	.init_controls = sd_init_controls,503	.start  = sd_start,504	.stopN  = sd_stopN,505	.pkt_scan = sd_pkt_scan,506	.get_jcomp = sd_get_jcomp,507	.set_jcomp = sd_set_jcomp,508};509 510static const struct sd_desc *sd_desc[2] = {511	&sd_desc_sakar_57379,512	&sd_desc_sportscam_dv15513};514 515/* -- device connect -- */516static int sd_probe(struct usb_interface *intf,517		const struct usb_device_id *id)518{519	return gspca_dev_probe(intf, id,520			sd_desc[id->driver_info],521			sizeof(struct sd),522			THIS_MODULE);523}524 525static struct usb_driver sd_driver = {526	.name       = MODULE_NAME,527	.id_table   = device_table,528	.probe      = sd_probe,529	.disconnect = gspca_disconnect,530#ifdef CONFIG_PM531	.suspend = gspca_suspend,532	.resume  = gspca_resume,533	.reset_resume = gspca_resume,534#endif535};536 537module_usb_driver(sd_driver);538