blob: aa9e921e7cef58531e2ce75b80f266670bfe10aa [file] [log] [blame]
Thomas Gleixnerfd9871f2019-05-19 15:51:54 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002/*
3 * Syntek DV4000 (STK014) subdriver
4 *
Jean-Francois Moined43fa322008-06-12 10:58:58 -03005 * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03006 */
7
Joe Perches133a9fe2011-08-21 19:56:57 -03008#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030010#define MODULE_NAME "stk014"
11
12#include "gspca.h"
13#include "jpeg.h"
14
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030015MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
16MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
17MODULE_LICENSE("GPL");
18
Hans de Goedeb56ab4c2012-06-27 16:48:33 -030019#define QUALITY 50
20
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030021/* specific webcam descriptor */
22struct sd {
23 struct gspca_dev gspca_dev; /* !! must be the first item */
Jean-François Moine9a731a32010-06-04 05:26:42 -030024 u8 jpeg_hdr[JPEG_HDR_SZ];
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030025};
26
Jean-Francois Moinecc611b82008-12-29 07:49:41 -030027static const struct v4l2_pix_format vga_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030028 {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},
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030038};
39
40/* -- read a register -- */
Jean-Francois Moineecb77682009-12-02 14:39:53 -030041static u8 reg_r(struct gspca_dev *gspca_dev,
Jean-Francois Moine739570b2008-07-14 09:38:29 -030042 __u16 index)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030043{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030044 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030045 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030046
Jean-Francois Moineecb77682009-12-02 14:39:53 -030047 if (gspca_dev->usb_err < 0)
48 return 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030049 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,
Jean-Francois Moine739570b2008-07-14 09:38:29 -030054 gspca_dev->usb_buf, 1,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030055 500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -030056 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -030057 pr_err("reg_r err %d\n", ret);
Jean-Francois Moineecb77682009-12-02 14:39:53 -030058 gspca_dev->usb_err = ret;
59 return 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -030060 }
61 return gspca_dev->usb_buf[0];
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030062}
63
64/* -- write a register -- */
Jean-Francois Moineecb77682009-12-02 14:39:53 -030065static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030066 __u16 index, __u16 value)
67{
68 struct usb_device *dev = gspca_dev->dev;
69 int ret;
70
Jean-Francois Moineecb77682009-12-02 14:39:53 -030071 if (gspca_dev->usb_err < 0)
72 return;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030073 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);
Jean-Francois Moineecb77682009-12-02 14:39:53 -030081 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -030082 pr_err("reg_w err %d\n", ret);
Jean-Francois Moineecb77682009-12-02 14:39:53 -030083 gspca_dev->usb_err = ret;
84 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030085}
86
Jean-Francois Moine739570b2008-07-14 09:38:29 -030087/* -- get a bulk value (4 bytes) -- */
Jean-Francois Moineecb77682009-12-02 14:39:53 -030088static void rcv_val(struct gspca_dev *gspca_dev,
Jean-Francois Moine739570b2008-07-14 09:38:29 -030089 int ads)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030090{
91 struct usb_device *dev = gspca_dev->dev;
92 int alen, ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030093
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030094 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);
Jean-Francois Moine739570b2008-07-14 09:38:29 -030098 reg_w(gspca_dev, 0x638, 4); /* len & 0xff */
99 reg_w(gspca_dev, 0x639, 0); /* len >> 8 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300100 reg_w(gspca_dev, 0x63a, 0);
101 reg_w(gspca_dev, 0x63b, 0);
102 reg_w(gspca_dev, 0x630, 5);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300103 if (gspca_dev->usb_err < 0)
104 return;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300105 ret = usb_bulk_msg(dev,
Jean-Francois Moine50e06de2008-12-31 08:13:46 -0300106 usb_rcvbulkpipe(dev, 0x05),
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300107 gspca_dev->usb_buf,
108 4, /* length */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300109 &alen,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300110 500); /* timeout in milliseconds */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300111 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300112 pr_err("rcv_val err %d\n", ret);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300113 gspca_dev->usb_err = ret;
114 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300115}
116
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300117/* -- send a bulk value -- */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300118static void snd_val(struct gspca_dev *gspca_dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300119 int ads,
120 unsigned int val)
121{
122 struct usb_device *dev = gspca_dev->dev;
123 int alen, ret;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300124 __u8 seq = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300125
126 if (ads == 0x003f08) {
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300127 reg_r(gspca_dev, 0x0704);
128 seq = reg_r(gspca_dev, 0x0705);
129 reg_r(gspca_dev, 0x0650);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300130 reg_w(gspca_dev, 0x654, seq);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300131 } else {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300132 reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300133 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300134 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);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300142 if (gspca_dev->usb_err < 0)
143 return;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300144 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;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300148 ret = usb_bulk_msg(dev,
149 usb_sndbulkpipe(dev, 6),
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300150 gspca_dev->usb_buf,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300151 4,
152 &alen,
153 500); /* timeout in milliseconds */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300154 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300155 pr_err("snd_val err %d\n", ret);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300156 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 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300163 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300164}
165
166/* set a camera parameter */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300167static void set_par(struct gspca_dev *gspca_dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300168 int parval)
169{
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300170 snd_val(gspca_dev, 0x003f08, parval);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300171}
172
Hans Verkuil74dec792012-05-16 08:38:34 -0300173static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300174{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300175 int parval;
176
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300177 parval = 0x06000000 /* whiteness */
Hans Verkuil74dec792012-05-16 08:38:34 -0300178 + (val << 16);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300179 set_par(gspca_dev, parval);
180}
181
Hans Verkuil74dec792012-05-16 08:38:34 -0300182static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300183{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300184 int parval;
185
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300186 parval = 0x07000000 /* contrast */
Hans Verkuil74dec792012-05-16 08:38:34 -0300187 + (val << 16);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300188 set_par(gspca_dev, parval);
189}
190
Hans Verkuil74dec792012-05-16 08:38:34 -0300191static void setcolors(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300192{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300193 int parval;
194
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300195 parval = 0x08000000 /* saturation */
Hans Verkuil74dec792012-05-16 08:38:34 -0300196 + (val << 16);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300197 set_par(gspca_dev, parval);
198}
199
Hans Verkuil74dec792012-05-16 08:38:34 -0300200static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300201{
Hans Verkuil74dec792012-05-16 08:38:34 -0300202 set_par(gspca_dev, val == 1
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300203 ? 0x33640000 /* 50 Hz */
204 : 0x33780000); /* 60 Hz */
205}
206
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300207/* this function is called at probe time */
208static int sd_config(struct gspca_dev *gspca_dev,
209 const struct usb_device_id *id)
210{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300211 gspca_dev->cam.cam_mode = vga_mode;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300212 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300213 return 0;
214}
215
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300216/* this function is called at probe and resume time */
217static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300218{
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300219 u8 ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300220
221 /* check if the device responds */
222 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300223 ret = reg_r(gspca_dev, 0x0740);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300224 if (gspca_dev->usb_err >= 0) {
225 if (ret != 0xff) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300226 pr_err("init reg: 0x%02x\n", ret);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300227 gspca_dev->usb_err = -EIO;
228 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300229 }
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300230 return gspca_dev->usb_err;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300231}
232
233/* -- start the camera -- */
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300234static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300235{
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300236 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300237 int ret, value;
238
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300239 /* create the JPEG header */
Ondrej Zary1966bc22013-08-30 17:54:23 -0300240 jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
241 gspca_dev->pixfmt.width,
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300242 0x22); /* JPEG 411 */
Hans de Goedeb56ab4c2012-06-27 16:48:33 -0300243 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300244
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300245 /* 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);
Ondrej Zary1966bc22013-08-30 17:54:23 -0300252 if (gspca_dev->pixfmt.width > 320)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300253 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);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300260 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300261 pr_err("set intf %d %d failed\n",
262 gspca_dev->iface, gspca_dev->alt);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300263 gspca_dev->usb_err = ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300264 goto out;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300265 }
Mauro Carvalho Chehabe2f233d2015-04-29 15:06:20 -0300266 reg_r(gspca_dev, 0x0630);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300267 rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300268 reg_r(gspca_dev, 0x0650);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300269 snd_val(gspca_dev, 0x000020, 0xffffffff);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300270 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);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300275 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 ? */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300279
280 /* start the video flow */
281 set_par(gspca_dev, 0x01000000);
282 set_par(gspca_dev, 0x01000000);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300283 if (gspca_dev->usb_err >= 0)
Joe Perches37d5efb2017-09-22 15:20:33 -0400284 gspca_dbg(gspca_dev, D_STREAM, "camera started alt: 0x%02x\n",
285 gspca_dev->alt);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300286out:
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300287 return gspca_dev->usb_err;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300288}
289
290static void sd_stopN(struct gspca_dev *gspca_dev)
291{
292 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300293
294 set_par(gspca_dev, 0x02000000);
295 set_par(gspca_dev, 0x02000000);
296 usb_set_interface(dev, gspca_dev->iface, 1);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300297 reg_r(gspca_dev, 0x0630);
298 rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */
299 reg_r(gspca_dev, 0x0650);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300300 snd_val(gspca_dev, 0x000020, 0xffffffff);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300301 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);
Joe Perches37d5efb2017-09-22 15:20:33 -0400306 gspca_dbg(gspca_dev, D_STREAM, "camera stopped\n");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300307}
308
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300309static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300310 u8 *data, /* isoc packet */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300311 int len) /* iso packet length */
312{
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300313 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300314 static unsigned char ffd9[] = {0xff, 0xd9};
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300315
316 /* a frame starts with:
317 * - 0xff 0xfe
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300318 * - 0x08 0x00 - length (little endian ?!)
319 * - 4 bytes = size of whole frame (BE - including header)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300320 * - 0x00 0x0c
321 * - 0xff 0xd8
322 * - .. JPEG image with escape sequences (ff 00)
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300323 * (without ending - ff d9)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300324 */
325 if (data[0] == 0xff && data[1] == 0xfe) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300326 gspca_frame_add(gspca_dev, LAST_PACKET,
327 ffd9, 2);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300328
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300329 /* put the JPEG 411 header */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300330 gspca_frame_add(gspca_dev, FIRST_PACKET,
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300331 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300332
333 /* beginning of the frame */
334#define STKHDRSZ 12
Jean-Francois Moine88437652008-11-24 06:28:58 -0300335 data += STKHDRSZ;
336 len -= STKHDRSZ;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300337 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300338 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300339}
340
Hans Verkuil74dec792012-05-16 08:38:34 -0300341static 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);
Hans Verkuil74dec792012-05-16 08:38:34 -0300345
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;
Hans Verkuil74dec792012-05-16 08:38:34 -0300364 }
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{
Hans Verkuil74dec792012-05-16 08:38:34 -0300374 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
375
376 gspca_dev->vdev.ctrl_handler = hdl;
Hans de Goedeb56ab4c2012-06-27 16:48:33 -0300377 v4l2_ctrl_handler_init(hdl, 4);
Hans Verkuil74dec792012-05-16 08:38:34 -0300378 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);
Hans Verkuil74dec792012-05-16 08:38:34 -0300388
389 if (hdl->error) {
390 pr_err("Could not initialize controls\n");
391 return hdl->error;
392 }
393 return 0;
394}
395
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300396/* sub-driver description */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300397static const struct sd_desc sd_desc = {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300398 .name = MODULE_NAME,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300399 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300400 .init = sd_init,
Hans Verkuil74dec792012-05-16 08:38:34 -0300401 .init_controls = sd_init_controls,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300402 .start = sd_start,
403 .stopN = sd_stopN,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300404 .pkt_scan = sd_pkt_scan,
405};
406
407/* -- module initialisation -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -0300408static const struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300409 {USB_DEVICE(0x05e1, 0x0893)},
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300410 {}
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{
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300418 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
419 THIS_MODULE);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300420}
421
422static struct usb_driver sd_driver = {
423 .name = MODULE_NAME,
424 .id_table = device_table,
425 .probe = sd_probe,
426 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -0300427#ifdef CONFIG_PM
428 .suspend = gspca_suspend,
429 .resume = gspca_resume,
Hans de Goede8bb58962012-06-30 06:44:47 -0300430 .reset_resume = gspca_resume,
Jean-Francois Moine6a709742008-09-03 16:48:10 -0300431#endif
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300432};
433
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -0800434module_usb_driver(sd_driver);