linux/drivers/media/video/gspca/sn9c2028.c
<<
>>
Prefs
   1/*
   2 * SN9C2028 library
   3 *
   4 * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
   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 "sn9c2028"
  22
  23#include "gspca.h"
  24
  25MODULE_AUTHOR("Theodore Kilgore");
  26MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver");
  27MODULE_LICENSE("GPL");
  28
  29/* specific webcam descriptor */
  30struct sd {
  31        struct gspca_dev gspca_dev;  /* !! must be the first item */
  32        u8 sof_read;
  33        u16 model;
  34};
  35
  36struct init_command {
  37        unsigned char instruction[6];
  38        unsigned char to_read; /* length to read. 0 means no reply requested */
  39};
  40
  41/* V4L2 controls supported by the driver */
  42static const struct ctrl sd_ctrls[] = {
  43};
  44
  45/* How to change the resolution of any of the VGA cams is unknown */
  46static const struct v4l2_pix_format vga_mode[] = {
  47        {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
  48                .bytesperline = 640,
  49                .sizeimage = 640 * 480 * 3 / 4,
  50                .colorspace = V4L2_COLORSPACE_SRGB,
  51                .priv = 0},
  52};
  53
  54/* No way to change the resolution of the CIF cams is known */
  55static const struct v4l2_pix_format cif_mode[] = {
  56        {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
  57                .bytesperline = 352,
  58                .sizeimage = 352 * 288 * 3 / 4,
  59                .colorspace = V4L2_COLORSPACE_SRGB,
  60                .priv = 0},
  61};
  62
  63/* the bytes to write are in gspca_dev->usb_buf */
  64static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command)
  65{
  66        int rc;
  67
  68        PDEBUG(D_USBO, "sending command %02x%02x%02x%02x%02x%02x", command[0],
  69               command[1], command[2], command[3], command[4], command[5]);
  70
  71        memcpy(gspca_dev->usb_buf, command, 6);
  72        rc = usb_control_msg(gspca_dev->dev,
  73                        usb_sndctrlpipe(gspca_dev->dev, 0),
  74                        USB_REQ_GET_CONFIGURATION,
  75                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
  76                        2, 0, gspca_dev->usb_buf, 6, 500);
  77        if (rc < 0) {
  78                err("command write [%02x] error %d",
  79                                gspca_dev->usb_buf[0], rc);
  80                return rc;
  81        }
  82
  83        return 0;
  84}
  85
  86static int sn9c2028_read1(struct gspca_dev *gspca_dev)
  87{
  88        int rc;
  89
  90        rc = usb_control_msg(gspca_dev->dev,
  91                        usb_rcvctrlpipe(gspca_dev->dev, 0),
  92                        USB_REQ_GET_STATUS,
  93                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
  94                        1, 0, gspca_dev->usb_buf, 1, 500);
  95        if (rc != 1) {
  96                err("read1 error %d", rc);
  97                return (rc < 0) ? rc : -EIO;
  98        }
  99        PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]);
 100        return gspca_dev->usb_buf[0];
 101}
 102
 103static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading)
 104{
 105        int rc;
 106        rc = usb_control_msg(gspca_dev->dev,
 107                        usb_rcvctrlpipe(gspca_dev->dev, 0),
 108                        USB_REQ_GET_STATUS,
 109                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 110                        4, 0, gspca_dev->usb_buf, 4, 500);
 111        if (rc != 4) {
 112                err("read4 error %d", rc);
 113                return (rc < 0) ? rc : -EIO;
 114        }
 115        memcpy(reading, gspca_dev->usb_buf, 4);
 116        PDEBUG(D_USBI, "read4 response %02x%02x%02x%02x", reading[0],
 117               reading[1], reading[2], reading[3]);
 118        return rc;
 119}
 120
 121static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command)
 122{
 123        int i, status;
 124        __u8 reading[4];
 125
 126        status = sn9c2028_command(gspca_dev, command);
 127        if (status < 0)
 128                return status;
 129
 130        status = -1;
 131        for (i = 0; i < 256 && status < 2; i++)
 132                status = sn9c2028_read1(gspca_dev);
 133        if (status != 2) {
 134                err("long command status read error %d", status);
 135                return (status < 0) ? status : -EIO;
 136        }
 137
 138        memset(reading, 0, 4);
 139        status = sn9c2028_read4(gspca_dev, reading);
 140        if (status < 0)
 141                return status;
 142
 143        /* in general, the first byte of the response is the first byte of
 144         * the command, or'ed with 8 */
 145        status = sn9c2028_read1(gspca_dev);
 146        if (status < 0)
 147                return status;
 148
 149        return 0;
 150}
 151
 152static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command)
 153{
 154        int err_code;
 155
 156        err_code = sn9c2028_command(gspca_dev, command);
 157        if (err_code < 0)
 158                return err_code;
 159
 160        err_code = sn9c2028_read1(gspca_dev);
 161        if (err_code < 0)
 162                return err_code;
 163
 164        return 0;
 165}
 166
 167/* this function is called at probe time */
 168static int sd_config(struct gspca_dev *gspca_dev,
 169                     const struct usb_device_id *id)
 170{
 171        struct sd *sd = (struct sd *) gspca_dev;
 172        struct cam *cam = &gspca_dev->cam;
 173
 174        PDEBUG(D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)",
 175               id->idVendor, id->idProduct);
 176
 177        sd->model = id->idProduct;
 178
 179        switch (sd->model) {
 180        case 0x7005:
 181                PDEBUG(D_PROBE, "Genius Smart 300 camera");
 182                break;
 183        case 0x8000:
 184                PDEBUG(D_PROBE, "DC31VC");
 185                break;
 186        case 0x8001:
 187                PDEBUG(D_PROBE, "Spy camera");
 188                break;
 189        case 0x8003:
 190                PDEBUG(D_PROBE, "CIF camera");
 191                break;
 192        case 0x8008:
 193                PDEBUG(D_PROBE, "Mini-Shotz ms-350 camera");
 194                break;
 195        case 0x800a:
 196                PDEBUG(D_PROBE, "Vivitar 3350b type camera");
 197                cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
 198                break;
 199        }
 200
 201        switch (sd->model) {
 202        case 0x8000:
 203        case 0x8001:
 204        case 0x8003:
 205                cam->cam_mode = cif_mode;
 206                cam->nmodes = ARRAY_SIZE(cif_mode);
 207                break;
 208        default:
 209                cam->cam_mode = vga_mode;
 210                cam->nmodes = ARRAY_SIZE(vga_mode);
 211        }
 212        return 0;
 213}
 214
 215/* this function is called at probe and resume time */
 216static int sd_init(struct gspca_dev *gspca_dev)
 217{
 218        int status = -1;
 219
 220        sn9c2028_read1(gspca_dev);
 221        sn9c2028_read1(gspca_dev);
 222        status = sn9c2028_read1(gspca_dev);
 223
 224        return (status < 0) ? status : 0;
 225}
 226
 227static int run_start_commands(struct gspca_dev *gspca_dev,
 228                              struct init_command *cam_commands, int n)
 229{
 230        int i, err_code = -1;
 231
 232        for (i = 0; i < n; i++) {
 233                switch (cam_commands[i].to_read) {
 234                case 4:
 235                        err_code = sn9c2028_long_command(gspca_dev,
 236                                        cam_commands[i].instruction);
 237                        break;
 238                case 1:
 239                        err_code = sn9c2028_short_command(gspca_dev,
 240                                        cam_commands[i].instruction);
 241                        break;
 242                case 0:
 243                        err_code = sn9c2028_command(gspca_dev,
 244                                        cam_commands[i].instruction);
 245                        break;
 246                }
 247                if (err_code < 0)
 248                        return err_code;
 249        }
 250        return 0;
 251}
 252
 253static int start_spy_cam(struct gspca_dev *gspca_dev)
 254{
 255        struct init_command spy_start_commands[] = {
 256                {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 257                {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
 258                {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
 259                {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
 260                {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
 261                {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
 262                {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width  352 */
 263                {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */
 264                /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */
 265                {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4},
 266                {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/
 267                /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */
 268                {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
 269                /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */
 270                {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
 271                {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
 272                /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */
 273                {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 274                {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
 275                /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */
 276                {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
 277                {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
 278                {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
 279                {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
 280                {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
 281                {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4},
 282                {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/
 283                /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
 284                {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
 285                /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */
 286                {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
 287                {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */
 288                {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4},
 289                /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
 290                {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4},
 291                {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4},
 292                {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4},
 293                {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
 294                {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4},
 295                {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4},
 296                {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4},
 297                /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */
 298                /* brightness or gain. 0 is default. 4 is good
 299                 * indoors at night with incandescent lighting */
 300                {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4},
 301                {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/
 302                {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4},
 303                {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
 304                {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4},
 305                {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4},
 306                /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */
 307                {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */
 308                /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */
 309                {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1},
 310                {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */
 311                /* Camera should start to capture now. */
 312        };
 313
 314        return run_start_commands(gspca_dev, spy_start_commands,
 315                                  ARRAY_SIZE(spy_start_commands));
 316}
 317
 318static int start_cif_cam(struct gspca_dev *gspca_dev)
 319{
 320        struct init_command cif_start_commands[] = {
 321                {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 322                /* The entire sequence below seems redundant */
 323                /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
 324                {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
 325                {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4},
 326                {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4},
 327                {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
 328                {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width?
 329                {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height?
 330                {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
 331                {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
 332                {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
 333                {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
 334                {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
 335                {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 336                {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
 337                {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
 338                {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
 339                {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
 340                {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
 341                {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/
 342                {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1},
 343                {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1},
 344                {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1},
 345                {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
 346                {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1},
 347                {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1},
 348                {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1},
 349                {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1},
 350                {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
 351                {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1},
 352                {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1},
 353                {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1},
 354                {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1},
 355                {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1},
 356                {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1},
 357                {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1},
 358                {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1},
 359                {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1},
 360                {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
 361                {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1},
 362                {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1},
 363                {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
 364                {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */
 365                {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */
 366                /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
 367                 * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing
 368                 * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */
 369                /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
 370                 * causes subsampling
 371                 * but not a change in the resolution setting! */
 372                {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 373                {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4},
 374                {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4},
 375                {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4},
 376                {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
 377                {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1},
 378                {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1},
 379                {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
 380                {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1},
 381                {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
 382                {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
 383                {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
 384                {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1},
 385                {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
 386                {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
 387                {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */
 388                /* Camera should start to capture now. */
 389        };
 390
 391        return run_start_commands(gspca_dev, cif_start_commands,
 392                                  ARRAY_SIZE(cif_start_commands));
 393}
 394
 395static int start_ms350_cam(struct gspca_dev *gspca_dev)
 396{
 397        struct init_command ms350_start_commands[] = {
 398                {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 399                {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 400                {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
 401                {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
 402                {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
 403                {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
 404                {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
 405                {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
 406                {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
 407                {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
 408                {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4},
 409                {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
 410                {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
 411                {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
 412                {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 413                {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
 414                {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
 415                {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
 416                {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
 417                {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
 418                {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
 419                {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4},
 420                {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4},
 421                {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4},
 422                {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4},
 423                {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4},
 424                {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4},
 425                {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4},
 426                {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4},
 427                {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4},
 428                {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4},
 429                {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4},
 430                {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
 431                {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4},
 432                {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4},
 433                {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4},
 434                {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4},
 435                {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
 436                {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4},
 437                {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
 438                {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4},
 439                {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4},
 440                {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4},
 441                {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4},
 442                {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width  */
 443                {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */
 444                {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */
 445                {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
 446                {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */
 447                {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 448                {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
 449                {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
 450                {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
 451                {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1},
 452                {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
 453                {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1},
 454                {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1},
 455                {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0},
 456                /* Camera should start to capture now. */
 457        };
 458
 459        return run_start_commands(gspca_dev, ms350_start_commands,
 460                                  ARRAY_SIZE(ms350_start_commands));
 461}
 462
 463static int start_genius_cam(struct gspca_dev *gspca_dev)
 464{
 465        struct init_command genius_start_commands[] = {
 466                {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 467                {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 468                {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4},
 469                {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
 470                {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
 471                /* "preliminary" width and height settings */
 472                {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
 473                {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
 474                {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
 475                {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 476                {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
 477                {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
 478                {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
 479                {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
 480                {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
 481                {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
 482                {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
 483                {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
 484                {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
 485                {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
 486                {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
 487                {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
 488                {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
 489                {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
 490                {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
 491                {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
 492                {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
 493                {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
 494                {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
 495                {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4},
 496                {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4},
 497                {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4},
 498                {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4},
 499                {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4},
 500                {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4},
 501                {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4},
 502                {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4},
 503                {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4},
 504                {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */
 505                {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */
 506                {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
 507                {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
 508                {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4},
 509                {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 510                {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
 511                {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
 512                {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
 513                {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
 514                {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4},
 515                {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
 516                {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4},
 517                {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
 518                {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4},
 519                {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
 520                {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4},
 521                {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
 522                {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4},
 523                {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4},
 524                {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4},
 525                {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
 526                {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
 527                {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0}
 528                /* Camera should start to capture now. */
 529        };
 530
 531        return run_start_commands(gspca_dev, genius_start_commands,
 532                                  ARRAY_SIZE(genius_start_commands));
 533}
 534
 535static int start_vivitar_cam(struct gspca_dev *gspca_dev)
 536{
 537        struct init_command vivitar_start_commands[] = {
 538                {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 539                {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
 540                {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
 541                {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4},
 542                {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4},
 543                {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
 544                {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
 545                {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
 546                {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
 547                {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4},
 548                /*
 549                 * Above is changed from OEM 0x0b. Fixes Bayer tiling.
 550                 * Presumably gives a vertical shift of one row.
 551                 */
 552                {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
 553                /* Above seems to do horizontal shift. */
 554                {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
 555                {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
 556                {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 557                {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
 558                {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
 559                {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
 560                /* Above three commands seem to relate to brightness. */
 561                {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
 562                {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
 563                {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
 564                {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1},
 565                {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1},
 566                {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1},
 567                {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1},
 568                {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
 569                {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1},
 570                {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1},
 571                {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1},
 572                {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1},
 573                {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1},
 574                {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1},
 575                {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1},
 576                {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1},
 577                {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
 578                {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1},
 579                {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1},
 580                {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1},
 581                {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1},
 582                {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1},
 583                {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1},
 584                {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1},
 585                {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1},
 586                {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1},
 587                {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1},
 588                {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1},
 589                {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1},
 590                {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1},
 591                {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1},
 592                {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1},
 593                {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1},
 594                {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1},
 595                {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1},
 596                {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1},
 597                {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1},
 598                /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
 599                {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
 600                {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */
 601                {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
 602                {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1},
 603                {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
 604                {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1},
 605                {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
 606                {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1},
 607                /* Above is brightness; OEM driver setting is 0x10 */
 608                {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
 609                {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
 610                {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}
 611        };
 612
 613        return run_start_commands(gspca_dev, vivitar_start_commands,
 614                                  ARRAY_SIZE(vivitar_start_commands));
 615}
 616
 617static int sd_start(struct gspca_dev *gspca_dev)
 618{
 619        struct sd *sd = (struct sd *) gspca_dev;
 620        int err_code;
 621
 622        sd->sof_read = 0;
 623
 624        switch (sd->model) {
 625        case 0x7005:
 626                err_code = start_genius_cam(gspca_dev);
 627                break;
 628        case 0x8001:
 629                err_code = start_spy_cam(gspca_dev);
 630                break;
 631        case 0x8003:
 632                err_code = start_cif_cam(gspca_dev);
 633                break;
 634        case 0x8008:
 635                err_code = start_ms350_cam(gspca_dev);
 636                break;
 637        case 0x800a:
 638                err_code = start_vivitar_cam(gspca_dev);
 639                break;
 640        default:
 641                err("Starting unknown camera, please report this");
 642                return -ENXIO;
 643        }
 644
 645        return err_code;
 646}
 647
 648static void sd_stopN(struct gspca_dev *gspca_dev)
 649{
 650        int result;
 651        __u8 data[6];
 652
 653        result = sn9c2028_read1(gspca_dev);
 654        if (result < 0)
 655                PDEBUG(D_ERR, "Camera Stop read failed");
 656
 657        memset(data, 0, 6);
 658        data[0] = 0x14;
 659        result = sn9c2028_command(gspca_dev, data);
 660        if (result < 0)
 661                PDEBUG(D_ERR, "Camera Stop command failed");
 662}
 663
 664/* Include sn9c2028 sof detection functions */
 665#include "sn9c2028.h"
 666
 667static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 668                        __u8 *data,                     /* isoc packet */
 669                        int len)                        /* iso packet length */
 670{
 671        unsigned char *sof;
 672
 673        sof = sn9c2028_find_sof(gspca_dev, data, len);
 674        if (sof) {
 675                int n;
 676
 677                /* finish decoding current frame */
 678                n = sof - data;
 679                if (n > sizeof sn9c2028_sof_marker)
 680                        n -= sizeof sn9c2028_sof_marker;
 681                else
 682                        n = 0;
 683                gspca_frame_add(gspca_dev, LAST_PACKET, data, n);
 684                /* Start next frame. */
 685                gspca_frame_add(gspca_dev, FIRST_PACKET,
 686                        sn9c2028_sof_marker, sizeof sn9c2028_sof_marker);
 687                len -= sof - data;
 688                data = sof;
 689        }
 690        gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 691}
 692
 693/* sub-driver description */
 694static const struct sd_desc sd_desc = {
 695        .name = MODULE_NAME,
 696        .ctrls = sd_ctrls,
 697        .nctrls = ARRAY_SIZE(sd_ctrls),
 698        .config = sd_config,
 699        .init = sd_init,
 700        .start = sd_start,
 701        .stopN = sd_stopN,
 702        .pkt_scan = sd_pkt_scan,
 703};
 704
 705/* -- module initialisation -- */
 706static const struct usb_device_id device_table[] = {
 707        {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */
 708        /* The Genius Smart is untested. I can't find an owner ! */
 709        /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */
 710        {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */
 711        {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */
 712        /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */
 713        {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */
 714        {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */
 715        {}
 716};
 717MODULE_DEVICE_TABLE(usb, device_table);
 718
 719/* -- device connect -- */
 720static int sd_probe(struct usb_interface *intf,
 721                        const struct usb_device_id *id)
 722{
 723        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
 724                               THIS_MODULE);
 725}
 726
 727static struct usb_driver sd_driver = {
 728        .name = MODULE_NAME,
 729        .id_table = device_table,
 730        .probe = sd_probe,
 731        .disconnect = gspca_disconnect,
 732#ifdef CONFIG_PM
 733        .suspend = gspca_suspend,
 734        .resume = gspca_resume,
 735#endif
 736};
 737
 738/* -- module insert / remove -- */
 739static int __init sd_mod_init(void)
 740{
 741        return usb_register(&sd_driver);
 742}
 743
 744static void __exit sd_mod_exit(void)
 745{
 746        usb_deregister(&sd_driver);
 747}
 748
 749module_init(sd_mod_init);
 750module_exit(sd_mod_exit);
 751