linux/drivers/media/usb/gspca/spca1528.c
<<
>>
Prefs
   1/*
   2 * spca1528 subdriver
   3 *
   4 * Copyright (C) 2010-2011 Jean-Francois Moine (http://moinejf.free.fr)
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 */
  20
  21#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  22
  23#define MODULE_NAME "spca1528"
  24
  25#include "gspca.h"
  26#include "jpeg.h"
  27
  28MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
  29MODULE_DESCRIPTION("SPCA1528 USB Camera Driver");
  30MODULE_LICENSE("GPL");
  31
  32/* specific webcam descriptor */
  33struct sd {
  34        struct gspca_dev gspca_dev;     /* !! must be the first item */
  35
  36        u8 pkt_seq;
  37
  38        u8 jpeg_hdr[JPEG_HDR_SZ];
  39};
  40
  41static const struct v4l2_pix_format vga_mode[] = {
  42/*              (does not work correctly)
  43        {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  44                .bytesperline = 176,
  45                .sizeimage = 176 * 144 * 5 / 8 + 590,
  46                .colorspace = V4L2_COLORSPACE_JPEG,
  47                .priv = 3},
  48*/
  49        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  50                .bytesperline = 320,
  51                .sizeimage = 320 * 240 * 4 / 8 + 590,
  52                .colorspace = V4L2_COLORSPACE_JPEG,
  53                .priv = 2},
  54        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  55                .bytesperline = 640,
  56                .sizeimage = 640 * 480 * 3 / 8 + 590,
  57                .colorspace = V4L2_COLORSPACE_JPEG,
  58                .priv = 1},
  59};
  60
  61/* read <len> bytes to gspca usb_buf */
  62static void reg_r(struct gspca_dev *gspca_dev,
  63                        u8 req,
  64                        u16 index,
  65                        int len)
  66{
  67#if USB_BUF_SZ < 64
  68#error "USB buffer too small"
  69#endif
  70        struct usb_device *dev = gspca_dev->dev;
  71        int ret;
  72
  73        if (gspca_dev->usb_err < 0)
  74                return;
  75        ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
  76                        req,
  77                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  78                        0x0000,                 /* value */
  79                        index,
  80                        gspca_dev->usb_buf, len,
  81                        500);
  82        PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", req, index,
  83                         gspca_dev->usb_buf[0]);
  84        if (ret < 0) {
  85                pr_err("reg_r err %d\n", ret);
  86                gspca_dev->usb_err = ret;
  87        }
  88}
  89
  90static void reg_w(struct gspca_dev *gspca_dev,
  91                        u8 req,
  92                        u16 value,
  93                        u16 index)
  94{
  95        struct usb_device *dev = gspca_dev->dev;
  96        int ret;
  97
  98        if (gspca_dev->usb_err < 0)
  99                return;
 100        PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
 101        ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 102                        req,
 103                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 104                        value, index,
 105                        NULL, 0, 500);
 106        if (ret < 0) {
 107                pr_err("reg_w err %d\n", ret);
 108                gspca_dev->usb_err = ret;
 109        }
 110}
 111
 112static void reg_wb(struct gspca_dev *gspca_dev,
 113                        u8 req,
 114                        u16 value,
 115                        u16 index,
 116                        u8 byte)
 117{
 118        struct usb_device *dev = gspca_dev->dev;
 119        int ret;
 120
 121        if (gspca_dev->usb_err < 0)
 122                return;
 123        PDEBUG(D_USBO, "SET %02x %04x %04x %02x", req, value, index, byte);
 124        gspca_dev->usb_buf[0] = byte;
 125        ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 126                        req,
 127                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 128                        value, index,
 129                        gspca_dev->usb_buf, 1, 500);
 130        if (ret < 0) {
 131                pr_err("reg_w err %d\n", ret);
 132                gspca_dev->usb_err = ret;
 133        }
 134}
 135
 136static void wait_status_0(struct gspca_dev *gspca_dev)
 137{
 138        int i, w;
 139
 140        i = 16;
 141        w = 0;
 142        do {
 143                reg_r(gspca_dev, 0x21, 0x0000, 1);
 144                if (gspca_dev->usb_buf[0] == 0)
 145                        return;
 146                w += 15;
 147                msleep(w);
 148        } while (--i > 0);
 149        PERR("wait_status_0 timeout");
 150        gspca_dev->usb_err = -ETIME;
 151}
 152
 153static void wait_status_1(struct gspca_dev *gspca_dev)
 154{
 155        int i;
 156
 157        i = 10;
 158        do {
 159                reg_r(gspca_dev, 0x21, 0x0001, 1);
 160                msleep(10);
 161                if (gspca_dev->usb_buf[0] == 1) {
 162                        reg_wb(gspca_dev, 0x21, 0x0000, 0x0001, 0x00);
 163                        reg_r(gspca_dev, 0x21, 0x0001, 1);
 164                        return;
 165                }
 166        } while (--i > 0);
 167        PERR("wait_status_1 timeout");
 168        gspca_dev->usb_err = -ETIME;
 169}
 170
 171static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
 172{
 173        reg_wb(gspca_dev, 0xc0, 0x0000, 0x00c0, val);
 174}
 175
 176static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
 177{
 178        reg_wb(gspca_dev, 0xc1, 0x0000, 0x00c1, val);
 179}
 180
 181static void sethue(struct gspca_dev *gspca_dev, s32 val)
 182{
 183        reg_wb(gspca_dev, 0xc2, 0x0000, 0x0000, val);
 184}
 185
 186static void setcolor(struct gspca_dev *gspca_dev, s32 val)
 187{
 188        reg_wb(gspca_dev, 0xc3, 0x0000, 0x00c3, val);
 189}
 190
 191static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
 192{
 193        reg_wb(gspca_dev, 0xc4, 0x0000, 0x00c4, val);
 194}
 195
 196/* this function is called at probe time */
 197static int sd_config(struct gspca_dev *gspca_dev,
 198                        const struct usb_device_id *id)
 199{
 200        gspca_dev->cam.cam_mode = vga_mode;
 201        gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
 202        gspca_dev->cam.npkt = 128; /* number of packets per ISOC message */
 203                        /*fixme: 256 in ms-win traces*/
 204
 205        return 0;
 206}
 207
 208/* this function is called at probe and resume time */
 209static int sd_init(struct gspca_dev *gspca_dev)
 210{
 211        reg_w(gspca_dev, 0x00, 0x0001, 0x2067);
 212        reg_w(gspca_dev, 0x00, 0x00d0, 0x206b);
 213        reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
 214        reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
 215        msleep(8);
 216        reg_w(gspca_dev, 0x00, 0x00c0, 0x206b);
 217        reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
 218        reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
 219
 220        reg_r(gspca_dev, 0x20, 0x0000, 1);
 221        reg_r(gspca_dev, 0x20, 0x0000, 5);
 222        reg_r(gspca_dev, 0x23, 0x0000, 64);
 223        PDEBUG(D_PROBE, "%s%s", &gspca_dev->usb_buf[0x1c],
 224                                &gspca_dev->usb_buf[0x30]);
 225        reg_r(gspca_dev, 0x23, 0x0001, 64);
 226        return gspca_dev->usb_err;
 227}
 228
 229/* function called at start time before URB creation */
 230static int sd_isoc_init(struct gspca_dev *gspca_dev)
 231{
 232        u8 mode;
 233
 234        reg_r(gspca_dev, 0x00, 0x2520, 1);
 235        wait_status_0(gspca_dev);
 236        reg_w(gspca_dev, 0xc5, 0x0003, 0x0000);
 237        wait_status_1(gspca_dev);
 238
 239        wait_status_0(gspca_dev);
 240        mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
 241        reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode);
 242        reg_r(gspca_dev, 0x25, 0x0004, 1);
 243        reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06);  /* 420 */
 244        reg_r(gspca_dev, 0x27, 0x0000, 1);
 245
 246/* not useful..
 247        gspca_dev->alt = 4;             * use alternate setting 3 */
 248
 249        return gspca_dev->usb_err;
 250}
 251
 252/* -- start the camera -- */
 253static int sd_start(struct gspca_dev *gspca_dev)
 254{
 255        struct sd *sd = (struct sd *) gspca_dev;
 256
 257        /* initialize the JPEG header */
 258        jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
 259                        gspca_dev->pixfmt.width,
 260                        0x22);          /* JPEG 411 */
 261
 262        /* the JPEG quality shall be 85% */
 263        jpeg_set_qual(sd->jpeg_hdr, 85);
 264
 265        reg_r(gspca_dev, 0x00, 0x2520, 1);
 266        msleep(8);
 267
 268        /* start the capture */
 269        wait_status_0(gspca_dev);
 270        reg_w(gspca_dev, 0x31, 0x0000, 0x0004); /* start request */
 271        wait_status_1(gspca_dev);
 272        wait_status_0(gspca_dev);
 273        msleep(200);
 274
 275        sd->pkt_seq = 0;
 276        return gspca_dev->usb_err;
 277}
 278
 279static void sd_stopN(struct gspca_dev *gspca_dev)
 280{
 281        /* stop the capture */
 282        wait_status_0(gspca_dev);
 283        reg_w(gspca_dev, 0x31, 0x0000, 0x0000); /* stop request */
 284        wait_status_1(gspca_dev);
 285        wait_status_0(gspca_dev);
 286}
 287
 288/* move a packet adding 0x00 after 0xff */
 289static void add_packet(struct gspca_dev *gspca_dev,
 290                        u8 *data,
 291                        int len)
 292{
 293        int i;
 294
 295        i = 0;
 296        do {
 297                if (data[i] == 0xff) {
 298                        gspca_frame_add(gspca_dev, INTER_PACKET,
 299                                        data, i + 1);
 300                        len -= i;
 301                        data += i;
 302                        *data = 0x00;
 303                        i = 0;
 304                }
 305        } while (++i < len);
 306        gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 307}
 308
 309static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 310                        u8 *data,                       /* isoc packet */
 311                        int len)                        /* iso packet length */
 312{
 313        struct sd *sd = (struct sd *) gspca_dev;
 314        static const u8 ffd9[] = {0xff, 0xd9};
 315
 316        /* image packets start with:
 317         *      02 8n
 318         * with <n> bit:
 319         *      0x01: even (0) / odd (1) image
 320         *      0x02: end of image when set
 321         */
 322        if (len < 3)
 323                return;                         /* empty packet */
 324        if (*data == 0x02) {
 325                if (data[1] & 0x02) {
 326                        sd->pkt_seq = !(data[1] & 1);
 327                        add_packet(gspca_dev, data + 2, len - 2);
 328                        gspca_frame_add(gspca_dev, LAST_PACKET,
 329                                        ffd9, 2);
 330                        return;
 331                }
 332                if ((data[1] & 1) != sd->pkt_seq)
 333                        goto err;
 334                if (gspca_dev->last_packet_type == LAST_PACKET)
 335                        gspca_frame_add(gspca_dev, FIRST_PACKET,
 336                                        sd->jpeg_hdr, JPEG_HDR_SZ);
 337                add_packet(gspca_dev, data + 2, len - 2);
 338                return;
 339        }
 340err:
 341        gspca_dev->last_packet_type = DISCARD_PACKET;
 342}
 343
 344static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
 345{
 346        struct gspca_dev *gspca_dev =
 347                container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 348
 349        gspca_dev->usb_err = 0;
 350
 351        if (!gspca_dev->streaming)
 352                return 0;
 353
 354        switch (ctrl->id) {
 355        case V4L2_CID_BRIGHTNESS:
 356                setbrightness(gspca_dev, ctrl->val);
 357                break;
 358        case V4L2_CID_CONTRAST:
 359                setcontrast(gspca_dev, ctrl->val);
 360                break;
 361        case V4L2_CID_HUE:
 362                sethue(gspca_dev, ctrl->val);
 363                break;
 364        case V4L2_CID_SATURATION:
 365                setcolor(gspca_dev, ctrl->val);
 366                break;
 367        case V4L2_CID_SHARPNESS:
 368                setsharpness(gspca_dev, ctrl->val);
 369                break;
 370        }
 371        return gspca_dev->usb_err;
 372}
 373
 374static const struct v4l2_ctrl_ops sd_ctrl_ops = {
 375        .s_ctrl = sd_s_ctrl,
 376};
 377
 378static int sd_init_controls(struct gspca_dev *gspca_dev)
 379{
 380        struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
 381
 382        gspca_dev->vdev.ctrl_handler = hdl;
 383        v4l2_ctrl_handler_init(hdl, 5);
 384        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 385                        V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
 386        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 387                        V4L2_CID_CONTRAST, 0, 8, 1, 1);
 388        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 389                        V4L2_CID_HUE, 0, 255, 1, 0);
 390        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 391                        V4L2_CID_SATURATION, 0, 8, 1, 1);
 392        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 393                        V4L2_CID_SHARPNESS, 0, 255, 1, 0);
 394
 395        if (hdl->error) {
 396                pr_err("Could not initialize controls\n");
 397                return hdl->error;
 398        }
 399        return 0;
 400}
 401
 402/* sub-driver description */
 403static const struct sd_desc sd_desc = {
 404        .name = MODULE_NAME,
 405        .config = sd_config,
 406        .init = sd_init,
 407        .init_controls = sd_init_controls,
 408        .isoc_init = sd_isoc_init,
 409        .start = sd_start,
 410        .stopN = sd_stopN,
 411        .pkt_scan = sd_pkt_scan,
 412};
 413
 414/* -- module initialisation -- */
 415static const struct usb_device_id device_table[] = {
 416        {USB_DEVICE(0x04fc, 0x1528)},
 417        {}
 418};
 419MODULE_DEVICE_TABLE(usb, device_table);
 420
 421/* -- device connect -- */
 422static int sd_probe(struct usb_interface *intf,
 423                        const struct usb_device_id *id)
 424{
 425        /* the video interface for isochronous transfer is 1 */
 426        if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
 427                return -ENODEV;
 428
 429        return gspca_dev_probe2(intf, id, &sd_desc, sizeof(struct sd),
 430                                THIS_MODULE);
 431}
 432
 433static struct usb_driver sd_driver = {
 434        .name = MODULE_NAME,
 435        .id_table = device_table,
 436        .probe = sd_probe,
 437        .disconnect = gspca_disconnect,
 438#ifdef CONFIG_PM
 439        .suspend = gspca_suspend,
 440        .resume = gspca_resume,
 441        .reset_resume = gspca_resume,
 442#endif
 443};
 444
 445module_usb_driver(sd_driver);
 446