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