Version:  2.0.40 2.2.26 2.4.37 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16

Linux/drivers/media/usb/gspca/sunplus.c

  1 /*
  2  *              Sunplus spca504(abc) spca533 spca536 library
  3  *              Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
  4  *
  5  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
  6  *
  7  * This program is free software; you can redistribute it and/or modify
  8  * it under the terms of the GNU General Public License as published by
  9  * the Free Software Foundation; either version 2 of the License, or
 10  * any later version.
 11  *
 12  * This program is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15  * GNU General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU General Public License
 18  * along with this program; if not, write to the Free Software
 19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 20  */
 21 
 22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 23 
 24 #define MODULE_NAME "sunplus"
 25 
 26 #include "gspca.h"
 27 #include "jpeg.h"
 28 
 29 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 30 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
 31 MODULE_LICENSE("GPL");
 32 
 33 #define QUALITY 85
 34 
 35 /* specific webcam descriptor */
 36 struct sd {
 37         struct gspca_dev gspca_dev;     /* !! must be the first item */
 38 
 39         bool autogain;
 40 
 41         u8 bridge;
 42 #define BRIDGE_SPCA504 0
 43 #define BRIDGE_SPCA504B 1
 44 #define BRIDGE_SPCA504C 2
 45 #define BRIDGE_SPCA533 3
 46 #define BRIDGE_SPCA536 4
 47         u8 subtype;
 48 #define AiptekMiniPenCam13 1
 49 #define LogitechClickSmart420 2
 50 #define LogitechClickSmart820 3
 51 #define MegapixV4 4
 52 #define MegaImageVI 5
 53 
 54         u8 jpeg_hdr[JPEG_HDR_SZ];
 55 };
 56 
 57 static const struct v4l2_pix_format vga_mode[] = {
 58         {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 59                 .bytesperline = 320,
 60                 .sizeimage = 320 * 240 * 3 / 8 + 590,
 61                 .colorspace = V4L2_COLORSPACE_JPEG,
 62                 .priv = 2},
 63         {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 64                 .bytesperline = 640,
 65                 .sizeimage = 640 * 480 * 3 / 8 + 590,
 66                 .colorspace = V4L2_COLORSPACE_JPEG,
 67                 .priv = 1},
 68 };
 69 
 70 static const struct v4l2_pix_format custom_mode[] = {
 71         {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 72                 .bytesperline = 320,
 73                 .sizeimage = 320 * 240 * 3 / 8 + 590,
 74                 .colorspace = V4L2_COLORSPACE_JPEG,
 75                 .priv = 2},
 76         {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 77                 .bytesperline = 464,
 78                 .sizeimage = 464 * 480 * 3 / 8 + 590,
 79                 .colorspace = V4L2_COLORSPACE_JPEG,
 80                 .priv = 1},
 81 };
 82 
 83 static const struct v4l2_pix_format vga_mode2[] = {
 84         {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 85                 .bytesperline = 176,
 86                 .sizeimage = 176 * 144 * 3 / 8 + 590,
 87                 .colorspace = V4L2_COLORSPACE_JPEG,
 88                 .priv = 4},
 89         {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 90                 .bytesperline = 320,
 91                 .sizeimage = 320 * 240 * 3 / 8 + 590,
 92                 .colorspace = V4L2_COLORSPACE_JPEG,
 93                 .priv = 3},
 94         {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 95                 .bytesperline = 352,
 96                 .sizeimage = 352 * 288 * 3 / 8 + 590,
 97                 .colorspace = V4L2_COLORSPACE_JPEG,
 98                 .priv = 2},
 99         {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
100                 .bytesperline = 640,
101                 .sizeimage = 640 * 480 * 3 / 8 + 590,
102                 .colorspace = V4L2_COLORSPACE_JPEG,
103                 .priv = 1},
104 };
105 
106 #define SPCA50X_OFFSET_DATA 10
107 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
108 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
109 #define SPCA504_PCCAM600_OFFSET_MODE     5
110 #define SPCA504_PCCAM600_OFFSET_DATA     14
111  /* Frame packet header offsets for the spca533 */
112 #define SPCA533_OFFSET_DATA     16
113 #define SPCA533_OFFSET_FRAMSEQ  15
114 /* Frame packet header offsets for the spca536 */
115 #define SPCA536_OFFSET_DATA     4
116 #define SPCA536_OFFSET_FRAMSEQ  1
117 
118 struct cmd {
119         u8 req;
120         u16 val;
121         u16 idx;
122 };
123 
124 /* Initialisation data for the Creative PC-CAM 600 */
125 static const struct cmd spca504_pccam600_init_data[] = {
126 /*      {0xa0, 0x0000, 0x0503},  * capture mode */
127         {0x00, 0x0000, 0x2000},
128         {0x00, 0x0013, 0x2301},
129         {0x00, 0x0003, 0x2000},
130         {0x00, 0x0001, 0x21ac},
131         {0x00, 0x0001, 0x21a6},
132         {0x00, 0x0000, 0x21a7}, /* brightness */
133         {0x00, 0x0020, 0x21a8}, /* contrast */
134         {0x00, 0x0001, 0x21ac}, /* sat/hue */
135         {0x00, 0x0000, 0x21ad}, /* hue */
136         {0x00, 0x001a, 0x21ae}, /* saturation */
137         {0x00, 0x0002, 0x21a3}, /* gamma */
138         {0x30, 0x0154, 0x0008},
139         {0x30, 0x0004, 0x0006},
140         {0x30, 0x0258, 0x0009},
141         {0x30, 0x0004, 0x0000},
142         {0x30, 0x0093, 0x0004},
143         {0x30, 0x0066, 0x0005},
144         {0x00, 0x0000, 0x2000},
145         {0x00, 0x0013, 0x2301},
146         {0x00, 0x0003, 0x2000},
147         {0x00, 0x0013, 0x2301},
148         {0x00, 0x0003, 0x2000},
149 };
150 
151 /* Creative PC-CAM 600 specific open data, sent before using the
152  * generic initialisation data from spca504_open_data.
153  */
154 static const struct cmd spca504_pccam600_open_data[] = {
155         {0x00, 0x0001, 0x2501},
156         {0x20, 0x0500, 0x0001}, /* snapshot mode */
157         {0x00, 0x0003, 0x2880},
158         {0x00, 0x0001, 0x2881},
159 };
160 
161 /* Initialisation data for the logitech clicksmart 420 */
162 static const struct cmd spca504A_clicksmart420_init_data[] = {
163 /*      {0xa0, 0x0000, 0x0503},  * capture mode */
164         {0x00, 0x0000, 0x2000},
165         {0x00, 0x0013, 0x2301},
166         {0x00, 0x0003, 0x2000},
167         {0x00, 0x0001, 0x21ac},
168         {0x00, 0x0001, 0x21a6},
169         {0x00, 0x0000, 0x21a7}, /* brightness */
170         {0x00, 0x0020, 0x21a8}, /* contrast */
171         {0x00, 0x0001, 0x21ac}, /* sat/hue */
172         {0x00, 0x0000, 0x21ad}, /* hue */
173         {0x00, 0x001a, 0x21ae}, /* saturation */
174         {0x00, 0x0002, 0x21a3}, /* gamma */
175         {0x30, 0x0004, 0x000a},
176         {0xb0, 0x0001, 0x0000},
177 
178         {0xa1, 0x0080, 0x0001},
179         {0x30, 0x0049, 0x0000},
180         {0x30, 0x0060, 0x0005},
181         {0x0c, 0x0004, 0x0000},
182         {0x00, 0x0000, 0x0000},
183         {0x00, 0x0000, 0x2000},
184         {0x00, 0x0013, 0x2301},
185         {0x00, 0x0003, 0x2000},
186 };
187 
188 /* clicksmart 420 open data ? */
189 static const struct cmd spca504A_clicksmart420_open_data[] = {
190         {0x00, 0x0001, 0x2501},
191         {0x20, 0x0502, 0x0000},
192         {0x06, 0x0000, 0x0000},
193         {0x00, 0x0004, 0x2880},
194         {0x00, 0x0001, 0x2881},
195 
196         {0xa0, 0x0000, 0x0503},
197 };
198 
199 static const u8 qtable_creative_pccam[2][64] = {
200         {                               /* Q-table Y-components */
201          0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
202          0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
203          0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
204          0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
205          0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
206          0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
207          0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
208          0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
209         {                               /* Q-table C-components */
210          0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
211          0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
212          0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
213          0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
214          0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
215          0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
216          0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
217          0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
218 };
219 
220 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
221  *              except for one byte. Possibly a typo?
222  *              NWG: 18/05/2003.
223  */
224 static const u8 qtable_spca504_default[2][64] = {
225         {                               /* Q-table Y-components */
226          0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
227          0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
228          0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
229          0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
230          0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
231          0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
232          0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
233          0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
234          },
235         {                               /* Q-table C-components */
236          0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
237          0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
238          0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
239          0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
240          0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
241          0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
242          0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
243          0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
244 };
245 
246 /* read <len> bytes to gspca_dev->usb_buf */
247 static void reg_r(struct gspca_dev *gspca_dev,
248                   u8 req,
249                   u16 index,
250                   u16 len)
251 {
252         int ret;
253 
254         if (len > USB_BUF_SZ) {
255                 PERR("reg_r: buffer overflow\n");
256                 return;
257         }
258         if (gspca_dev->usb_err < 0)
259                 return;
260         ret = usb_control_msg(gspca_dev->dev,
261                         usb_rcvctrlpipe(gspca_dev->dev, 0),
262                         req,
263                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
264                         0,              /* value */
265                         index,
266                         len ? gspca_dev->usb_buf : NULL, len,
267                         500);
268         if (ret < 0) {
269                 pr_err("reg_r err %d\n", ret);
270                 gspca_dev->usb_err = ret;
271         }
272 }
273 
274 /* write one byte */
275 static void reg_w_1(struct gspca_dev *gspca_dev,
276                    u8 req,
277                    u16 value,
278                    u16 index,
279                    u16 byte)
280 {
281         int ret;
282 
283         if (gspca_dev->usb_err < 0)
284                 return;
285         gspca_dev->usb_buf[0] = byte;
286         ret = usb_control_msg(gspca_dev->dev,
287                         usb_sndctrlpipe(gspca_dev->dev, 0),
288                         req,
289                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
290                         value, index,
291                         gspca_dev->usb_buf, 1,
292                         500);
293         if (ret < 0) {
294                 pr_err("reg_w_1 err %d\n", ret);
295                 gspca_dev->usb_err = ret;
296         }
297 }
298 
299 /* write req / index / value */
300 static void reg_w_riv(struct gspca_dev *gspca_dev,
301                      u8 req, u16 index, u16 value)
302 {
303         struct usb_device *dev = gspca_dev->dev;
304         int ret;
305 
306         if (gspca_dev->usb_err < 0)
307                 return;
308         ret = usb_control_msg(dev,
309                         usb_sndctrlpipe(dev, 0),
310                         req,
311                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
312                         value, index, NULL, 0, 500);
313         if (ret < 0) {
314                 pr_err("reg_w_riv err %d\n", ret);
315                 gspca_dev->usb_err = ret;
316                 return;
317         }
318         PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
319                 req, index, value);
320 }
321 
322 static void write_vector(struct gspca_dev *gspca_dev,
323                         const struct cmd *data, int ncmds)
324 {
325         while (--ncmds >= 0) {
326                 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
327                 data++;
328         }
329 }
330 
331 static void setup_qtable(struct gspca_dev *gspca_dev,
332                         const u8 qtable[2][64])
333 {
334         int i;
335 
336         /* loop over y components */
337         for (i = 0; i < 64; i++)
338                 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
339 
340         /* loop over c components */
341         for (i = 0; i < 64; i++)
342                 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
343 }
344 
345 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
346                              u8 req, u16 idx, u16 val)
347 {
348         reg_w_riv(gspca_dev, req, idx, val);
349         reg_r(gspca_dev, 0x01, 0x0001, 1);
350         PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
351         reg_w_riv(gspca_dev, req, idx, val);
352 
353         msleep(200);
354         reg_r(gspca_dev, 0x01, 0x0001, 1);
355         PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
356 }
357 
358 static void spca504_read_info(struct gspca_dev *gspca_dev)
359 {
360         int i;
361         u8 info[6];
362 
363         if (gspca_debug < D_STREAM)
364                 return;
365 
366         for (i = 0; i < 6; i++) {
367                 reg_r(gspca_dev, 0, i, 1);
368                 info[i] = gspca_dev->usb_buf[0];
369         }
370         PDEBUG(D_STREAM,
371                 "Read info: %d %d %d %d %d %d."
372                 " Should be 1,0,2,2,0,0",
373                 info[0], info[1], info[2],
374                 info[3], info[4], info[5]);
375 }
376 
377 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
378                         u8 req,
379                         u16 idx, u16 val, u8 endcode, u8 count)
380 {
381         u16 status;
382 
383         reg_w_riv(gspca_dev, req, idx, val);
384         reg_r(gspca_dev, 0x01, 0x0001, 1);
385         if (gspca_dev->usb_err < 0)
386                 return;
387         PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
388                         gspca_dev->usb_buf[0], endcode);
389         if (!count)
390                 return;
391         count = 200;
392         while (--count > 0) {
393                 msleep(10);
394                 /* gsmart mini2 write a each wait setting 1 ms is enough */
395 /*              reg_w_riv(gspca_dev, req, idx, val); */
396                 reg_r(gspca_dev, 0x01, 0x0001, 1);
397                 status = gspca_dev->usb_buf[0];
398                 if (status == endcode) {
399                         PDEBUG(D_FRAM, "status 0x%04x after wait %d",
400                                 status, 200 - count);
401                                 break;
402                 }
403         }
404 }
405 
406 static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
407 {
408         int count = 10;
409 
410         while (--count > 0) {
411                 reg_r(gspca_dev, 0x21, 0, 1);
412                 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
413                         break;
414                 msleep(10);
415         }
416 }
417 
418 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
419 {
420         int count = 50;
421 
422         while (--count > 0) {
423                 reg_r(gspca_dev, 0x21, 1, 1);
424                 if (gspca_dev->usb_buf[0] != 0) {
425                         reg_w_1(gspca_dev, 0x21, 0, 1, 0);
426                         reg_r(gspca_dev, 0x21, 1, 1);
427                         spca504B_PollingDataReady(gspca_dev);
428                         break;
429                 }
430                 msleep(10);
431         }
432 }
433 
434 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
435 {
436         u8 *data;
437 
438         if (gspca_debug < D_STREAM)
439                 return;
440 
441         data = gspca_dev->usb_buf;
442         reg_r(gspca_dev, 0x20, 0, 5);
443         PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
444                 data[0], data[1], data[2], data[3], data[4]);
445         reg_r(gspca_dev, 0x23, 0, 64);
446         reg_r(gspca_dev, 0x23, 1, 64);
447 }
448 
449 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
450 {
451         struct sd *sd = (struct sd *) gspca_dev;
452         u8 Size;
453 
454         Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
455         switch (sd->bridge) {
456         case BRIDGE_SPCA533:
457                 reg_w_riv(gspca_dev, 0x31, 0, 0);
458                 spca504B_WaitCmdStatus(gspca_dev);
459                 spca504B_PollingDataReady(gspca_dev);
460                 spca50x_GetFirmware(gspca_dev);
461 
462                 reg_w_1(gspca_dev, 0x24, 0, 8, 2);              /* type */
463                 reg_r(gspca_dev, 0x24, 8, 1);
464 
465                 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
466                 reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
467                 spca504B_PollingDataReady(gspca_dev);
468 
469                 /* Init the cam width height with some values get on init ? */
470                 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
471                 spca504B_WaitCmdStatus(gspca_dev);
472                 spca504B_PollingDataReady(gspca_dev);
473                 break;
474         default:
475 /* case BRIDGE_SPCA504B: */
476 /* case BRIDGE_SPCA536: */
477                 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
478                 reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
479                 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
480                 reg_r(gspca_dev, 0x27, 0, 1);                   /* type */
481                 spca504B_PollingDataReady(gspca_dev);
482                 break;
483         case BRIDGE_SPCA504:
484                 Size += 3;
485                 if (sd->subtype == AiptekMiniPenCam13) {
486                         /* spca504a aiptek */
487                         spca504A_acknowledged_command(gspca_dev,
488                                                 0x08, Size, 0,
489                                                 0x80 | (Size & 0x0f), 1);
490                         spca504A_acknowledged_command(gspca_dev,
491                                                         1, 3, 0, 0x9f, 0);
492                 } else {
493                         spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
494                 }
495                 break;
496         case BRIDGE_SPCA504C:
497                 /* capture mode */
498                 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
499                 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
500                 break;
501         }
502 }
503 
504 static void spca504_wait_status(struct gspca_dev *gspca_dev)
505 {
506         int cnt;
507 
508         cnt = 256;
509         while (--cnt > 0) {
510                 /* With this we get the status, when return 0 it's all ok */
511                 reg_r(gspca_dev, 0x06, 0x00, 1);
512                 if (gspca_dev->usb_buf[0] == 0)
513                         return;
514                 msleep(10);
515         }
516 }
517 
518 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
519 {
520         reg_w_1(gspca_dev, 0x26, 0, 0, 3);
521         reg_r(gspca_dev, 0x26, 0, 1);
522         spca504B_PollingDataReady(gspca_dev);
523 }
524 
525 static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
526 {
527         struct sd *sd = (struct sd *) gspca_dev;
528         u16 reg;
529 
530         reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
531         reg_w_riv(gspca_dev, 0x00, reg, val);
532 }
533 
534 static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
535 {
536         struct sd *sd = (struct sd *) gspca_dev;
537         u16 reg;
538 
539         reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
540         reg_w_riv(gspca_dev, 0x00, reg, val);
541 }
542 
543 static void setcolors(struct gspca_dev *gspca_dev, s32 val)
544 {
545         struct sd *sd = (struct sd *) gspca_dev;
546         u16 reg;
547 
548         reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
549         reg_w_riv(gspca_dev, 0x00, reg, val);
550 }
551 
552 static void init_ctl_reg(struct gspca_dev *gspca_dev)
553 {
554         struct sd *sd = (struct sd *) gspca_dev;
555         int pollreg = 1;
556 
557         switch (sd->bridge) {
558         case BRIDGE_SPCA504:
559         case BRIDGE_SPCA504C:
560                 pollreg = 0;
561                 /* fall thru */
562         default:
563 /*      case BRIDGE_SPCA533: */
564 /*      case BRIDGE_SPCA504B: */
565                 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00);  /* hue */
566                 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01);  /* sat/hue */
567                 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00);  /* gamma */
568                 break;
569         case BRIDGE_SPCA536:
570                 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
571                 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
572                 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
573                 break;
574         }
575         if (pollreg)
576                 spca504B_PollingDataReady(gspca_dev);
577 }
578 
579 /* this function is called at probe time */
580 static int sd_config(struct gspca_dev *gspca_dev,
581                         const struct usb_device_id *id)
582 {
583         struct sd *sd = (struct sd *) gspca_dev;
584         struct cam *cam;
585 
586         cam = &gspca_dev->cam;
587 
588         sd->bridge = id->driver_info >> 8;
589         sd->subtype = id->driver_info;
590 
591         if (sd->subtype == AiptekMiniPenCam13) {
592 
593                 /* try to get the firmware as some cam answer 2.0.1.2.2
594                  * and should be a spca504b then overwrite that setting */
595                 reg_r(gspca_dev, 0x20, 0, 1);
596                 switch (gspca_dev->usb_buf[0]) {
597                 case 1:
598                         break;          /* (right bridge/subtype) */
599                 case 2:
600                         sd->bridge = BRIDGE_SPCA504B;
601                         sd->subtype = 0;
602                         break;
603                 default:
604                         return -ENODEV;
605                 }
606         }
607 
608         switch (sd->bridge) {
609         default:
610 /*      case BRIDGE_SPCA504B: */
611 /*      case BRIDGE_SPCA504: */
612 /*      case BRIDGE_SPCA536: */
613                 cam->cam_mode = vga_mode;
614                 cam->nmodes = ARRAY_SIZE(vga_mode);
615                 break;
616         case BRIDGE_SPCA533:
617                 cam->cam_mode = custom_mode;
618                 if (sd->subtype == MegaImageVI)         /* 320x240 only */
619                         cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
620                 else
621                         cam->nmodes = ARRAY_SIZE(custom_mode);
622                 break;
623         case BRIDGE_SPCA504C:
624                 cam->cam_mode = vga_mode2;
625                 cam->nmodes = ARRAY_SIZE(vga_mode2);
626                 break;
627         }
628         return 0;
629 }
630 
631 /* this function is called at probe and resume time */
632 static int sd_init(struct gspca_dev *gspca_dev)
633 {
634         struct sd *sd = (struct sd *) gspca_dev;
635 
636         switch (sd->bridge) {
637         case BRIDGE_SPCA504B:
638                 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
639                 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
640                 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
641                 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
642                 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
643                 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
644                 /* fall thru */
645         case BRIDGE_SPCA533:
646                 spca504B_PollingDataReady(gspca_dev);
647                 spca50x_GetFirmware(gspca_dev);
648                 break;
649         case BRIDGE_SPCA536:
650                 spca50x_GetFirmware(gspca_dev);
651                 reg_r(gspca_dev, 0x00, 0x5002, 1);
652                 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
653                 reg_r(gspca_dev, 0x24, 0, 1);
654                 spca504B_PollingDataReady(gspca_dev);
655                 reg_w_riv(gspca_dev, 0x34, 0, 0);
656                 spca504B_WaitCmdStatus(gspca_dev);
657                 break;
658         case BRIDGE_SPCA504C:   /* pccam600 */
659                 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
660                 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
661                 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001);     /* reset */
662                 spca504_wait_status(gspca_dev);
663                 if (sd->subtype == LogitechClickSmart420)
664                         write_vector(gspca_dev,
665                                 spca504A_clicksmart420_open_data,
666                                 ARRAY_SIZE(spca504A_clicksmart420_open_data));
667                 else
668                         write_vector(gspca_dev, spca504_pccam600_open_data,
669                                 ARRAY_SIZE(spca504_pccam600_open_data));
670                 setup_qtable(gspca_dev, qtable_creative_pccam);
671                 break;
672         default:
673 /*      case BRIDGE_SPCA504: */
674                 PDEBUG(D_STREAM, "Opening SPCA504");
675                 if (sd->subtype == AiptekMiniPenCam13) {
676                         spca504_read_info(gspca_dev);
677 
678                         /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
679                         spca504A_acknowledged_command(gspca_dev, 0x24,
680                                                         8, 3, 0x9e, 1);
681                         /* Twice sequential need status 0xff->0x9e->0x9d */
682                         spca504A_acknowledged_command(gspca_dev, 0x24,
683                                                         8, 3, 0x9e, 0);
684 
685                         spca504A_acknowledged_command(gspca_dev, 0x24,
686                                                         0, 0, 0x9d, 1);
687                         /******************************/
688                         /* spca504a aiptek */
689                         spca504A_acknowledged_command(gspca_dev, 0x08,
690                                                         6, 0, 0x86, 1);
691 /*                      reg_write (dev, 0, 0x2000, 0); */
692 /*                      reg_write (dev, 0, 0x2883, 1); */
693 /*                      spca504A_acknowledged_command (gspca_dev, 0x08,
694                                                         6, 0, 0x86, 1); */
695 /*                      spca504A_acknowledged_command (gspca_dev, 0x24,
696                                                         0, 0, 0x9D, 1); */
697                         reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
698                                                         /* L92 sno1t.txt */
699                         reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
700                         spca504A_acknowledged_command(gspca_dev, 0x01,
701                                                         0x0f, 0, 0xff, 0);
702                 }
703                 /* setup qtable */
704                 reg_w_riv(gspca_dev, 0, 0x2000, 0);
705                 reg_w_riv(gspca_dev, 0, 0x2883, 1);
706                 setup_qtable(gspca_dev, qtable_spca504_default);
707                 break;
708         }
709         return gspca_dev->usb_err;
710 }
711 
712 static int sd_start(struct gspca_dev *gspca_dev)
713 {
714         struct sd *sd = (struct sd *) gspca_dev;
715         int enable;
716 
717         /* create the JPEG header */
718         jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
719                         gspca_dev->pixfmt.width,
720                         0x22);          /* JPEG 411 */
721         jpeg_set_qual(sd->jpeg_hdr, QUALITY);
722 
723         if (sd->bridge == BRIDGE_SPCA504B)
724                 spca504B_setQtable(gspca_dev);
725         spca504B_SetSizeType(gspca_dev);
726         switch (sd->bridge) {
727         default:
728 /*      case BRIDGE_SPCA504B: */
729 /*      case BRIDGE_SPCA533: */
730 /*      case BRIDGE_SPCA536: */
731                 switch (sd->subtype) {
732                 case MegapixV4:
733                 case LogitechClickSmart820:
734                 case MegaImageVI:
735                         reg_w_riv(gspca_dev, 0xf0, 0, 0);
736                         spca504B_WaitCmdStatus(gspca_dev);
737                         reg_r(gspca_dev, 0xf0, 4, 0);
738                         spca504B_WaitCmdStatus(gspca_dev);
739                         break;
740                 default:
741                         reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
742                         spca504B_WaitCmdStatus(gspca_dev);
743                         spca504B_PollingDataReady(gspca_dev);
744                         break;
745                 }
746                 break;
747         case BRIDGE_SPCA504:
748                 if (sd->subtype == AiptekMiniPenCam13) {
749                         spca504_read_info(gspca_dev);
750 
751                         /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
752                         spca504A_acknowledged_command(gspca_dev, 0x24,
753                                                         8, 3, 0x9e, 1);
754                         /* Twice sequential need status 0xff->0x9e->0x9d */
755                         spca504A_acknowledged_command(gspca_dev, 0x24,
756                                                         8, 3, 0x9e, 0);
757                         spca504A_acknowledged_command(gspca_dev, 0x24,
758                                                         0, 0, 0x9d, 1);
759                 } else {
760                         spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
761                         spca504_read_info(gspca_dev);
762                         spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
763                         spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
764                 }
765                 spca504B_SetSizeType(gspca_dev);
766                 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
767                                                         /* L92 sno1t.txt */
768                 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
769                 break;
770         case BRIDGE_SPCA504C:
771                 if (sd->subtype == LogitechClickSmart420) {
772                         write_vector(gspca_dev,
773                                 spca504A_clicksmart420_init_data,
774                                 ARRAY_SIZE(spca504A_clicksmart420_init_data));
775                 } else {
776                         write_vector(gspca_dev, spca504_pccam600_init_data,
777                                 ARRAY_SIZE(spca504_pccam600_init_data));
778                 }
779                 enable = (sd->autogain ? 0x04 : 0x01);
780                 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
781                                                         /* auto exposure */
782                 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
783                                                         /* auto whiteness */
784 
785                 /* set default exposure compensation and whiteness balance */
786                 reg_w_riv(gspca_dev, 0x30, 0x0001, 800);        /* ~ 20 fps */
787                 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
788                 spca504B_SetSizeType(gspca_dev);
789                 break;
790         }
791         init_ctl_reg(gspca_dev);
792         return gspca_dev->usb_err;
793 }
794 
795 static void sd_stopN(struct gspca_dev *gspca_dev)
796 {
797         struct sd *sd = (struct sd *) gspca_dev;
798 
799         switch (sd->bridge) {
800         default:
801 /*      case BRIDGE_SPCA533: */
802 /*      case BRIDGE_SPCA536: */
803 /*      case BRIDGE_SPCA504B: */
804                 reg_w_riv(gspca_dev, 0x31, 0, 0);
805                 spca504B_WaitCmdStatus(gspca_dev);
806                 spca504B_PollingDataReady(gspca_dev);
807                 break;
808         case BRIDGE_SPCA504:
809         case BRIDGE_SPCA504C:
810                 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
811 
812                 if (sd->subtype == AiptekMiniPenCam13) {
813                         /* spca504a aiptek */
814 /*                      spca504A_acknowledged_command(gspca_dev, 0x08,
815                                                          6, 0, 0x86, 1); */
816                         spca504A_acknowledged_command(gspca_dev, 0x24,
817                                                         0x00, 0x00, 0x9d, 1);
818                         spca504A_acknowledged_command(gspca_dev, 0x01,
819                                                         0x0f, 0x00, 0xff, 1);
820                 } else {
821                         spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
822                         reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
823                 }
824                 break;
825         }
826 }
827 
828 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
829                         u8 *data,                       /* isoc packet */
830                         int len)                        /* iso packet length */
831 {
832         struct sd *sd = (struct sd *) gspca_dev;
833         int i, sof = 0;
834         static u8 ffd9[] = {0xff, 0xd9};
835 
836 /* frames are jpeg 4.1.1 without 0xff escape */
837         switch (sd->bridge) {
838         case BRIDGE_SPCA533:
839                 if (data[0] == 0xff) {
840                         if (data[1] != 0x01) {  /* drop packet */
841 /*                              gspca_dev->last_packet_type = DISCARD_PACKET; */
842                                 return;
843                         }
844                         sof = 1;
845                         data += SPCA533_OFFSET_DATA;
846                         len -= SPCA533_OFFSET_DATA;
847                 } else {
848                         data += 1;
849                         len -= 1;
850                 }
851                 break;
852         case BRIDGE_SPCA536:
853                 if (data[0] == 0xff) {
854                         sof = 1;
855                         data += SPCA536_OFFSET_DATA;
856                         len -= SPCA536_OFFSET_DATA;
857                 } else {
858                         data += 2;
859                         len -= 2;
860                 }
861                 break;
862         default:
863 /*      case BRIDGE_SPCA504: */
864 /*      case BRIDGE_SPCA504B: */
865                 switch (data[0]) {
866                 case 0xfe:                      /* start of frame */
867                         sof = 1;
868                         data += SPCA50X_OFFSET_DATA;
869                         len -= SPCA50X_OFFSET_DATA;
870                         break;
871                 case 0xff:                      /* drop packet */
872 /*                      gspca_dev->last_packet_type = DISCARD_PACKET; */
873                         return;
874                 default:
875                         data += 1;
876                         len -= 1;
877                         break;
878                 }
879                 break;
880         case BRIDGE_SPCA504C:
881                 switch (data[0]) {
882                 case 0xfe:                      /* start of frame */
883                         sof = 1;
884                         data += SPCA504_PCCAM600_OFFSET_DATA;
885                         len -= SPCA504_PCCAM600_OFFSET_DATA;
886                         break;
887                 case 0xff:                      /* drop packet */
888 /*                      gspca_dev->last_packet_type = DISCARD_PACKET; */
889                         return;
890                 default:
891                         data += 1;
892                         len -= 1;
893                         break;
894                 }
895                 break;
896         }
897         if (sof) {              /* start of frame */
898                 gspca_frame_add(gspca_dev, LAST_PACKET,
899                                 ffd9, 2);
900 
901                 /* put the JPEG header in the new frame */
902                 gspca_frame_add(gspca_dev, FIRST_PACKET,
903                         sd->jpeg_hdr, JPEG_HDR_SZ);
904         }
905 
906         /* add 0x00 after 0xff */
907         i = 0;
908         do {
909                 if (data[i] == 0xff) {
910                         gspca_frame_add(gspca_dev, INTER_PACKET,
911                                         data, i + 1);
912                         len -= i;
913                         data += i;
914                         *data = 0x00;
915                         i = 0;
916                 }
917                 i++;
918         } while (i < len);
919         gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
920 }
921 
922 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
923 {
924         struct gspca_dev *gspca_dev =
925                 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
926         struct sd *sd = (struct sd *)gspca_dev;
927 
928         gspca_dev->usb_err = 0;
929 
930         if (!gspca_dev->streaming)
931                 return 0;
932 
933         switch (ctrl->id) {
934         case V4L2_CID_BRIGHTNESS:
935                 setbrightness(gspca_dev, ctrl->val);
936                 break;
937         case V4L2_CID_CONTRAST:
938                 setcontrast(gspca_dev, ctrl->val);
939                 break;
940         case V4L2_CID_SATURATION:
941                 setcolors(gspca_dev, ctrl->val);
942                 break;
943         case V4L2_CID_AUTOGAIN:
944                 sd->autogain = ctrl->val;
945                 break;
946         }
947         return gspca_dev->usb_err;
948 }
949 
950 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
951         .s_ctrl = sd_s_ctrl,
952 };
953 
954 static int sd_init_controls(struct gspca_dev *gspca_dev)
955 {
956         struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
957 
958         gspca_dev->vdev.ctrl_handler = hdl;
959         v4l2_ctrl_handler_init(hdl, 4);
960         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
961                         V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
962         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
963                         V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
964         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
965                         V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
966         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
967                         V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
968 
969         if (hdl->error) {
970                 pr_err("Could not initialize controls\n");
971                 return hdl->error;
972         }
973         return 0;
974 }
975 
976 /* sub-driver description */
977 static const struct sd_desc sd_desc = {
978         .name = MODULE_NAME,
979         .config = sd_config,
980         .init = sd_init,
981         .init_controls = sd_init_controls,
982         .start = sd_start,
983         .stopN = sd_stopN,
984         .pkt_scan = sd_pkt_scan,
985 };
986 
987 /* -- module initialisation -- */
988 #define BS(bridge, subtype) \
989         .driver_info = (BRIDGE_ ## bridge << 8) \
990                         | (subtype)
991 static const struct usb_device_id device_table[] = {
992         {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
993         {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
994         {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
995         {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
996         {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
997         {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
998         {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
999         {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1000         {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1001         {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1002         {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1003         {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1004         {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1005         {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1006         {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1007         {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1008         {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1009         {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1010         {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1011         {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1012         {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1013         {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1014         {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1015         {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1016         {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1017         {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1018         {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1019         {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1020         {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1021         {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1022         {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1023         {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1024         {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1025         {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1026         {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1027         {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1028         {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1029         {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1030         {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B, 0)},
1031         {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1032         {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1033         {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1034         {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1035         {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1036         {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1037         {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1038         {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1039         {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1040         {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1041         {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1042         {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1043         {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1044         {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1045         {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1046         {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1047         {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1048         {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1049         {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1050         {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1051         {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1052         {}
1053 };
1054 MODULE_DEVICE_TABLE(usb, device_table);
1055 
1056 /* -- device connect -- */
1057 static int sd_probe(struct usb_interface *intf,
1058                         const struct usb_device_id *id)
1059 {
1060         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1061                                 THIS_MODULE);
1062 }
1063 
1064 static struct usb_driver sd_driver = {
1065         .name = MODULE_NAME,
1066         .id_table = device_table,
1067         .probe = sd_probe,
1068         .disconnect = gspca_disconnect,
1069 #ifdef CONFIG_PM
1070         .suspend = gspca_suspend,
1071         .resume = gspca_resume,
1072         .reset_resume = gspca_resume,
1073 #endif
1074 };
1075 
1076 module_usb_driver(sd_driver);
1077 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us