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