linux/drivers/media/video/gspca/spca1528.c
<<
>>
Prefs
   1/*
   2 * spca1528 subdriver
   3 *
   4 * Copyright (C) 2010 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 MODULE_NAME "spca1528"
  22
  23#include "gspca.h"
  24#include "jpeg.h"
  25
  26MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
  27MODULE_DESCRIPTION("SPCA1528 USB Camera Driver");
  28MODULE_LICENSE("GPL");
  29
  30/* specific webcam descriptor */
  31struct sd {
  32        struct gspca_dev gspca_dev;     /* !! must be the first item */
  33
  34        u8 brightness;
  35        u8 contrast;
  36        u8 hue;
  37        u8 color;
  38        u8 sharpness;
  39
  40        u8 pkt_seq;
  41
  42        u8 jpeg_hdr[JPEG_HDR_SZ];
  43};
  44
  45/* V4L2 controls supported by the driver */
  46static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
  47static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
  48static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
  49static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
  50static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
  51static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
  52static int sd_setcolor(struct gspca_dev *gspca_dev, __s32 val);
  53static int sd_getcolor(struct gspca_dev *gspca_dev, __s32 *val);
  54static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
  55static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
  56
  57static const struct ctrl sd_ctrls[] = {
  58        {
  59            {
  60                .id      = V4L2_CID_BRIGHTNESS,
  61                .type    = V4L2_CTRL_TYPE_INTEGER,
  62                .name    = "Brightness",
  63                .minimum = 0,
  64                .maximum = 255,
  65                .step    = 1,
  66#define BRIGHTNESS_DEF 128
  67                .default_value = BRIGHTNESS_DEF,
  68            },
  69            .set = sd_setbrightness,
  70            .get = sd_getbrightness,
  71        },
  72        {
  73            {
  74                .id      = V4L2_CID_CONTRAST,
  75                .type    = V4L2_CTRL_TYPE_INTEGER,
  76                .name    = "Contrast",
  77                .minimum = 0,
  78                .maximum = 8,
  79                .step    = 1,
  80#define CONTRAST_DEF 1
  81                .default_value = CONTRAST_DEF,
  82            },
  83            .set = sd_setcontrast,
  84            .get = sd_getcontrast,
  85        },
  86        {
  87            {
  88                .id      = V4L2_CID_HUE,
  89                .type    = V4L2_CTRL_TYPE_INTEGER,
  90                .name    = "Hue",
  91                .minimum = 0,
  92                .maximum = 255,
  93                .step    = 1,
  94#define HUE_DEF 0
  95                .default_value = HUE_DEF,
  96            },
  97            .set = sd_sethue,
  98            .get = sd_gethue,
  99        },
 100        {
 101            {
 102                .id      = V4L2_CID_SATURATION,
 103                .type    = V4L2_CTRL_TYPE_INTEGER,
 104                .name    = "Saturation",
 105                .minimum = 0,
 106                .maximum = 8,
 107                .step    = 1,
 108#define COLOR_DEF 1
 109                .default_value = COLOR_DEF,
 110            },
 111            .set = sd_setcolor,
 112            .get = sd_getcolor,
 113        },
 114        {
 115            {
 116                .id      = V4L2_CID_SHARPNESS,
 117                .type    = V4L2_CTRL_TYPE_INTEGER,
 118                .name    = "Sharpness",
 119                .minimum = 0,
 120                .maximum = 255,
 121                .step    = 1,
 122#define SHARPNESS_DEF 0
 123                .default_value = SHARPNESS_DEF,
 124            },
 125            .set = sd_setsharpness,
 126            .get = sd_getsharpness,
 127        },
 128};
 129
 130static const struct v4l2_pix_format vga_mode[] = {
 131/*              (does not work correctly)
 132        {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 133                .bytesperline = 176,
 134                .sizeimage = 176 * 144 * 5 / 8 + 590,
 135                .colorspace = V4L2_COLORSPACE_JPEG,
 136                .priv = 3},
 137*/
 138        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 139                .bytesperline = 320,
 140                .sizeimage = 320 * 240 * 4 / 8 + 590,
 141                .colorspace = V4L2_COLORSPACE_JPEG,
 142                .priv = 2},
 143        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 144                .bytesperline = 640,
 145                .sizeimage = 640 * 480 * 3 / 8 + 590,
 146                .colorspace = V4L2_COLORSPACE_JPEG,
 147                .priv = 1},
 148};
 149
 150/* read <len> bytes to gspca usb_buf */
 151static void reg_r(struct gspca_dev *gspca_dev,
 152                        u8 req,
 153                        u16 index,
 154                        int len)
 155{
 156#if USB_BUF_SZ < 64
 157#error "USB buffer too small"
 158#endif
 159        struct usb_device *dev = gspca_dev->dev;
 160        int ret;
 161
 162        if (gspca_dev->usb_err < 0)
 163                return;
 164        ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 165                        req,
 166                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 167                        0x0000,                 /* value */
 168                        index,
 169                        gspca_dev->usb_buf, len,
 170                        500);
 171        PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", req, index,
 172                         gspca_dev->usb_buf[0]);
 173        if (ret < 0) {
 174                err("reg_r err %d", ret);
 175                gspca_dev->usb_err = ret;
 176        }
 177}
 178
 179static void reg_w(struct gspca_dev *gspca_dev,
 180                        u8 req,
 181                        u16 value,
 182                        u16 index)
 183{
 184        struct usb_device *dev = gspca_dev->dev;
 185        int ret;
 186
 187        if (gspca_dev->usb_err < 0)
 188                return;
 189        PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
 190        ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 191                        req,
 192                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 193                        value, index,
 194                        NULL, 0, 500);
 195        if (ret < 0) {
 196                err("reg_w err %d", ret);
 197                gspca_dev->usb_err = ret;
 198        }
 199}
 200
 201static void reg_wb(struct gspca_dev *gspca_dev,
 202                        u8 req,
 203                        u16 value,
 204                        u16 index,
 205                        u8 byte)
 206{
 207        struct usb_device *dev = gspca_dev->dev;
 208        int ret;
 209
 210        if (gspca_dev->usb_err < 0)
 211                return;
 212        PDEBUG(D_USBO, "SET %02x %04x %04x %02x", req, value, index, byte);
 213        gspca_dev->usb_buf[0] = byte;
 214        ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 215                        req,
 216                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 217                        value, index,
 218                        gspca_dev->usb_buf, 1, 500);
 219        if (ret < 0) {
 220                err("reg_w err %d", ret);
 221                gspca_dev->usb_err = ret;
 222        }
 223}
 224
 225static void wait_status_0(struct gspca_dev *gspca_dev)
 226{
 227        int i;
 228
 229        i = 20;
 230        do {
 231                reg_r(gspca_dev, 0x21, 0x0000, 1);
 232                if (gspca_dev->usb_buf[0] == 0)
 233                        return;
 234                msleep(30);
 235        } while (--i > 0);
 236        PDEBUG(D_ERR, "wait_status_0 timeout");
 237        gspca_dev->usb_err = -ETIME;
 238}
 239
 240static void wait_status_1(struct gspca_dev *gspca_dev)
 241{
 242        int i;
 243
 244        i = 10;
 245        do {
 246                reg_r(gspca_dev, 0x21, 0x0001, 1);
 247                msleep(10);
 248                if (gspca_dev->usb_buf[0] == 1) {
 249                        reg_wb(gspca_dev, 0x21, 0x0000, 0x0001, 0x00);
 250                        reg_r(gspca_dev, 0x21, 0x0001, 1);
 251                        return;
 252                }
 253        } while (--i > 0);
 254        PDEBUG(D_ERR, "wait_status_1 timeout");
 255        gspca_dev->usb_err = -ETIME;
 256}
 257
 258static void setbrightness(struct gspca_dev *gspca_dev)
 259{
 260        struct sd *sd = (struct sd *) gspca_dev;
 261
 262        reg_wb(gspca_dev, 0xc0, 0x0000, 0x00c0, sd->brightness);
 263}
 264
 265static void setcontrast(struct gspca_dev *gspca_dev)
 266{
 267        struct sd *sd = (struct sd *) gspca_dev;
 268
 269        reg_wb(gspca_dev, 0xc1, 0x0000, 0x00c1, sd->contrast);
 270}
 271
 272static void sethue(struct gspca_dev *gspca_dev)
 273{
 274        struct sd *sd = (struct sd *) gspca_dev;
 275
 276        reg_wb(gspca_dev, 0xc2, 0x0000, 0x0000, sd->hue);
 277}
 278
 279static void setcolor(struct gspca_dev *gspca_dev)
 280{
 281        struct sd *sd = (struct sd *) gspca_dev;
 282
 283        reg_wb(gspca_dev, 0xc3, 0x0000, 0x00c3, sd->color);
 284}
 285
 286static void setsharpness(struct gspca_dev *gspca_dev)
 287{
 288        struct sd *sd = (struct sd *) gspca_dev;
 289
 290        reg_wb(gspca_dev, 0xc4, 0x0000, 0x00c4, sd->sharpness);
 291}
 292
 293/* this function is called at probe time */
 294static int sd_config(struct gspca_dev *gspca_dev,
 295                        const struct usb_device_id *id)
 296{
 297        struct sd *sd = (struct sd *) gspca_dev;
 298
 299        gspca_dev->cam.cam_mode = vga_mode;
 300        gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
 301        gspca_dev->cam.npkt = 128; /* number of packets per ISOC message */
 302                        /*fixme: 256 in ms-win traces*/
 303
 304        sd->brightness = BRIGHTNESS_DEF;
 305        sd->contrast = CONTRAST_DEF;
 306        sd->hue = HUE_DEF;
 307        sd->color = COLOR_DEF;
 308        sd->sharpness = SHARPNESS_DEF;
 309
 310        gspca_dev->nbalt = 4;           /* use alternate setting 3 */
 311
 312        return 0;
 313}
 314
 315/* this function is called at probe and resume time */
 316static int sd_init(struct gspca_dev *gspca_dev)
 317{
 318        reg_w(gspca_dev, 0x00, 0x0001, 0x2067);
 319        reg_w(gspca_dev, 0x00, 0x00d0, 0x206b);
 320        reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
 321        reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
 322        msleep(8);
 323        reg_w(gspca_dev, 0x00, 0x00c0, 0x206b);
 324        reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
 325        reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
 326
 327        reg_r(gspca_dev, 0x20, 0x0000, 1);
 328        reg_r(gspca_dev, 0x20, 0x0000, 5);
 329        reg_r(gspca_dev, 0x23, 0x0000, 64);
 330        PDEBUG(D_PROBE, "%s%s", &gspca_dev->usb_buf[0x1c],
 331                                &gspca_dev->usb_buf[0x30]);
 332        reg_r(gspca_dev, 0x23, 0x0001, 64);
 333        return gspca_dev->usb_err;
 334}
 335
 336/* function called at start time before URB creation */
 337static int sd_isoc_init(struct gspca_dev *gspca_dev)
 338{
 339        u8 mode;
 340
 341        reg_r(gspca_dev, 0x00, 0x2520, 1);
 342        wait_status_0(gspca_dev);
 343        reg_w(gspca_dev, 0xc5, 0x0003, 0x0000);
 344        wait_status_1(gspca_dev);
 345
 346        wait_status_0(gspca_dev);
 347        mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
 348        reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode);
 349        reg_r(gspca_dev, 0x25, 0x0004, 1);
 350        reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06);
 351        reg_r(gspca_dev, 0x27, 0x0000, 1);
 352        return gspca_dev->usb_err;
 353}
 354
 355/* -- start the camera -- */
 356static int sd_start(struct gspca_dev *gspca_dev)
 357{
 358        struct sd *sd = (struct sd *) gspca_dev;
 359
 360        /* initialize the JPEG header */
 361        jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 362                        0x22);          /* JPEG 411 */
 363
 364        /* the JPEG quality seems to be 82% */
 365        jpeg_set_qual(sd->jpeg_hdr, 82);
 366
 367        /* set the controls */
 368        setbrightness(gspca_dev);
 369        setcontrast(gspca_dev);
 370        sethue(gspca_dev);
 371        setcolor(gspca_dev);
 372        setsharpness(gspca_dev);
 373
 374        msleep(5);
 375        reg_r(gspca_dev, 0x00, 0x2520, 1);
 376        msleep(8);
 377
 378        /* start the capture */
 379        wait_status_0(gspca_dev);
 380        reg_w(gspca_dev, 0x31, 0x0000, 0x0004);
 381        wait_status_1(gspca_dev);
 382        wait_status_0(gspca_dev);
 383        msleep(200);
 384
 385        sd->pkt_seq = 0;
 386        return gspca_dev->usb_err;
 387}
 388
 389static void sd_stopN(struct gspca_dev *gspca_dev)
 390{
 391        /* stop the capture */
 392        wait_status_0(gspca_dev);
 393        reg_w(gspca_dev, 0x31, 0x0000, 0x0000);
 394        wait_status_1(gspca_dev);
 395        wait_status_0(gspca_dev);
 396}
 397
 398/* move a packet adding 0x00 after 0xff */
 399static void add_packet(struct gspca_dev *gspca_dev,
 400                        u8 *data,
 401                        int len)
 402{
 403        int i;
 404
 405        i = 0;
 406        do {
 407                if (data[i] == 0xff) {
 408                        gspca_frame_add(gspca_dev, INTER_PACKET,
 409                                        data, i + 1);
 410                        len -= i;
 411                        data += i;
 412                        *data = 0x00;
 413                        i = 0;
 414                }
 415        } while (++i < len);
 416        gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 417}
 418
 419static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 420                        u8 *data,                       /* isoc packet */
 421                        int len)                        /* iso packet length */
 422{
 423        struct sd *sd = (struct sd *) gspca_dev;
 424        static const u8 ffd9[] = {0xff, 0xd9};
 425
 426        /* image packets start with:
 427         *      02 8n
 428         * with <n> bit:
 429         *      0x01: even (0) / odd (1) image
 430         *      0x02: end of image when set
 431         */
 432        if (len < 3)
 433                return;                         /* empty packet */
 434        if (*data == 0x02) {
 435                if (data[1] & 0x02) {
 436                        sd->pkt_seq = !(data[1] & 1);
 437                        add_packet(gspca_dev, data + 2, len - 2);
 438                        gspca_frame_add(gspca_dev, LAST_PACKET,
 439                                        ffd9, 2);
 440                        return;
 441                }
 442                if ((data[1] & 1) != sd->pkt_seq)
 443                        goto err;
 444                if (gspca_dev->last_packet_type == LAST_PACKET)
 445                        gspca_frame_add(gspca_dev, FIRST_PACKET,
 446                                        sd->jpeg_hdr, JPEG_HDR_SZ);
 447                add_packet(gspca_dev, data + 2, len - 2);
 448                return;
 449        }
 450err:
 451        gspca_dev->last_packet_type = DISCARD_PACKET;
 452}
 453
 454static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 455{
 456        struct sd *sd = (struct sd *) gspca_dev;
 457
 458        sd->brightness = val;
 459        if (gspca_dev->streaming)
 460                setbrightness(gspca_dev);
 461        return gspca_dev->usb_err;
 462}
 463
 464static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
 465{
 466        struct sd *sd = (struct sd *) gspca_dev;
 467
 468        *val = sd->brightness;
 469        return 0;
 470}
 471
 472static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
 473{
 474        struct sd *sd = (struct sd *) gspca_dev;
 475
 476        sd->contrast = val;
 477        if (gspca_dev->streaming)
 478                setcontrast(gspca_dev);
 479        return gspca_dev->usb_err;
 480}
 481
 482static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
 483{
 484        struct sd *sd = (struct sd *) gspca_dev;
 485
 486        *val = sd->contrast;
 487        return 0;
 488}
 489
 490static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
 491{
 492        struct sd *sd = (struct sd *) gspca_dev;
 493
 494        sd->hue = val;
 495        if (gspca_dev->streaming)
 496                sethue(gspca_dev);
 497        return gspca_dev->usb_err;
 498}
 499
 500static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
 501{
 502        struct sd *sd = (struct sd *) gspca_dev;
 503
 504        *val = sd->hue;
 505        return 0;
 506}
 507
 508static int sd_setcolor(struct gspca_dev *gspca_dev, __s32 val)
 509{
 510        struct sd *sd = (struct sd *) gspca_dev;
 511
 512        sd->color = val;
 513        if (gspca_dev->streaming)
 514                setcolor(gspca_dev);
 515        return gspca_dev->usb_err;
 516}
 517
 518static int sd_getcolor(struct gspca_dev *gspca_dev, __s32 *val)
 519{
 520        struct sd *sd = (struct sd *) gspca_dev;
 521
 522        *val = sd->color;
 523        return 0;
 524}
 525
 526static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
 527{
 528        struct sd *sd = (struct sd *) gspca_dev;
 529
 530        sd->sharpness = val;
 531        if (gspca_dev->streaming)
 532                setsharpness(gspca_dev);
 533        return gspca_dev->usb_err;
 534}
 535
 536static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
 537{
 538        struct sd *sd = (struct sd *) gspca_dev;
 539
 540        *val = sd->sharpness;
 541        return 0;
 542}
 543
 544/* sub-driver description */
 545static const struct sd_desc sd_desc = {
 546        .name = MODULE_NAME,
 547        .ctrls = sd_ctrls,
 548        .nctrls = ARRAY_SIZE(sd_ctrls),
 549        .config = sd_config,
 550        .init = sd_init,
 551        .isoc_init = sd_isoc_init,
 552        .start = sd_start,
 553        .stopN = sd_stopN,
 554        .pkt_scan = sd_pkt_scan,
 555};
 556
 557/* -- module initialisation -- */
 558static const struct usb_device_id device_table[] = {
 559        {USB_DEVICE(0x04fc, 0x1528)},
 560        {}
 561};
 562MODULE_DEVICE_TABLE(usb, device_table);
 563
 564/* -- device connect -- */
 565static int sd_probe(struct usb_interface *intf,
 566                        const struct usb_device_id *id)
 567{
 568        /* the video interface for isochronous transfer is 1 */
 569        if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
 570                return -ENODEV;
 571
 572        return gspca_dev_probe2(intf, id, &sd_desc, sizeof(struct sd),
 573                                THIS_MODULE);
 574}
 575
 576static struct usb_driver sd_driver = {
 577        .name = MODULE_NAME,
 578        .id_table = device_table,
 579        .probe = sd_probe,
 580        .disconnect = gspca_disconnect,
 581#ifdef CONFIG_PM
 582        .suspend = gspca_suspend,
 583        .resume = gspca_resume,
 584#endif
 585};
 586
 587/* -- module insert / remove -- */
 588static int __init sd_mod_init(void)
 589{
 590        return usb_register(&sd_driver);
 591}
 592static void __exit sd_mod_exit(void)
 593{
 594        usb_deregister(&sd_driver);
 595}
 596
 597module_init(sd_mod_init);
 598module_exit(sd_mod_exit);
 599