Commit | Line | Data |
---|---|---|
c942fddf | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
4c98834a EA |
2 | /* |
3 | * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher | |
4 | * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland | |
5 | * Copyright (c) 2002, 2003 Tuukka Toivonen | |
6 | * Copyright (c) 2008 Erik Andrén | |
7 | * | |
4c98834a EA |
8 | * P/N 861037: Sensor HDCS1000 ASIC STV0600 |
9 | * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 | |
10 | * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express | |
11 | * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam | |
12 | * P/N 861075-0040: Sensor HDCS1000 ASIC | |
13 | * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB | |
14 | * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web | |
15 | */ | |
16 | ||
133a9fe9 JP |
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
18 | ||
0158e98f | 19 | #include <linux/input.h> |
4c98834a EA |
20 | #include "stv06xx_sensor.h" |
21 | ||
22 | MODULE_AUTHOR("Erik Andrén"); | |
23 | MODULE_DESCRIPTION("STV06XX USB Camera Driver"); | |
24 | MODULE_LICENSE("GPL"); | |
25 | ||
90ab5ee9 RR |
26 | static bool dump_bridge; |
27 | static bool dump_sensor; | |
4c98834a EA |
28 | |
29 | int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data) | |
30 | { | |
31 | int err; | |
c93396e1 | 32 | struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; |
4c98834a EA |
33 | struct usb_device *udev = sd->gspca_dev.dev; |
34 | __u8 *buf = sd->gspca_dev.usb_buf; | |
c93396e1 | 35 | |
4c98834a EA |
36 | u8 len = (i2c_data > 0xff) ? 2 : 1; |
37 | ||
38 | buf[0] = i2c_data & 0xff; | |
39 | buf[1] = (i2c_data >> 8) & 0xff; | |
40 | ||
41 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | |
42 | 0x04, 0x40, address, 0, buf, len, | |
43 | STV06XX_URB_MSG_TIMEOUT); | |
44 | ||
37d5efb0 JP |
45 | gspca_dbg(gspca_dev, D_CONF, "Written 0x%x to address 0x%x, status: %d\n", |
46 | i2c_data, address, err); | |
4c98834a EA |
47 | |
48 | return (err < 0) ? err : 0; | |
49 | } | |
50 | ||
51 | int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data) | |
52 | { | |
53 | int err; | |
c93396e1 | 54 | struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; |
4c98834a EA |
55 | struct usb_device *udev = sd->gspca_dev.dev; |
56 | __u8 *buf = sd->gspca_dev.usb_buf; | |
57 | ||
58 | err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | |
59 | 0x04, 0xc0, address, 0, buf, 1, | |
60 | STV06XX_URB_MSG_TIMEOUT); | |
61 | ||
62 | *i2c_data = buf[0]; | |
63 | ||
37d5efb0 JP |
64 | gspca_dbg(gspca_dev, D_CONF, "Reading 0x%x from address 0x%x, status %d\n", |
65 | *i2c_data, address, err); | |
4c98834a EA |
66 | |
67 | return (err < 0) ? err : 0; | |
68 | } | |
69 | ||
70 | /* Wraps the normal write sensor bytes / words functions for writing a | |
71 | single value */ | |
72 | int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value) | |
73 | { | |
74 | if (sd->sensor->i2c_len == 2) { | |
75 | u16 data[2] = { address, value }; | |
76 | return stv06xx_write_sensor_words(sd, data, 1); | |
77 | } else { | |
78 | u8 data[2] = { address, value }; | |
79 | return stv06xx_write_sensor_bytes(sd, data, 1); | |
80 | } | |
81 | } | |
82 | ||
83 | static int stv06xx_write_sensor_finish(struct sd *sd) | |
84 | { | |
85 | int err = 0; | |
86 | ||
8668d504 | 87 | if (sd->bridge == BRIDGE_STV610) { |
4c98834a EA |
88 | struct usb_device *udev = sd->gspca_dev.dev; |
89 | __u8 *buf = sd->gspca_dev.usb_buf; | |
90 | ||
4c98834a EA |
91 | buf[0] = 0; |
92 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | |
93 | 0x04, 0x40, 0x1704, 0, buf, 1, | |
94 | STV06XX_URB_MSG_TIMEOUT); | |
95 | } | |
96 | ||
97 | return (err < 0) ? err : 0; | |
98 | } | |
99 | ||
100 | int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len) | |
101 | { | |
102 | int err, i, j; | |
c93396e1 | 103 | struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; |
4c98834a EA |
104 | struct usb_device *udev = sd->gspca_dev.dev; |
105 | __u8 *buf = sd->gspca_dev.usb_buf; | |
106 | ||
37d5efb0 JP |
107 | gspca_dbg(gspca_dev, D_CONF, "I2C: Command buffer contains %d entries\n", |
108 | len); | |
4c98834a EA |
109 | for (i = 0; i < len;) { |
110 | /* Build the command buffer */ | |
111 | memset(buf, 0, I2C_BUFFER_LENGTH); | |
112 | for (j = 0; j < I2C_MAX_BYTES && i < len; j++, i++) { | |
113 | buf[j] = data[2*i]; | |
114 | buf[0x10 + j] = data[2*i+1]; | |
37d5efb0 JP |
115 | gspca_dbg(gspca_dev, D_CONF, "I2C: Writing 0x%02x to reg 0x%02x\n", |
116 | data[2*i+1], data[2*i]); | |
4c98834a EA |
117 | } |
118 | buf[0x20] = sd->sensor->i2c_addr; | |
119 | buf[0x21] = j - 1; /* Number of commands to send - 1 */ | |
120 | buf[0x22] = I2C_WRITE_CMD; | |
121 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | |
122 | 0x04, 0x40, 0x0400, 0, buf, | |
123 | I2C_BUFFER_LENGTH, | |
124 | STV06XX_URB_MSG_TIMEOUT); | |
a8ca20b2 EA |
125 | if (err < 0) |
126 | return err; | |
272ece5e MCC |
127 | } |
128 | return stv06xx_write_sensor_finish(sd); | |
4c98834a EA |
129 | } |
130 | ||
131 | int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len) | |
132 | { | |
133 | int err, i, j; | |
c93396e1 | 134 | struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; |
4c98834a EA |
135 | struct usb_device *udev = sd->gspca_dev.dev; |
136 | __u8 *buf = sd->gspca_dev.usb_buf; | |
137 | ||
37d5efb0 JP |
138 | gspca_dbg(gspca_dev, D_CONF, "I2C: Command buffer contains %d entries\n", |
139 | len); | |
4c98834a EA |
140 | |
141 | for (i = 0; i < len;) { | |
142 | /* Build the command buffer */ | |
143 | memset(buf, 0, I2C_BUFFER_LENGTH); | |
144 | for (j = 0; j < I2C_MAX_WORDS && i < len; j++, i++) { | |
145 | buf[j] = data[2*i]; | |
146 | buf[0x10 + j * 2] = data[2*i+1]; | |
147 | buf[0x10 + j * 2 + 1] = data[2*i+1] >> 8; | |
37d5efb0 JP |
148 | gspca_dbg(gspca_dev, D_CONF, "I2C: Writing 0x%04x to reg 0x%02x\n", |
149 | data[2*i+1], data[2*i]); | |
4c98834a EA |
150 | } |
151 | buf[0x20] = sd->sensor->i2c_addr; | |
152 | buf[0x21] = j - 1; /* Number of commands to send - 1 */ | |
153 | buf[0x22] = I2C_WRITE_CMD; | |
154 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | |
155 | 0x04, 0x40, 0x0400, 0, buf, | |
156 | I2C_BUFFER_LENGTH, | |
157 | STV06XX_URB_MSG_TIMEOUT); | |
158 | if (err < 0) | |
159 | return err; | |
160 | } | |
161 | return stv06xx_write_sensor_finish(sd); | |
162 | } | |
163 | ||
164 | int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value) | |
165 | { | |
166 | int err; | |
c93396e1 | 167 | struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; |
4c98834a EA |
168 | struct usb_device *udev = sd->gspca_dev.dev; |
169 | __u8 *buf = sd->gspca_dev.usb_buf; | |
170 | ||
171 | err = stv06xx_write_bridge(sd, STV_I2C_FLUSH, sd->sensor->i2c_flush); | |
172 | if (err < 0) | |
173 | return err; | |
174 | ||
175 | /* Clear mem */ | |
176 | memset(buf, 0, I2C_BUFFER_LENGTH); | |
177 | ||
178 | buf[0] = address; | |
179 | buf[0x20] = sd->sensor->i2c_addr; | |
180 | buf[0x21] = 0; | |
181 | ||
182 | /* Read I2C register */ | |
183 | buf[0x22] = I2C_READ_CMD; | |
184 | ||
185 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | |
186 | 0x04, 0x40, 0x1400, 0, buf, I2C_BUFFER_LENGTH, | |
187 | STV06XX_URB_MSG_TIMEOUT); | |
188 | if (err < 0) { | |
133a9fe9 | 189 | pr_err("I2C: Read error writing address: %d\n", err); |
4c98834a EA |
190 | return err; |
191 | } | |
192 | ||
193 | err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | |
194 | 0x04, 0xc0, 0x1410, 0, buf, sd->sensor->i2c_len, | |
195 | STV06XX_URB_MSG_TIMEOUT); | |
196 | if (sd->sensor->i2c_len == 2) | |
197 | *value = buf[0] | (buf[1] << 8); | |
198 | else | |
199 | *value = buf[0]; | |
200 | ||
37d5efb0 JP |
201 | gspca_dbg(gspca_dev, D_CONF, "I2C: Read 0x%x from address 0x%x, status: %d\n", |
202 | *value, address, err); | |
4c98834a EA |
203 | |
204 | return (err < 0) ? err : 0; | |
205 | } | |
206 | ||
207 | /* Dumps all bridge registers */ | |
208 | static void stv06xx_dump_bridge(struct sd *sd) | |
209 | { | |
210 | int i; | |
211 | u8 data, buf; | |
212 | ||
133a9fe9 | 213 | pr_info("Dumping all stv06xx bridge registers\n"); |
4c98834a EA |
214 | for (i = 0x1400; i < 0x160f; i++) { |
215 | stv06xx_read_bridge(sd, i, &data); | |
216 | ||
133a9fe9 | 217 | pr_info("Read 0x%x from address 0x%x\n", data, i); |
4c98834a EA |
218 | } |
219 | ||
133a9fe9 | 220 | pr_info("Testing stv06xx bridge registers for writability\n"); |
4c98834a EA |
221 | for (i = 0x1400; i < 0x160f; i++) { |
222 | stv06xx_read_bridge(sd, i, &data); | |
223 | buf = data; | |
224 | ||
225 | stv06xx_write_bridge(sd, i, 0xff); | |
226 | stv06xx_read_bridge(sd, i, &data); | |
227 | if (data == 0xff) | |
133a9fe9 | 228 | pr_info("Register 0x%x is read/write\n", i); |
4c98834a | 229 | else if (data != buf) |
133a9fe9 JP |
230 | pr_info("Register 0x%x is read/write, but only partially\n", |
231 | i); | |
4c98834a | 232 | else |
133a9fe9 | 233 | pr_info("Register 0x%x is read-only\n", i); |
4c98834a EA |
234 | |
235 | stv06xx_write_bridge(sd, i, buf); | |
236 | } | |
237 | } | |
238 | ||
239 | /* this function is called at probe and resume time */ | |
240 | static int stv06xx_init(struct gspca_dev *gspca_dev) | |
241 | { | |
242 | struct sd *sd = (struct sd *) gspca_dev; | |
243 | int err; | |
244 | ||
37d5efb0 | 245 | gspca_dbg(gspca_dev, D_PROBE, "Initializing camera\n"); |
4c98834a EA |
246 | |
247 | /* Let the usb init settle for a bit | |
248 | before performing the initialization */ | |
249 | msleep(250); | |
250 | ||
251 | err = sd->sensor->init(sd); | |
252 | ||
8668d504 | 253 | if (dump_sensor && sd->sensor->dump) |
4c98834a EA |
254 | sd->sensor->dump(sd); |
255 | ||
256 | return (err < 0) ? err : 0; | |
257 | } | |
258 | ||
dec9c514 HV |
259 | /* this function is called at probe time */ |
260 | static int stv06xx_init_controls(struct gspca_dev *gspca_dev) | |
261 | { | |
262 | struct sd *sd = (struct sd *) gspca_dev; | |
263 | ||
37d5efb0 | 264 | gspca_dbg(gspca_dev, D_PROBE, "Initializing controls\n"); |
dec9c514 | 265 | |
a8a47860 | 266 | gspca_dev->vdev.ctrl_handler = &gspca_dev->ctrl_handler; |
dec9c514 HV |
267 | return sd->sensor->init_controls(sd); |
268 | } | |
269 | ||
4c98834a EA |
270 | /* Start the camera */ |
271 | static int stv06xx_start(struct gspca_dev *gspca_dev) | |
272 | { | |
273 | struct sd *sd = (struct sd *) gspca_dev; | |
c0b33bdc HG |
274 | struct usb_host_interface *alt; |
275 | struct usb_interface *intf; | |
276 | int err, packet_size; | |
277 | ||
278 | intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); | |
279 | alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); | |
280 | if (!alt) { | |
52173c5f | 281 | gspca_err(gspca_dev, "Couldn't get altsetting\n"); |
c0b33bdc HG |
282 | return -EIO; |
283 | } | |
284 | ||
285 | packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); | |
286 | err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size); | |
287 | if (err < 0) | |
288 | return err; | |
4c98834a EA |
289 | |
290 | /* Prepare the sensor for start */ | |
291 | err = sd->sensor->start(sd); | |
292 | if (err < 0) | |
293 | goto out; | |
294 | ||
295 | /* Start isochronous streaming */ | |
296 | err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 1); | |
297 | ||
298 | out: | |
299 | if (err < 0) | |
37d5efb0 | 300 | gspca_dbg(gspca_dev, D_STREAM, "Starting stream failed\n"); |
4c98834a | 301 | else |
37d5efb0 | 302 | gspca_dbg(gspca_dev, D_STREAM, "Started streaming\n"); |
4c98834a EA |
303 | |
304 | return (err < 0) ? err : 0; | |
305 | } | |
306 | ||
c0b33bdc HG |
307 | static int stv06xx_isoc_init(struct gspca_dev *gspca_dev) |
308 | { | |
309 | struct usb_host_interface *alt; | |
310 | struct sd *sd = (struct sd *) gspca_dev; | |
311 | ||
312 | /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ | |
5dae603d | 313 | alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; |
c0b33bdc HG |
314 | alt->endpoint[0].desc.wMaxPacketSize = |
315 | cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]); | |
316 | ||
317 | return 0; | |
318 | } | |
319 | ||
320 | static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev) | |
321 | { | |
322 | int ret, packet_size, min_packet_size; | |
323 | struct usb_host_interface *alt; | |
324 | struct sd *sd = (struct sd *) gspca_dev; | |
325 | ||
5dae603d | 326 | alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; |
c0b33bdc HG |
327 | packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); |
328 | min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode]; | |
329 | if (packet_size <= min_packet_size) | |
330 | return -EIO; | |
331 | ||
332 | packet_size -= 100; | |
333 | if (packet_size < min_packet_size) | |
334 | packet_size = min_packet_size; | |
335 | alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size); | |
336 | ||
337 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); | |
338 | if (ret < 0) | |
52173c5f | 339 | gspca_err(gspca_dev, "set alt 1 err %d\n", ret); |
c0b33bdc HG |
340 | |
341 | return ret; | |
342 | } | |
343 | ||
4c98834a EA |
344 | static void stv06xx_stopN(struct gspca_dev *gspca_dev) |
345 | { | |
346 | int err; | |
347 | struct sd *sd = (struct sd *) gspca_dev; | |
348 | ||
349 | /* stop ISO-streaming */ | |
350 | err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 0); | |
351 | if (err < 0) | |
352 | goto out; | |
353 | ||
354 | err = sd->sensor->stop(sd); | |
4c98834a EA |
355 | |
356 | out: | |
357 | if (err < 0) | |
37d5efb0 | 358 | gspca_dbg(gspca_dev, D_STREAM, "Failed to stop stream\n"); |
4c98834a | 359 | else |
37d5efb0 | 360 | gspca_dbg(gspca_dev, D_STREAM, "Stopped streaming\n"); |
4c98834a EA |
361 | } |
362 | ||
363 | /* | |
364 | * Analyse an USB packet of the data stream and store it appropriately. | |
365 | * Each packet contains an integral number of chunks. Each chunk has | |
366 | * 2-bytes identification, followed by 2-bytes that describe the chunk | |
367 | * length. Known/guessed chunk identifications are: | |
368 | * 8001/8005/C001/C005 - Begin new frame | |
369 | * 8002/8006/C002/C006 - End frame | |
370 | * 0200/4200 - Contains actual image data, bayer or compressed | |
371 | * 0005 - 11 bytes of unknown data | |
372 | * 0100 - 2 bytes of unknown data | |
373 | * The 0005 and 0100 chunks seem to appear only in compressed stream. | |
374 | */ | |
375 | static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, | |
76dd272b | 376 | u8 *data, /* isoc packet */ |
4c98834a EA |
377 | int len) /* iso packet length */ |
378 | { | |
8668d504 HG |
379 | struct sd *sd = (struct sd *) gspca_dev; |
380 | ||
37d5efb0 | 381 | gspca_dbg(gspca_dev, D_PACK, "Packet of length %d arrived\n", len); |
4c98834a EA |
382 | |
383 | /* A packet may contain several frames | |
384 | loop until the whole packet is reached */ | |
385 | while (len) { | |
386 | int id, chunk_len; | |
387 | ||
388 | if (len < 4) { | |
37d5efb0 | 389 | gspca_dbg(gspca_dev, D_PACK, "Packet is smaller than 4 bytes\n"); |
4c98834a EA |
390 | return; |
391 | } | |
392 | ||
393 | /* Capture the id */ | |
394 | id = (data[0] << 8) | data[1]; | |
395 | ||
396 | /* Capture the chunk length */ | |
397 | chunk_len = (data[2] << 8) | data[3]; | |
37d5efb0 JP |
398 | gspca_dbg(gspca_dev, D_PACK, "Chunk id: %x, length: %d\n", |
399 | id, chunk_len); | |
4c98834a EA |
400 | |
401 | data += 4; | |
402 | len -= 4; | |
403 | ||
404 | if (len < chunk_len) { | |
52173c5f | 405 | gspca_err(gspca_dev, "URB packet length is smaller than the specified chunk length\n"); |
8668d504 | 406 | gspca_dev->last_packet_type = DISCARD_PACKET; |
4c98834a EA |
407 | return; |
408 | } | |
409 | ||
8668d504 | 410 | /* First byte seem to be 02=data 2nd byte is unknown??? */ |
1d00d6c1 | 411 | if (sd->bridge == BRIDGE_ST6422 && (id & 0xff00) == 0x0200) |
8668d504 HG |
412 | goto frame_data; |
413 | ||
4c98834a EA |
414 | switch (id) { |
415 | case 0x0200: | |
416 | case 0x4200: | |
8668d504 | 417 | frame_data: |
37d5efb0 | 418 | gspca_dbg(gspca_dev, D_PACK, "Frame data packet detected\n"); |
4c98834a | 419 | |
8668d504 HG |
420 | if (sd->to_skip) { |
421 | int skip = (sd->to_skip < chunk_len) ? | |
422 | sd->to_skip : chunk_len; | |
423 | data += skip; | |
424 | len -= skip; | |
425 | chunk_len -= skip; | |
426 | sd->to_skip -= skip; | |
427 | } | |
428 | ||
76dd272b | 429 | gspca_frame_add(gspca_dev, INTER_PACKET, |
4c98834a EA |
430 | data, chunk_len); |
431 | break; | |
432 | ||
433 | case 0x8001: | |
434 | case 0x8005: | |
435 | case 0xc001: | |
436 | case 0xc005: | |
37d5efb0 | 437 | gspca_dbg(gspca_dev, D_PACK, "Starting new frame\n"); |
4c98834a EA |
438 | |
439 | /* Create a new frame, chunk length should be zero */ | |
440 | gspca_frame_add(gspca_dev, FIRST_PACKET, | |
76dd272b | 441 | NULL, 0); |
4c98834a | 442 | |
8668d504 | 443 | if (sd->bridge == BRIDGE_ST6422) |
1966bc2a | 444 | sd->to_skip = gspca_dev->pixfmt.width * 4; |
8668d504 | 445 | |
4c98834a | 446 | if (chunk_len) |
52173c5f | 447 | gspca_err(gspca_dev, "Chunk length is non-zero on a SOF\n"); |
4c98834a EA |
448 | break; |
449 | ||
450 | case 0x8002: | |
451 | case 0x8006: | |
452 | case 0xc002: | |
37d5efb0 | 453 | gspca_dbg(gspca_dev, D_PACK, "End of frame detected\n"); |
4c98834a EA |
454 | |
455 | /* Complete the last frame (if any) */ | |
76dd272b JFM |
456 | gspca_frame_add(gspca_dev, LAST_PACKET, |
457 | NULL, 0); | |
4c98834a EA |
458 | |
459 | if (chunk_len) | |
52173c5f | 460 | gspca_err(gspca_dev, "Chunk length is non-zero on a EOF\n"); |
4c98834a EA |
461 | break; |
462 | ||
463 | case 0x0005: | |
37d5efb0 | 464 | gspca_dbg(gspca_dev, D_PACK, "Chunk 0x005 detected\n"); |
4c98834a EA |
465 | /* Unknown chunk with 11 bytes of data, |
466 | occurs just before end of each frame | |
467 | in compressed mode */ | |
468 | break; | |
469 | ||
470 | case 0x0100: | |
37d5efb0 | 471 | gspca_dbg(gspca_dev, D_PACK, "Chunk 0x0100 detected\n"); |
4c98834a EA |
472 | /* Unknown chunk with 2 bytes of data, |
473 | occurs 2-3 times per USB interrupt */ | |
474 | break; | |
8668d504 | 475 | case 0x42ff: |
37d5efb0 | 476 | gspca_dbg(gspca_dev, D_PACK, "Chunk 0x42ff detected\n"); |
8668d504 HG |
477 | /* Special chunk seen sometimes on the ST6422 */ |
478 | break; | |
4c98834a | 479 | default: |
37d5efb0 JP |
480 | gspca_dbg(gspca_dev, D_PACK, "Unknown chunk 0x%04x detected\n", |
481 | id); | |
4c98834a EA |
482 | /* Unknown chunk */ |
483 | } | |
484 | data += chunk_len; | |
485 | len -= chunk_len; | |
486 | } | |
487 | } | |
488 | ||
00ddb707 | 489 | #if IS_ENABLED(CONFIG_INPUT) |
0158e98f HG |
490 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, |
491 | u8 *data, /* interrupt packet data */ | |
492 | int len) /* interrupt packet length */ | |
493 | { | |
494 | int ret = -EINVAL; | |
495 | ||
13e6c9f4 | 496 | if (len == 1 && (data[0] == 0x80 || data[0] == 0x10)) { |
0158e98f HG |
497 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); |
498 | input_sync(gspca_dev->input_dev); | |
499 | ret = 0; | |
500 | } | |
501 | ||
13e6c9f4 | 502 | if (len == 1 && (data[0] == 0x88 || data[0] == 0x11)) { |
0158e98f HG |
503 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); |
504 | input_sync(gspca_dev->input_dev); | |
505 | ret = 0; | |
506 | } | |
507 | ||
508 | return ret; | |
509 | } | |
510 | #endif | |
511 | ||
4c98834a EA |
512 | static int stv06xx_config(struct gspca_dev *gspca_dev, |
513 | const struct usb_device_id *id); | |
514 | ||
515 | /* sub-driver description */ | |
516 | static const struct sd_desc sd_desc = { | |
517 | .name = MODULE_NAME, | |
518 | .config = stv06xx_config, | |
519 | .init = stv06xx_init, | |
dec9c514 | 520 | .init_controls = stv06xx_init_controls, |
4c98834a EA |
521 | .start = stv06xx_start, |
522 | .stopN = stv06xx_stopN, | |
0158e98f | 523 | .pkt_scan = stv06xx_pkt_scan, |
c0b33bdc HG |
524 | .isoc_init = stv06xx_isoc_init, |
525 | .isoc_nego = stv06xx_isoc_nego, | |
00ddb707 | 526 | #if IS_ENABLED(CONFIG_INPUT) |
0158e98f HG |
527 | .int_pkt_scan = sd_int_pkt_scan, |
528 | #endif | |
4c98834a EA |
529 | }; |
530 | ||
531 | /* This function is called at probe time */ | |
532 | static int stv06xx_config(struct gspca_dev *gspca_dev, | |
533 | const struct usb_device_id *id) | |
534 | { | |
535 | struct sd *sd = (struct sd *) gspca_dev; | |
4c98834a | 536 | |
37d5efb0 | 537 | gspca_dbg(gspca_dev, D_PROBE, "Configuring camera\n"); |
4c98834a | 538 | |
8668d504 | 539 | sd->bridge = id->driver_info; |
d67a1ada | 540 | gspca_dev->sd_desc = &sd_desc; |
4c98834a EA |
541 | |
542 | if (dump_bridge) | |
543 | stv06xx_dump_bridge(sd); | |
544 | ||
8668d504 HG |
545 | sd->sensor = &stv06xx_sensor_st6422; |
546 | if (!sd->sensor->probe(sd)) | |
547 | return 0; | |
548 | ||
4c98834a EA |
549 | sd->sensor = &stv06xx_sensor_vv6410; |
550 | if (!sd->sensor->probe(sd)) | |
551 | return 0; | |
552 | ||
553 | sd->sensor = &stv06xx_sensor_hdcs1x00; | |
554 | if (!sd->sensor->probe(sd)) | |
555 | return 0; | |
556 | ||
557 | sd->sensor = &stv06xx_sensor_hdcs1020; | |
558 | if (!sd->sensor->probe(sd)) | |
559 | return 0; | |
560 | ||
561 | sd->sensor = &stv06xx_sensor_pb0100; | |
562 | if (!sd->sensor->probe(sd)) | |
563 | return 0; | |
564 | ||
565 | sd->sensor = NULL; | |
566 | return -ENODEV; | |
567 | } | |
568 | ||
569 | ||
570 | ||
571 | /* -- module initialisation -- */ | |
95c967c1 | 572 | static const struct usb_device_id device_table[] = { |
6e6a8b5a | 573 | {USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 }, /* QuickCam Express */ |
b2fdd0ee MCC |
574 | {USB_DEVICE(0x046d, 0x0850), .driver_info = BRIDGE_STV610 }, /* LEGO cam / QuickCam Web */ |
575 | {USB_DEVICE(0x046d, 0x0870), .driver_info = BRIDGE_STV602 }, /* Dexxa WebCam USB */ | |
576 | {USB_DEVICE(0x046D, 0x08F0), .driver_info = BRIDGE_ST6422 }, /* QuickCam Messenger */ | |
577 | {USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 }, /* QuickCam Communicate */ | |
578 | {USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 }, /* QuickCam Messenger (new) */ | |
4c98834a EA |
579 | {} |
580 | }; | |
581 | MODULE_DEVICE_TABLE(usb, device_table); | |
582 | ||
583 | /* -- device connect -- */ | |
584 | static int sd_probe(struct usb_interface *intf, | |
585 | const struct usb_device_id *id) | |
586 | { | |
4c98834a EA |
587 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), |
588 | THIS_MODULE); | |
589 | } | |
590 | ||
8a787b40 | 591 | static void sd_disconnect(struct usb_interface *intf) |
4c98834a EA |
592 | { |
593 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | |
594 | struct sd *sd = (struct sd *) gspca_dev; | |
dec9c514 | 595 | void *priv = sd->sensor_priv; |
37d5efb0 | 596 | gspca_dbg(gspca_dev, D_PROBE, "Disconnecting the stv06xx device\n"); |
4c98834a | 597 | |
dec9c514 | 598 | sd->sensor = NULL; |
4c98834a | 599 | gspca_disconnect(intf); |
dec9c514 | 600 | kfree(priv); |
4c98834a EA |
601 | } |
602 | ||
603 | static struct usb_driver sd_driver = { | |
604 | .name = MODULE_NAME, | |
605 | .id_table = device_table, | |
606 | .probe = sd_probe, | |
607 | .disconnect = sd_disconnect, | |
608 | #ifdef CONFIG_PM | |
609 | .suspend = gspca_suspend, | |
610 | .resume = gspca_resume, | |
dec9c514 | 611 | .reset_resume = gspca_resume, |
4c98834a EA |
612 | #endif |
613 | }; | |
614 | ||
ecb3b2b3 | 615 | module_usb_driver(sd_driver); |
4c98834a EA |
616 | |
617 | module_param(dump_bridge, bool, S_IRUGO | S_IWUSR); | |
618 | MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup"); | |
619 | ||
620 | module_param(dump_sensor, bool, S_IRUGO | S_IWUSR); | |
621 | MODULE_PARM_DESC(dump_sensor, "Dumps all sensor registers at startup"); |