linux/drivers/media/usb/gspca/stk014.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Syntek DV4000 (STK014) subdriver
   4 *
   5 * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr)
   6 */
   7
   8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   9
  10#define MODULE_NAME "stk014"
  11
  12#include "gspca.h"
  13#include "jpeg.h"
  14
  15MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
  16MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
  17MODULE_LICENSE("GPL");
  18
  19#define QUALITY 50
  20
  21/* specific webcam descriptor */
  22struct sd {
  23        struct gspca_dev gspca_dev;     /* !! must be the first item */
  24        u8 jpeg_hdr[JPEG_HDR_SZ];
  25};
  26
  27static const struct v4l2_pix_format vga_mode[] = {
  28        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  29                .bytesperline = 320,
  30                .sizeimage = 320 * 240 * 3 / 8 + 590,
  31                .colorspace = V4L2_COLORSPACE_JPEG,
  32                .priv = 1},
  33        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  34                .bytesperline = 640,
  35                .sizeimage = 640 * 480 * 3 / 8 + 590,
  36                .colorspace = V4L2_COLORSPACE_JPEG,
  37                .priv = 0},
  38};
  39
  40/* -- read a register -- */
  41static u8 reg_r(struct gspca_dev *gspca_dev,
  42                        __u16 index)
  43{
  44        struct usb_device *dev = gspca_dev->dev;
  45        int ret;
  46
  47        if (gspca_dev->usb_err < 0)
  48                return 0;
  49        ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
  50                        0x00,
  51                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  52                        0x00,
  53                        index,
  54                        gspca_dev->usb_buf, 1,
  55                        500);
  56        if (ret < 0) {
  57                pr_err("reg_r err %d\n", ret);
  58                gspca_dev->usb_err = ret;
  59                return 0;
  60        }
  61        return gspca_dev->usb_buf[0];
  62}
  63
  64/* -- write a register -- */
  65static void reg_w(struct gspca_dev *gspca_dev,
  66                        __u16 index, __u16 value)
  67{
  68        struct usb_device *dev = gspca_dev->dev;
  69        int ret;
  70
  71        if (gspca_dev->usb_err < 0)
  72                return;
  73        ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
  74                        0x01,
  75                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  76                        value,
  77                        index,
  78                        NULL,
  79                        0,
  80                        500);
  81        if (ret < 0) {
  82                pr_err("reg_w err %d\n", ret);
  83                gspca_dev->usb_err = ret;
  84        }
  85}
  86
  87/* -- get a bulk value (4 bytes) -- */
  88static void rcv_val(struct gspca_dev *gspca_dev,
  89                        int ads)
  90{
  91        struct usb_device *dev = gspca_dev->dev;
  92        int alen, ret;
  93
  94        reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff);
  95        reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff);
  96        reg_w(gspca_dev, 0x636, ads & 0xff);
  97        reg_w(gspca_dev, 0x637, 0);
  98        reg_w(gspca_dev, 0x638, 4);     /* len & 0xff */
  99        reg_w(gspca_dev, 0x639, 0);     /* len >> 8 */
 100        reg_w(gspca_dev, 0x63a, 0);
 101        reg_w(gspca_dev, 0x63b, 0);
 102        reg_w(gspca_dev, 0x630, 5);
 103        if (gspca_dev->usb_err < 0)
 104                return;
 105        ret = usb_bulk_msg(dev,
 106                        usb_rcvbulkpipe(dev, 0x05),
 107                        gspca_dev->usb_buf,
 108                        4,              /* length */
 109                        &alen,
 110                        500);           /* timeout in milliseconds */
 111        if (ret < 0) {
 112                pr_err("rcv_val err %d\n", ret);
 113                gspca_dev->usb_err = ret;
 114        }
 115}
 116
 117/* -- send a bulk value -- */
 118static void snd_val(struct gspca_dev *gspca_dev,
 119                        int ads,
 120                        unsigned int val)
 121{
 122        struct usb_device *dev = gspca_dev->dev;
 123        int alen, ret;
 124        __u8 seq = 0;
 125
 126        if (ads == 0x003f08) {
 127                reg_r(gspca_dev, 0x0704);
 128                seq = reg_r(gspca_dev, 0x0705);
 129                reg_r(gspca_dev, 0x0650);
 130                reg_w(gspca_dev, 0x654, seq);
 131        } else {
 132                reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
 133        }
 134        reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff);
 135        reg_w(gspca_dev, 0x656, ads & 0xff);
 136        reg_w(gspca_dev, 0x657, 0);
 137        reg_w(gspca_dev, 0x658, 0x04);  /* size */
 138        reg_w(gspca_dev, 0x659, 0);
 139        reg_w(gspca_dev, 0x65a, 0);
 140        reg_w(gspca_dev, 0x65b, 0);
 141        reg_w(gspca_dev, 0x650, 5);
 142        if (gspca_dev->usb_err < 0)
 143                return;
 144        gspca_dev->usb_buf[0] = val >> 24;
 145        gspca_dev->usb_buf[1] = val >> 16;
 146        gspca_dev->usb_buf[2] = val >> 8;
 147        gspca_dev->usb_buf[3] = val;
 148        ret = usb_bulk_msg(dev,
 149                        usb_sndbulkpipe(dev, 6),
 150                        gspca_dev->usb_buf,
 151                        4,
 152                        &alen,
 153                        500);   /* timeout in milliseconds */
 154        if (ret < 0) {
 155                pr_err("snd_val err %d\n", ret);
 156                gspca_dev->usb_err = ret;
 157        } else {
 158                if (ads == 0x003f08) {
 159                        seq += 4;
 160                        seq &= 0x3f;
 161                        reg_w(gspca_dev, 0x705, seq);
 162                }
 163        }
 164}
 165
 166/* set a camera parameter */
 167static void set_par(struct gspca_dev *gspca_dev,
 168                   int parval)
 169{
 170        snd_val(gspca_dev, 0x003f08, parval);
 171}
 172
 173static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
 174{
 175        int parval;
 176
 177        parval = 0x06000000             /* whiteness */
 178                + (val << 16);
 179        set_par(gspca_dev, parval);
 180}
 181
 182static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
 183{
 184        int parval;
 185
 186        parval = 0x07000000             /* contrast */
 187                + (val << 16);
 188        set_par(gspca_dev, parval);
 189}
 190
 191static void setcolors(struct gspca_dev *gspca_dev, s32 val)
 192{
 193        int parval;
 194
 195        parval = 0x08000000             /* saturation */
 196                + (val << 16);
 197        set_par(gspca_dev, parval);
 198}
 199
 200static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
 201{
 202        set_par(gspca_dev, val == 1
 203                        ? 0x33640000            /* 50 Hz */
 204                        : 0x33780000);          /* 60 Hz */
 205}
 206
 207/* this function is called at probe time */
 208static int sd_config(struct gspca_dev *gspca_dev,
 209                        const struct usb_device_id *id)
 210{
 211        gspca_dev->cam.cam_mode = vga_mode;
 212        gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
 213        return 0;
 214}
 215
 216/* this function is called at probe and resume time */
 217static int sd_init(struct gspca_dev *gspca_dev)
 218{
 219        u8 ret;
 220
 221        /* check if the device responds */
 222        usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
 223        ret = reg_r(gspca_dev, 0x0740);
 224        if (gspca_dev->usb_err >= 0) {
 225                if (ret != 0xff) {
 226                        pr_err("init reg: 0x%02x\n", ret);
 227                        gspca_dev->usb_err = -EIO;
 228                }
 229        }
 230        return gspca_dev->usb_err;
 231}
 232
 233/* -- start the camera -- */
 234static int sd_start(struct gspca_dev *gspca_dev)
 235{
 236        struct sd *sd = (struct sd *) gspca_dev;
 237        int ret, value;
 238
 239        /* create the JPEG header */
 240        jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
 241                        gspca_dev->pixfmt.width,
 242                        0x22);          /* JPEG 411 */
 243        jpeg_set_qual(sd->jpeg_hdr, QUALITY);
 244
 245        /* work on alternate 1 */
 246        usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
 247
 248        set_par(gspca_dev, 0x10000000);
 249        set_par(gspca_dev, 0x00000000);
 250        set_par(gspca_dev, 0x8002e001);
 251        set_par(gspca_dev, 0x14000000);
 252        if (gspca_dev->pixfmt.width > 320)
 253                value = 0x8002e001;             /* 640x480 */
 254        else
 255                value = 0x4001f000;             /* 320x240 */
 256        set_par(gspca_dev, value);
 257        ret = usb_set_interface(gspca_dev->dev,
 258                                        gspca_dev->iface,
 259                                        gspca_dev->alt);
 260        if (ret < 0) {
 261                pr_err("set intf %d %d failed\n",
 262                       gspca_dev->iface, gspca_dev->alt);
 263                gspca_dev->usb_err = ret;
 264                goto out;
 265        }
 266        reg_r(gspca_dev, 0x0630);
 267        rcv_val(gspca_dev, 0x000020);   /* << (value ff ff ff ff) */
 268        reg_r(gspca_dev, 0x0650);
 269        snd_val(gspca_dev, 0x000020, 0xffffffff);
 270        reg_w(gspca_dev, 0x0620, 0);
 271        reg_w(gspca_dev, 0x0630, 0);
 272        reg_w(gspca_dev, 0x0640, 0);
 273        reg_w(gspca_dev, 0x0650, 0);
 274        reg_w(gspca_dev, 0x0660, 0);
 275        set_par(gspca_dev, 0x09800000);         /* Red ? */
 276        set_par(gspca_dev, 0x0a800000);         /* Green ? */
 277        set_par(gspca_dev, 0x0b800000);         /* Blue ? */
 278        set_par(gspca_dev, 0x0d030000);         /* Gamma ? */
 279
 280        /* start the video flow */
 281        set_par(gspca_dev, 0x01000000);
 282        set_par(gspca_dev, 0x01000000);
 283        if (gspca_dev->usb_err >= 0)
 284                gspca_dbg(gspca_dev, D_STREAM, "camera started alt: 0x%02x\n",
 285                          gspca_dev->alt);
 286out:
 287        return gspca_dev->usb_err;
 288}
 289
 290static void sd_stopN(struct gspca_dev *gspca_dev)
 291{
 292        struct usb_device *dev = gspca_dev->dev;
 293
 294        set_par(gspca_dev, 0x02000000);
 295        set_par(gspca_dev, 0x02000000);
 296        usb_set_interface(dev, gspca_dev->iface, 1);
 297        reg_r(gspca_dev, 0x0630);
 298        rcv_val(gspca_dev, 0x000020);   /* << (value ff ff ff ff) */
 299        reg_r(gspca_dev, 0x0650);
 300        snd_val(gspca_dev, 0x000020, 0xffffffff);
 301        reg_w(gspca_dev, 0x0620, 0);
 302        reg_w(gspca_dev, 0x0630, 0);
 303        reg_w(gspca_dev, 0x0640, 0);
 304        reg_w(gspca_dev, 0x0650, 0);
 305        reg_w(gspca_dev, 0x0660, 0);
 306        gspca_dbg(gspca_dev, D_STREAM, "camera stopped\n");
 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 unsigned char ffd9[] = {0xff, 0xd9};
 315
 316        /* a frame starts with:
 317         *      - 0xff 0xfe
 318         *      - 0x08 0x00     - length (little endian ?!)
 319         *      - 4 bytes = size of whole frame (BE - including header)
 320         *      - 0x00 0x0c
 321         *      - 0xff 0xd8
 322         *      - ..    JPEG image with escape sequences (ff 00)
 323         *              (without ending - ff d9)
 324         */
 325        if (data[0] == 0xff && data[1] == 0xfe) {
 326                gspca_frame_add(gspca_dev, LAST_PACKET,
 327                                ffd9, 2);
 328
 329                /* put the JPEG 411 header */
 330                gspca_frame_add(gspca_dev, FIRST_PACKET,
 331                        sd->jpeg_hdr, JPEG_HDR_SZ);
 332
 333                /* beginning of the frame */
 334#define STKHDRSZ 12
 335                data += STKHDRSZ;
 336                len -= STKHDRSZ;
 337        }
 338        gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 339}
 340
 341static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
 342{
 343        struct gspca_dev *gspca_dev =
 344                container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 345
 346        gspca_dev->usb_err = 0;
 347
 348        if (!gspca_dev->streaming)
 349                return 0;
 350
 351        switch (ctrl->id) {
 352        case V4L2_CID_BRIGHTNESS:
 353                setbrightness(gspca_dev, ctrl->val);
 354                break;
 355        case V4L2_CID_CONTRAST:
 356                setcontrast(gspca_dev, ctrl->val);
 357                break;
 358        case V4L2_CID_SATURATION:
 359                setcolors(gspca_dev, ctrl->val);
 360                break;
 361        case V4L2_CID_POWER_LINE_FREQUENCY:
 362                setlightfreq(gspca_dev, ctrl->val);
 363                break;
 364        }
 365        return gspca_dev->usb_err;
 366}
 367
 368static const struct v4l2_ctrl_ops sd_ctrl_ops = {
 369        .s_ctrl = sd_s_ctrl,
 370};
 371
 372static int sd_init_controls(struct gspca_dev *gspca_dev)
 373{
 374        struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
 375
 376        gspca_dev->vdev.ctrl_handler = hdl;
 377        v4l2_ctrl_handler_init(hdl, 4);
 378        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 379                        V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
 380        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 381                        V4L2_CID_CONTRAST, 0, 255, 1, 127);
 382        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 383                        V4L2_CID_SATURATION, 0, 255, 1, 127);
 384        v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
 385                        V4L2_CID_POWER_LINE_FREQUENCY,
 386                        V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
 387                        V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
 388
 389        if (hdl->error) {
 390                pr_err("Could not initialize controls\n");
 391                return hdl->error;
 392        }
 393        return 0;
 394}
 395
 396/* sub-driver description */
 397static const struct sd_desc sd_desc = {
 398        .name = MODULE_NAME,
 399        .config = sd_config,
 400        .init = sd_init,
 401        .init_controls = sd_init_controls,
 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(0x05e1, 0x0893)},
 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        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
 419                                THIS_MODULE);
 420}
 421
 422static struct usb_driver sd_driver = {
 423        .name = MODULE_NAME,
 424        .id_table = device_table,
 425        .probe = sd_probe,
 426        .disconnect = gspca_disconnect,
 427#ifdef CONFIG_PM
 428        .suspend = gspca_suspend,
 429        .resume = gspca_resume,
 430        .reset_resume = gspca_resume,
 431#endif
 432};
 433
 434module_usb_driver(sd_driver);
 435