Path: blob/master/drivers/media/video/gspca/jeilinj.c
17723 views
/*1* Jeilinj subdriver2*3* Supports some Jeilin dual-mode cameras which use bulk transport and4* download raw JPEG data.5*6* Copyright (C) 2009 Theodore Kilgore7*8* Sportscam DV15 support and control settings are9* Copyright (C) 2011 Patrice Chotard10*11* This program is free software; you can redistribute it and/or modify12* it under the terms of the GNU General Public License as published by13* the Free Software Foundation; either version 2 of the License, or14* any later version.15*16* This program is distributed in the hope that it will be useful,17* but WITHOUT ANY WARRANTY; without even the implied warranty of18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the19* GNU General Public License for more details.20*21* You should have received a copy of the GNU General Public License22* along with this program; if not, write to the Free Software23* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA24*/2526#define MODULE_NAME "jeilinj"2728#include <linux/slab.h>29#include "gspca.h"30#include "jpeg.h"3132MODULE_AUTHOR("Theodore Kilgore <[email protected]>");33MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver");34MODULE_LICENSE("GPL");3536/* Default timeouts, in ms */37#define JEILINJ_CMD_TIMEOUT 50038#define JEILINJ_CMD_DELAY 16039#define JEILINJ_DATA_TIMEOUT 10004041/* Maximum transfer size to use. */42#define JEILINJ_MAX_TRANSFER 0x20043#define FRAME_HEADER_LEN 0x1044#define FRAME_START 0xFFFFFFFF4546enum {47SAKAR_57379,48SPORTSCAM_DV15,49};5051#define CAMQUALITY_MIN 0 /* highest cam quality */52#define CAMQUALITY_MAX 97 /* lowest cam quality */5354enum e_ctrl {55LIGHTFREQ,56AUTOGAIN,57RED,58GREEN,59BLUE,60NCTRLS /* number of controls */61};6263/* Structure to hold all of our device specific stuff */64struct sd {65struct gspca_dev gspca_dev; /* !! must be the first item */66struct gspca_ctrl ctrls[NCTRLS];67int blocks_left;68const struct v4l2_pix_format *cap_mode;69/* Driver stuff */70u8 type;71u8 quality; /* image quality */72#define QUALITY_MIN 3573#define QUALITY_MAX 8574#define QUALITY_DEF 8575u8 jpeg_hdr[JPEG_HDR_SZ];76};7778struct jlj_command {79unsigned char instruction[2];80unsigned char ack_wanted;81unsigned char delay;82};8384/* AFAICT these cameras will only do 320x240. */85static struct v4l2_pix_format jlj_mode[] = {86{ 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,87.bytesperline = 320,88.sizeimage = 320 * 240,89.colorspace = V4L2_COLORSPACE_JPEG,90.priv = 0},91{ 640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,92.bytesperline = 640,93.sizeimage = 640 * 480,94.colorspace = V4L2_COLORSPACE_JPEG,95.priv = 0}96};9798/*99* cam uses endpoint 0x03 to send commands, 0x84 for read commands,100* and 0x82 for bulk transfer.101*/102103/* All commands are two bytes only */104static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)105{106int retval;107108if (gspca_dev->usb_err < 0)109return;110memcpy(gspca_dev->usb_buf, command, 2);111retval = usb_bulk_msg(gspca_dev->dev,112usb_sndbulkpipe(gspca_dev->dev, 3),113gspca_dev->usb_buf, 2, NULL, 500);114if (retval < 0) {115err("command write [%02x] error %d",116gspca_dev->usb_buf[0], retval);117gspca_dev->usb_err = retval;118}119}120121/* Responses are one byte only */122static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char response)123{124int retval;125126if (gspca_dev->usb_err < 0)127return;128retval = usb_bulk_msg(gspca_dev->dev,129usb_rcvbulkpipe(gspca_dev->dev, 0x84),130gspca_dev->usb_buf, 1, NULL, 500);131response = gspca_dev->usb_buf[0];132if (retval < 0) {133err("read command [%02x] error %d",134gspca_dev->usb_buf[0], retval);135gspca_dev->usb_err = retval;136}137}138139static void setfreq(struct gspca_dev *gspca_dev)140{141struct sd *sd = (struct sd *) gspca_dev;142u8 freq_commands[][2] = {143{0x71, 0x80},144{0x70, 0x07}145};146147freq_commands[0][1] |= (sd->ctrls[LIGHTFREQ].val >> 1);148149jlj_write2(gspca_dev, freq_commands[0]);150jlj_write2(gspca_dev, freq_commands[1]);151}152153static void setcamquality(struct gspca_dev *gspca_dev)154{155struct sd *sd = (struct sd *) gspca_dev;156u8 quality_commands[][2] = {157{0x71, 0x1E},158{0x70, 0x06}159};160u8 camquality;161162/* adapt camera quality from jpeg quality */163camquality = ((QUALITY_MAX - sd->quality) * CAMQUALITY_MAX)164/ (QUALITY_MAX - QUALITY_MIN);165quality_commands[0][1] += camquality;166167jlj_write2(gspca_dev, quality_commands[0]);168jlj_write2(gspca_dev, quality_commands[1]);169}170171static void setautogain(struct gspca_dev *gspca_dev)172{173struct sd *sd = (struct sd *) gspca_dev;174u8 autogain_commands[][2] = {175{0x94, 0x02},176{0xcf, 0x00}177};178179autogain_commands[1][1] = (sd->ctrls[AUTOGAIN].val << 4);180181jlj_write2(gspca_dev, autogain_commands[0]);182jlj_write2(gspca_dev, autogain_commands[1]);183}184185static void setred(struct gspca_dev *gspca_dev)186{187struct sd *sd = (struct sd *) gspca_dev;188u8 setred_commands[][2] = {189{0x94, 0x02},190{0xe6, 0x00}191};192193setred_commands[1][1] = sd->ctrls[RED].val;194195jlj_write2(gspca_dev, setred_commands[0]);196jlj_write2(gspca_dev, setred_commands[1]);197}198199static void setgreen(struct gspca_dev *gspca_dev)200{201struct sd *sd = (struct sd *) gspca_dev;202u8 setgreen_commands[][2] = {203{0x94, 0x02},204{0xe7, 0x00}205};206207setgreen_commands[1][1] = sd->ctrls[GREEN].val;208209jlj_write2(gspca_dev, setgreen_commands[0]);210jlj_write2(gspca_dev, setgreen_commands[1]);211}212213static void setblue(struct gspca_dev *gspca_dev)214{215struct sd *sd = (struct sd *) gspca_dev;216u8 setblue_commands[][2] = {217{0x94, 0x02},218{0xe9, 0x00}219};220221setblue_commands[1][1] = sd->ctrls[BLUE].val;222223jlj_write2(gspca_dev, setblue_commands[0]);224jlj_write2(gspca_dev, setblue_commands[1]);225}226227static const struct ctrl sd_ctrls[NCTRLS] = {228[LIGHTFREQ] = {229{230.id = V4L2_CID_POWER_LINE_FREQUENCY,231.type = V4L2_CTRL_TYPE_MENU,232.name = "Light frequency filter",233.minimum = V4L2_CID_POWER_LINE_FREQUENCY_DISABLED, /* 1 */234.maximum = V4L2_CID_POWER_LINE_FREQUENCY_60HZ, /* 2 */235.step = 1,236.default_value = V4L2_CID_POWER_LINE_FREQUENCY_60HZ,237},238.set_control = setfreq239},240[AUTOGAIN] = {241{242.id = V4L2_CID_AUTOGAIN,243.type = V4L2_CTRL_TYPE_INTEGER,244.name = "Automatic Gain (and Exposure)",245.minimum = 0,246.maximum = 3,247.step = 1,248#define AUTOGAIN_DEF 0249.default_value = AUTOGAIN_DEF,250},251.set_control = setautogain252},253[RED] = {254{255.id = V4L2_CID_RED_BALANCE,256.type = V4L2_CTRL_TYPE_INTEGER,257.name = "red balance",258.minimum = 0,259.maximum = 3,260.step = 1,261#define RED_BALANCE_DEF 2262.default_value = RED_BALANCE_DEF,263},264.set_control = setred265},266267[GREEN] = {268{269.id = V4L2_CID_GAIN,270.type = V4L2_CTRL_TYPE_INTEGER,271.name = "green balance",272.minimum = 0,273.maximum = 3,274.step = 1,275#define GREEN_BALANCE_DEF 2276.default_value = GREEN_BALANCE_DEF,277},278.set_control = setgreen279},280[BLUE] = {281{282.id = V4L2_CID_BLUE_BALANCE,283.type = V4L2_CTRL_TYPE_INTEGER,284.name = "blue balance",285.minimum = 0,286.maximum = 3,287.step = 1,288#define BLUE_BALANCE_DEF 2289.default_value = BLUE_BALANCE_DEF,290},291.set_control = setblue292},293};294295static int jlj_start(struct gspca_dev *gspca_dev)296{297int i;298int start_commands_size;299u8 response = 0xff;300struct sd *sd = (struct sd *) gspca_dev;301struct jlj_command start_commands[] = {302{{0x71, 0x81}, 0, 0},303{{0x70, 0x05}, 0, JEILINJ_CMD_DELAY},304{{0x95, 0x70}, 1, 0},305{{0x71, 0x81 - gspca_dev->curr_mode}, 0, 0},306{{0x70, 0x04}, 0, JEILINJ_CMD_DELAY},307{{0x95, 0x70}, 1, 0},308{{0x71, 0x00}, 0, 0}, /* start streaming ??*/309{{0x70, 0x08}, 0, JEILINJ_CMD_DELAY},310{{0x95, 0x70}, 1, 0},311#define SPORTSCAM_DV15_CMD_SIZE 9312{{0x94, 0x02}, 0, 0},313{{0xde, 0x24}, 0, 0},314{{0x94, 0x02}, 0, 0},315{{0xdd, 0xf0}, 0, 0},316{{0x94, 0x02}, 0, 0},317{{0xe3, 0x2c}, 0, 0},318{{0x94, 0x02}, 0, 0},319{{0xe4, 0x00}, 0, 0},320{{0x94, 0x02}, 0, 0},321{{0xe5, 0x00}, 0, 0},322{{0x94, 0x02}, 0, 0},323{{0xe6, 0x2c}, 0, 0},324{{0x94, 0x03}, 0, 0},325{{0xaa, 0x00}, 0, 0}326};327328sd->blocks_left = 0;329/* Under Windows, USB spy shows that only the 9 first start330* commands are used for SPORTSCAM_DV15 webcam331*/332if (sd->type == SPORTSCAM_DV15)333start_commands_size = SPORTSCAM_DV15_CMD_SIZE;334else335start_commands_size = ARRAY_SIZE(start_commands);336337for (i = 0; i < start_commands_size; i++) {338jlj_write2(gspca_dev, start_commands[i].instruction);339if (start_commands[i].delay)340msleep(start_commands[i].delay);341if (start_commands[i].ack_wanted)342jlj_read1(gspca_dev, response);343}344setcamquality(gspca_dev);345msleep(2);346setfreq(gspca_dev);347if (gspca_dev->usb_err < 0)348PDEBUG(D_ERR, "Start streaming command failed");349return gspca_dev->usb_err;350}351352static void sd_pkt_scan(struct gspca_dev *gspca_dev,353u8 *data, int len)354{355struct sd *sd = (struct sd *) gspca_dev;356int packet_type;357u32 header_marker;358359PDEBUG(D_STREAM, "Got %d bytes out of %d for Block 0",360len, JEILINJ_MAX_TRANSFER);361if (len != JEILINJ_MAX_TRANSFER) {362PDEBUG(D_PACK, "bad length");363goto discard;364}365/* check if it's start of frame */366header_marker = ((u32 *)data)[0];367if (header_marker == FRAME_START) {368sd->blocks_left = data[0x0a] - 1;369PDEBUG(D_STREAM, "blocks_left = 0x%x", sd->blocks_left);370/* Start a new frame, and add the JPEG header, first thing */371gspca_frame_add(gspca_dev, FIRST_PACKET,372sd->jpeg_hdr, JPEG_HDR_SZ);373/* Toss line 0 of data block 0, keep the rest. */374gspca_frame_add(gspca_dev, INTER_PACKET,375data + FRAME_HEADER_LEN,376JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN);377} else if (sd->blocks_left > 0) {378PDEBUG(D_STREAM, "%d blocks remaining for frame",379sd->blocks_left);380sd->blocks_left -= 1;381if (sd->blocks_left == 0)382packet_type = LAST_PACKET;383else384packet_type = INTER_PACKET;385gspca_frame_add(gspca_dev, packet_type,386data, JEILINJ_MAX_TRANSFER);387} else388goto discard;389return;390discard:391/* Discard data until a new frame starts. */392gspca_dev->last_packet_type = DISCARD_PACKET;393}394395/* This function is called at probe time just before sd_init */396static int sd_config(struct gspca_dev *gspca_dev,397const struct usb_device_id *id)398{399struct cam *cam = &gspca_dev->cam;400struct sd *dev = (struct sd *) gspca_dev;401402dev->type = id->driver_info;403gspca_dev->cam.ctrls = dev->ctrls;404dev->quality = QUALITY_DEF;405dev->ctrls[LIGHTFREQ].def = V4L2_CID_POWER_LINE_FREQUENCY_60HZ;406dev->ctrls[RED].def = RED_BALANCE_DEF;407dev->ctrls[GREEN].def = GREEN_BALANCE_DEF;408dev->ctrls[BLUE].def = BLUE_BALANCE_DEF;409PDEBUG(D_PROBE,410"JEILINJ camera detected"411" (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);412cam->cam_mode = jlj_mode;413cam->nmodes = ARRAY_SIZE(jlj_mode);414cam->bulk = 1;415cam->bulk_nurbs = 1;416cam->bulk_size = JEILINJ_MAX_TRANSFER;417return 0;418}419420static void sd_stopN(struct gspca_dev *gspca_dev)421{422int i;423u8 *buf;424u8 stop_commands[][2] = {425{0x71, 0x00},426{0x70, 0x09},427{0x71, 0x80},428{0x70, 0x05}429};430431for (;;) {432/* get the image remaining blocks */433usb_bulk_msg(gspca_dev->dev,434gspca_dev->urb[0]->pipe,435gspca_dev->urb[0]->transfer_buffer,436JEILINJ_MAX_TRANSFER, NULL,437JEILINJ_DATA_TIMEOUT);438439/* search for 0xff 0xd9 (EOF for JPEG) */440i = 0;441buf = gspca_dev->urb[0]->transfer_buffer;442while ((i < (JEILINJ_MAX_TRANSFER - 1)) &&443((buf[i] != 0xff) || (buf[i+1] != 0xd9)))444i++;445446if (i != (JEILINJ_MAX_TRANSFER - 1))447/* last remaining block found */448break;449}450451for (i = 0; i < ARRAY_SIZE(stop_commands); i++)452jlj_write2(gspca_dev, stop_commands[i]);453}454455/* this function is called at probe and resume time */456static int sd_init(struct gspca_dev *gspca_dev)457{458return gspca_dev->usb_err;459}460461/* Set up for getting frames. */462static int sd_start(struct gspca_dev *gspca_dev)463{464struct sd *dev = (struct sd *) gspca_dev;465466/* create the JPEG header */467jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width,4680x21); /* JPEG 422 */469jpeg_set_qual(dev->jpeg_hdr, dev->quality);470PDEBUG(D_STREAM, "Start streaming at %dx%d",471gspca_dev->height, gspca_dev->width);472jlj_start(gspca_dev);473return gspca_dev->usb_err;474}475476/* Table of supported USB devices */477static const struct usb_device_id device_table[] = {478{USB_DEVICE(0x0979, 0x0280), .driver_info = SAKAR_57379},479{USB_DEVICE(0x0979, 0x0270), .driver_info = SPORTSCAM_DV15},480{}481};482483MODULE_DEVICE_TABLE(usb, device_table);484485static int sd_querymenu(struct gspca_dev *gspca_dev,486struct v4l2_querymenu *menu)487{488switch (menu->id) {489case V4L2_CID_POWER_LINE_FREQUENCY:490switch (menu->index) {491case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */492strcpy((char *) menu->name, "disable");493return 0;494case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */495strcpy((char *) menu->name, "50 Hz");496return 0;497case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */498strcpy((char *) menu->name, "60 Hz");499return 0;500}501break;502}503return -EINVAL;504}505506static int sd_set_jcomp(struct gspca_dev *gspca_dev,507struct v4l2_jpegcompression *jcomp)508{509struct sd *sd = (struct sd *) gspca_dev;510511if (jcomp->quality < QUALITY_MIN)512sd->quality = QUALITY_MIN;513else if (jcomp->quality > QUALITY_MAX)514sd->quality = QUALITY_MAX;515else516sd->quality = jcomp->quality;517if (gspca_dev->streaming) {518jpeg_set_qual(sd->jpeg_hdr, sd->quality);519setcamquality(gspca_dev);520}521return 0;522}523524static int sd_get_jcomp(struct gspca_dev *gspca_dev,525struct v4l2_jpegcompression *jcomp)526{527struct sd *sd = (struct sd *) gspca_dev;528529memset(jcomp, 0, sizeof *jcomp);530jcomp->quality = sd->quality;531jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT532| V4L2_JPEG_MARKER_DQT;533return 0;534}535536537/* sub-driver description */538static const struct sd_desc sd_desc_sakar_57379 = {539.name = MODULE_NAME,540.config = sd_config,541.init = sd_init,542.start = sd_start,543.stopN = sd_stopN,544.pkt_scan = sd_pkt_scan,545};546547/* sub-driver description */548static const struct sd_desc sd_desc_sportscam_dv15 = {549.name = MODULE_NAME,550.config = sd_config,551.init = sd_init,552.start = sd_start,553.stopN = sd_stopN,554.pkt_scan = sd_pkt_scan,555.ctrls = sd_ctrls,556.nctrls = ARRAY_SIZE(sd_ctrls),557.querymenu = sd_querymenu,558.get_jcomp = sd_get_jcomp,559.set_jcomp = sd_set_jcomp,560};561562static const struct sd_desc *sd_desc[2] = {563&sd_desc_sakar_57379,564&sd_desc_sportscam_dv15565};566567/* -- device connect -- */568static int sd_probe(struct usb_interface *intf,569const struct usb_device_id *id)570{571return gspca_dev_probe(intf, id,572sd_desc[id->driver_info],573sizeof(struct sd),574THIS_MODULE);575}576577static struct usb_driver sd_driver = {578.name = MODULE_NAME,579.id_table = device_table,580.probe = sd_probe,581.disconnect = gspca_disconnect,582#ifdef CONFIG_PM583.suspend = gspca_suspend,584.resume = gspca_resume,585#endif586};587588/* -- module insert / remove -- */589static int __init sd_mod_init(void)590{591return usb_register(&sd_driver);592}593594static void __exit sd_mod_exit(void)595{596usb_deregister(&sd_driver);597}598599module_init(sd_mod_init);600module_exit(sd_mod_exit);601602603