1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * GSPCA Endpoints (formerly known as AOX) se401 USB Camera sub Driver |
4 | * |
5 | * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com> |
6 | * |
7 | * Based on the v4l1 se401 driver which is: |
8 | * |
9 | * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) |
10 | */ |
11 | |
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
13 | |
14 | #define MODULE_NAME "se401" |
15 | |
16 | #define BULK_SIZE 4096 |
17 | #define PACKET_SIZE 1024 |
18 | #define READ_REQ_SIZE 64 |
19 | #define MAX_MODES ((READ_REQ_SIZE - 6) / 4) |
20 | /* The se401 compression algorithm uses a fixed quant factor, which |
21 | can be configured by setting the high nibble of the SE401_OPERATINGMODE |
22 | feature. This needs to exactly match what is in libv4l! */ |
23 | #define SE401_QUANT_FACT 8 |
24 | |
25 | #include <linux/input.h> |
26 | #include <linux/slab.h> |
27 | #include "gspca.h" |
28 | #include "se401.h" |
29 | |
30 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>" ); |
31 | MODULE_DESCRIPTION("Endpoints se401" ); |
32 | MODULE_LICENSE("GPL" ); |
33 | |
34 | /* exposure change state machine states */ |
35 | enum { |
36 | EXPO_CHANGED, |
37 | EXPO_DROP_FRAME, |
38 | EXPO_NO_CHANGE, |
39 | }; |
40 | |
41 | /* specific webcam descriptor */ |
42 | struct sd { |
43 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
44 | struct { /* exposure/freq control cluster */ |
45 | struct v4l2_ctrl *exposure; |
46 | struct v4l2_ctrl *freq; |
47 | }; |
48 | bool has_brightness; |
49 | struct v4l2_pix_format fmts[MAX_MODES]; |
50 | int pixels_read; |
51 | int packet_read; |
52 | u8 packet[PACKET_SIZE]; |
53 | u8 restart_stream; |
54 | u8 button_state; |
55 | u8 resetlevel; |
56 | u8 resetlevel_frame_count; |
57 | int resetlevel_adjust_dir; |
58 | int expo_change_state; |
59 | }; |
60 | |
61 | |
62 | static void se401_write_req(struct gspca_dev *gspca_dev, u16 req, u16 value, |
63 | int silent) |
64 | { |
65 | int err; |
66 | |
67 | if (gspca_dev->usb_err < 0) |
68 | return; |
69 | |
70 | err = usb_control_msg(dev: gspca_dev->dev, |
71 | usb_sndctrlpipe(gspca_dev->dev, 0), request: req, |
72 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
73 | value, index: 0, NULL, size: 0, timeout: 1000); |
74 | if (err < 0) { |
75 | if (!silent) |
76 | pr_err("write req failed req %#04x val %#04x error %d\n" , |
77 | req, value, err); |
78 | gspca_dev->usb_err = err; |
79 | } |
80 | } |
81 | |
82 | static void se401_read_req(struct gspca_dev *gspca_dev, u16 req, int silent) |
83 | { |
84 | int err; |
85 | |
86 | if (gspca_dev->usb_err < 0) |
87 | return; |
88 | |
89 | if (USB_BUF_SZ < READ_REQ_SIZE) { |
90 | pr_err("USB_BUF_SZ too small!!\n" ); |
91 | gspca_dev->usb_err = -ENOBUFS; |
92 | return; |
93 | } |
94 | |
95 | err = usb_control_msg(dev: gspca_dev->dev, |
96 | usb_rcvctrlpipe(gspca_dev->dev, 0), request: req, |
97 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
98 | value: 0, index: 0, data: gspca_dev->usb_buf, READ_REQ_SIZE, timeout: 1000); |
99 | if (err < 0) { |
100 | if (!silent) |
101 | pr_err("read req failed req %#04x error %d\n" , |
102 | req, err); |
103 | gspca_dev->usb_err = err; |
104 | /* |
105 | * Make sure the buffer is zeroed to avoid uninitialized |
106 | * values. |
107 | */ |
108 | memset(gspca_dev->usb_buf, 0, READ_REQ_SIZE); |
109 | } |
110 | } |
111 | |
112 | static void se401_set_feature(struct gspca_dev *gspca_dev, |
113 | u16 selector, u16 param) |
114 | { |
115 | int err; |
116 | |
117 | if (gspca_dev->usb_err < 0) |
118 | return; |
119 | |
120 | err = usb_control_msg(dev: gspca_dev->dev, |
121 | usb_sndctrlpipe(gspca_dev->dev, 0), |
122 | SE401_REQ_SET_EXT_FEATURE, |
123 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
124 | value: param, index: selector, NULL, size: 0, timeout: 1000); |
125 | if (err < 0) { |
126 | pr_err("set feature failed sel %#04x param %#04x error %d\n" , |
127 | selector, param, err); |
128 | gspca_dev->usb_err = err; |
129 | } |
130 | } |
131 | |
132 | static int se401_get_feature(struct gspca_dev *gspca_dev, u16 selector) |
133 | { |
134 | int err; |
135 | |
136 | if (gspca_dev->usb_err < 0) |
137 | return gspca_dev->usb_err; |
138 | |
139 | if (USB_BUF_SZ < 2) { |
140 | pr_err("USB_BUF_SZ too small!!\n" ); |
141 | gspca_dev->usb_err = -ENOBUFS; |
142 | return gspca_dev->usb_err; |
143 | } |
144 | |
145 | err = usb_control_msg(dev: gspca_dev->dev, |
146 | usb_rcvctrlpipe(gspca_dev->dev, 0), |
147 | SE401_REQ_GET_EXT_FEATURE, |
148 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
149 | value: 0, index: selector, data: gspca_dev->usb_buf, size: 2, timeout: 1000); |
150 | if (err < 0) { |
151 | pr_err("get feature failed sel %#04x error %d\n" , |
152 | selector, err); |
153 | gspca_dev->usb_err = err; |
154 | return err; |
155 | } |
156 | return gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8); |
157 | } |
158 | |
159 | static void setbrightness(struct gspca_dev *gspca_dev, s32 val) |
160 | { |
161 | /* HDG: this does not seem to do anything on my cam */ |
162 | se401_write_req(gspca_dev, SE401_REQ_SET_BRT, value: val, silent: 0); |
163 | } |
164 | |
165 | static void setgain(struct gspca_dev *gspca_dev, s32 val) |
166 | { |
167 | u16 gain = 63 - val; |
168 | |
169 | /* red color gain */ |
170 | se401_set_feature(gspca_dev, HV7131_REG_ARCG, param: gain); |
171 | /* green color gain */ |
172 | se401_set_feature(gspca_dev, HV7131_REG_AGCG, param: gain); |
173 | /* blue color gain */ |
174 | se401_set_feature(gspca_dev, HV7131_REG_ABCG, param: gain); |
175 | } |
176 | |
177 | static void setexposure(struct gspca_dev *gspca_dev, s32 val, s32 freq) |
178 | { |
179 | struct sd *sd = (struct sd *) gspca_dev; |
180 | int integration = val << 6; |
181 | u8 expose_h, expose_m, expose_l; |
182 | |
183 | /* Do this before the set_feature calls, for proper timing wrt |
184 | the interrupt driven pkt_scan. Note we may still race but that |
185 | is not a big issue, the expo change state machine is merely for |
186 | avoiding underexposed frames getting send out, if one sneaks |
187 | through so be it */ |
188 | sd->expo_change_state = EXPO_CHANGED; |
189 | |
190 | if (freq == V4L2_CID_POWER_LINE_FREQUENCY_50HZ) |
191 | integration = integration - integration % 106667; |
192 | if (freq == V4L2_CID_POWER_LINE_FREQUENCY_60HZ) |
193 | integration = integration - integration % 88889; |
194 | |
195 | expose_h = (integration >> 16); |
196 | expose_m = (integration >> 8); |
197 | expose_l = integration; |
198 | |
199 | /* integration time low */ |
200 | se401_set_feature(gspca_dev, HV7131_REG_TITL, param: expose_l); |
201 | /* integration time mid */ |
202 | se401_set_feature(gspca_dev, HV7131_REG_TITM, param: expose_m); |
203 | /* integration time high */ |
204 | se401_set_feature(gspca_dev, HV7131_REG_TITU, param: expose_h); |
205 | } |
206 | |
207 | static int sd_config(struct gspca_dev *gspca_dev, |
208 | const struct usb_device_id *id) |
209 | { |
210 | struct sd *sd = (struct sd *)gspca_dev; |
211 | struct cam *cam = &gspca_dev->cam; |
212 | u8 *cd = gspca_dev->usb_buf; |
213 | int i, j, n; |
214 | int widths[MAX_MODES], heights[MAX_MODES]; |
215 | |
216 | /* Read the camera descriptor */ |
217 | se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, silent: 1); |
218 | if (gspca_dev->usb_err) { |
219 | /* Sometimes after being idle for a while the se401 won't |
220 | respond and needs a good kicking */ |
221 | usb_reset_device(dev: gspca_dev->dev); |
222 | gspca_dev->usb_err = 0; |
223 | se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, silent: 0); |
224 | } |
225 | |
226 | /* Some cameras start with their LED on */ |
227 | se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, value: 0, silent: 0); |
228 | if (gspca_dev->usb_err) |
229 | return gspca_dev->usb_err; |
230 | |
231 | if (cd[1] != 0x41) { |
232 | pr_err("Wrong descriptor type\n" ); |
233 | return -ENODEV; |
234 | } |
235 | |
236 | if (!(cd[2] & SE401_FORMAT_BAYER)) { |
237 | pr_err("Bayer format not supported!\n" ); |
238 | return -ENODEV; |
239 | } |
240 | |
241 | if (cd[3]) |
242 | pr_info("ExtraFeatures: %d\n" , cd[3]); |
243 | |
244 | n = cd[4] | (cd[5] << 8); |
245 | if (n > MAX_MODES) { |
246 | pr_err("Too many frame sizes\n" ); |
247 | return -ENODEV; |
248 | } |
249 | |
250 | for (i = 0; i < n ; i++) { |
251 | widths[i] = cd[6 + i * 4 + 0] | (cd[6 + i * 4 + 1] << 8); |
252 | heights[i] = cd[6 + i * 4 + 2] | (cd[6 + i * 4 + 3] << 8); |
253 | } |
254 | |
255 | for (i = 0; i < n ; i++) { |
256 | sd->fmts[i].width = widths[i]; |
257 | sd->fmts[i].height = heights[i]; |
258 | sd->fmts[i].field = V4L2_FIELD_NONE; |
259 | sd->fmts[i].colorspace = V4L2_COLORSPACE_SRGB; |
260 | sd->fmts[i].priv = 1; |
261 | |
262 | /* janggu compression only works for 1/4th or 1/16th res */ |
263 | for (j = 0; j < n; j++) { |
264 | if (widths[j] / 2 == widths[i] && |
265 | heights[j] / 2 == heights[i]) { |
266 | sd->fmts[i].priv = 2; |
267 | break; |
268 | } |
269 | } |
270 | /* 1/16th if available too is better then 1/4th, because |
271 | we then use a larger area of the sensor */ |
272 | for (j = 0; j < n; j++) { |
273 | if (widths[j] / 4 == widths[i] && |
274 | heights[j] / 4 == heights[i]) { |
275 | sd->fmts[i].priv = 4; |
276 | break; |
277 | } |
278 | } |
279 | |
280 | if (sd->fmts[i].priv == 1) { |
281 | /* Not a 1/4th or 1/16th res, use bayer */ |
282 | sd->fmts[i].pixelformat = V4L2_PIX_FMT_SBGGR8; |
283 | sd->fmts[i].bytesperline = widths[i]; |
284 | sd->fmts[i].sizeimage = widths[i] * heights[i]; |
285 | pr_info("Frame size: %dx%d bayer\n" , |
286 | widths[i], heights[i]); |
287 | } else { |
288 | /* Found a match use janggu compression */ |
289 | sd->fmts[i].pixelformat = V4L2_PIX_FMT_SE401; |
290 | sd->fmts[i].bytesperline = 0; |
291 | sd->fmts[i].sizeimage = widths[i] * heights[i] * 3; |
292 | pr_info("Frame size: %dx%d 1/%dth janggu\n" , |
293 | widths[i], heights[i], |
294 | sd->fmts[i].priv * sd->fmts[i].priv); |
295 | } |
296 | } |
297 | |
298 | cam->cam_mode = sd->fmts; |
299 | cam->nmodes = n; |
300 | cam->bulk = 1; |
301 | cam->bulk_size = BULK_SIZE; |
302 | cam->bulk_nurbs = 4; |
303 | sd->resetlevel = 0x2d; /* Set initial resetlevel */ |
304 | |
305 | /* See if the camera supports brightness */ |
306 | se401_read_req(gspca_dev, SE401_REQ_GET_BRT, silent: 1); |
307 | sd->has_brightness = !!gspca_dev->usb_err; |
308 | gspca_dev->usb_err = 0; |
309 | |
310 | return 0; |
311 | } |
312 | |
313 | /* this function is called at probe and resume time */ |
314 | static int sd_init(struct gspca_dev *gspca_dev) |
315 | { |
316 | return 0; |
317 | } |
318 | |
319 | /* function called at start time before URB creation */ |
320 | static int sd_isoc_init(struct gspca_dev *gspca_dev) |
321 | { |
322 | gspca_dev->alt = 1; /* Ignore the bogus isoc alt settings */ |
323 | |
324 | return gspca_dev->usb_err; |
325 | } |
326 | |
327 | /* -- start the camera -- */ |
328 | static int sd_start(struct gspca_dev *gspca_dev) |
329 | { |
330 | struct sd *sd = (struct sd *)gspca_dev; |
331 | int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
332 | int mode = 0; |
333 | |
334 | se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, value: 1, silent: 1); |
335 | if (gspca_dev->usb_err) { |
336 | /* Sometimes after being idle for a while the se401 won't |
337 | respond and needs a good kicking */ |
338 | usb_reset_device(dev: gspca_dev->dev); |
339 | gspca_dev->usb_err = 0; |
340 | se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, value: 1, silent: 0); |
341 | } |
342 | se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, value: 1, silent: 0); |
343 | |
344 | se401_set_feature(gspca_dev, HV7131_REG_MODE_B, param: 0x05); |
345 | |
346 | /* set size + mode */ |
347 | se401_write_req(gspca_dev, SE401_REQ_SET_WIDTH, |
348 | value: gspca_dev->pixfmt.width * mult, silent: 0); |
349 | se401_write_req(gspca_dev, SE401_REQ_SET_HEIGHT, |
350 | value: gspca_dev->pixfmt.height * mult, silent: 0); |
351 | /* |
352 | * HDG: disabled this as it does not seem to do anything |
353 | * se401_write_req(gspca_dev, SE401_REQ_SET_OUTPUT_MODE, |
354 | * SE401_FORMAT_BAYER, 0); |
355 | */ |
356 | |
357 | switch (mult) { |
358 | case 1: /* Raw bayer */ |
359 | mode = 0x03; break; |
360 | case 2: /* 1/4th janggu */ |
361 | mode = SE401_QUANT_FACT << 4; break; |
362 | case 4: /* 1/16th janggu */ |
363 | mode = (SE401_QUANT_FACT << 4) | 0x02; break; |
364 | } |
365 | se401_set_feature(gspca_dev, SE401_OPERATINGMODE, param: mode); |
366 | |
367 | se401_set_feature(gspca_dev, HV7131_REG_ARLV, param: sd->resetlevel); |
368 | |
369 | sd->packet_read = 0; |
370 | sd->pixels_read = 0; |
371 | sd->restart_stream = 0; |
372 | sd->resetlevel_frame_count = 0; |
373 | sd->resetlevel_adjust_dir = 0; |
374 | sd->expo_change_state = EXPO_NO_CHANGE; |
375 | |
376 | se401_write_req(gspca_dev, SE401_REQ_START_CONTINUOUS_CAPTURE, value: 0, silent: 0); |
377 | |
378 | return gspca_dev->usb_err; |
379 | } |
380 | |
381 | static void sd_stopN(struct gspca_dev *gspca_dev) |
382 | { |
383 | se401_write_req(gspca_dev, SE401_REQ_STOP_CONTINUOUS_CAPTURE, value: 0, silent: 0); |
384 | se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, value: 0, silent: 0); |
385 | se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, value: 0, silent: 0); |
386 | } |
387 | |
388 | static void sd_dq_callback(struct gspca_dev *gspca_dev) |
389 | { |
390 | struct sd *sd = (struct sd *)gspca_dev; |
391 | unsigned int ahrc, alrc; |
392 | int oldreset, adjust_dir; |
393 | |
394 | /* Restart the stream if requested do so by pkt_scan */ |
395 | if (sd->restart_stream) { |
396 | sd_stopN(gspca_dev); |
397 | sd_start(gspca_dev); |
398 | sd->restart_stream = 0; |
399 | } |
400 | |
401 | /* Automatically adjust sensor reset level |
402 | Hyundai have some really nice docs about this and other sensor |
403 | related stuff on their homepage: www.hei.co.kr */ |
404 | sd->resetlevel_frame_count++; |
405 | if (sd->resetlevel_frame_count < 20) |
406 | return; |
407 | |
408 | /* For some reason this normally read-only register doesn't get reset |
409 | to zero after reading them just once... */ |
410 | se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH); |
411 | se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL); |
412 | se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH); |
413 | se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL); |
414 | ahrc = 256*se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH) + |
415 | se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL); |
416 | alrc = 256*se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH) + |
417 | se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL); |
418 | |
419 | /* Not an exact science, but it seems to work pretty well... */ |
420 | oldreset = sd->resetlevel; |
421 | if (alrc > 10) { |
422 | while (alrc >= 10 && sd->resetlevel < 63) { |
423 | sd->resetlevel++; |
424 | alrc /= 2; |
425 | } |
426 | } else if (ahrc > 20) { |
427 | while (ahrc >= 20 && sd->resetlevel > 0) { |
428 | sd->resetlevel--; |
429 | ahrc /= 2; |
430 | } |
431 | } |
432 | /* Detect ping-pong-ing and halve adjustment to avoid overshoot */ |
433 | if (sd->resetlevel > oldreset) |
434 | adjust_dir = 1; |
435 | else |
436 | adjust_dir = -1; |
437 | if (sd->resetlevel_adjust_dir && |
438 | sd->resetlevel_adjust_dir != adjust_dir) |
439 | sd->resetlevel = oldreset + (sd->resetlevel - oldreset) / 2; |
440 | |
441 | if (sd->resetlevel != oldreset) { |
442 | sd->resetlevel_adjust_dir = adjust_dir; |
443 | se401_set_feature(gspca_dev, HV7131_REG_ARLV, param: sd->resetlevel); |
444 | } |
445 | |
446 | sd->resetlevel_frame_count = 0; |
447 | } |
448 | |
449 | static void sd_complete_frame(struct gspca_dev *gspca_dev, u8 *data, int len) |
450 | { |
451 | struct sd *sd = (struct sd *)gspca_dev; |
452 | |
453 | switch (sd->expo_change_state) { |
454 | case EXPO_CHANGED: |
455 | /* The exposure was changed while this frame |
456 | was being send, so this frame is ok */ |
457 | sd->expo_change_state = EXPO_DROP_FRAME; |
458 | break; |
459 | case EXPO_DROP_FRAME: |
460 | /* The exposure was changed while this frame |
461 | was being captured, drop it! */ |
462 | gspca_dev->last_packet_type = DISCARD_PACKET; |
463 | sd->expo_change_state = EXPO_NO_CHANGE; |
464 | break; |
465 | case EXPO_NO_CHANGE: |
466 | break; |
467 | } |
468 | gspca_frame_add(gspca_dev, packet_type: LAST_PACKET, data, len); |
469 | } |
470 | |
471 | static void sd_pkt_scan_janggu(struct gspca_dev *gspca_dev, u8 *data, int len) |
472 | { |
473 | struct sd *sd = (struct sd *)gspca_dev; |
474 | int imagesize = gspca_dev->pixfmt.width * gspca_dev->pixfmt.height; |
475 | int i, plen, bits, pixels, info, count; |
476 | |
477 | if (sd->restart_stream) |
478 | return; |
479 | |
480 | /* Sometimes a 1024 bytes garbage bulk packet is send between frames */ |
481 | if (gspca_dev->last_packet_type == LAST_PACKET && len == 1024) { |
482 | gspca_dev->last_packet_type = DISCARD_PACKET; |
483 | return; |
484 | } |
485 | |
486 | i = 0; |
487 | while (i < len) { |
488 | /* Read header if not already be present from prev bulk pkt */ |
489 | if (sd->packet_read < 4) { |
490 | count = 4 - sd->packet_read; |
491 | if (count > len - i) |
492 | count = len - i; |
493 | memcpy(&sd->packet[sd->packet_read], &data[i], count); |
494 | sd->packet_read += count; |
495 | i += count; |
496 | if (sd->packet_read < 4) |
497 | break; |
498 | } |
499 | bits = sd->packet[3] + (sd->packet[2] << 8); |
500 | pixels = sd->packet[1] + ((sd->packet[0] & 0x3f) << 8); |
501 | info = (sd->packet[0] & 0xc0) >> 6; |
502 | plen = ((bits + 47) >> 4) << 1; |
503 | /* Sanity checks */ |
504 | if (plen > 1024) { |
505 | pr_err("invalid packet len %d restarting stream\n" , |
506 | plen); |
507 | goto error; |
508 | } |
509 | if (info == 3) { |
510 | pr_err("unknown frame info value restarting stream\n" ); |
511 | goto error; |
512 | } |
513 | |
514 | /* Read (remainder of) packet contents */ |
515 | count = plen - sd->packet_read; |
516 | if (count > len - i) |
517 | count = len - i; |
518 | memcpy(&sd->packet[sd->packet_read], &data[i], count); |
519 | sd->packet_read += count; |
520 | i += count; |
521 | if (sd->packet_read < plen) |
522 | break; |
523 | |
524 | sd->pixels_read += pixels; |
525 | sd->packet_read = 0; |
526 | |
527 | switch (info) { |
528 | case 0: /* Frame data */ |
529 | gspca_frame_add(gspca_dev, packet_type: INTER_PACKET, data: sd->packet, |
530 | len: plen); |
531 | break; |
532 | case 1: /* EOF */ |
533 | if (sd->pixels_read != imagesize) { |
534 | pr_err("frame size %d expected %d\n" , |
535 | sd->pixels_read, imagesize); |
536 | goto error; |
537 | } |
538 | sd_complete_frame(gspca_dev, data: sd->packet, len: plen); |
539 | return; /* Discard the rest of the bulk packet !! */ |
540 | case 2: /* SOF */ |
541 | gspca_frame_add(gspca_dev, packet_type: FIRST_PACKET, data: sd->packet, |
542 | len: plen); |
543 | sd->pixels_read = pixels; |
544 | break; |
545 | } |
546 | } |
547 | return; |
548 | |
549 | error: |
550 | sd->restart_stream = 1; |
551 | /* Give userspace a 0 bytes frame, so our dq callback gets |
552 | called and it can restart the stream */ |
553 | gspca_frame_add(gspca_dev, packet_type: FIRST_PACKET, NULL, len: 0); |
554 | gspca_frame_add(gspca_dev, packet_type: LAST_PACKET, NULL, len: 0); |
555 | } |
556 | |
557 | static void sd_pkt_scan_bayer(struct gspca_dev *gspca_dev, u8 *data, int len) |
558 | { |
559 | struct cam *cam = &gspca_dev->cam; |
560 | int imagesize = cam->cam_mode[gspca_dev->curr_mode].sizeimage; |
561 | |
562 | if (gspca_dev->image_len == 0) { |
563 | gspca_frame_add(gspca_dev, packet_type: FIRST_PACKET, data, len); |
564 | return; |
565 | } |
566 | |
567 | if (gspca_dev->image_len + len >= imagesize) { |
568 | sd_complete_frame(gspca_dev, data, len); |
569 | return; |
570 | } |
571 | |
572 | gspca_frame_add(gspca_dev, packet_type: INTER_PACKET, data, len); |
573 | } |
574 | |
575 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len) |
576 | { |
577 | int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
578 | |
579 | if (len == 0) |
580 | return; |
581 | |
582 | if (mult == 1) /* mult == 1 means raw bayer */ |
583 | sd_pkt_scan_bayer(gspca_dev, data, len); |
584 | else |
585 | sd_pkt_scan_janggu(gspca_dev, data, len); |
586 | } |
587 | |
588 | #if IS_ENABLED(CONFIG_INPUT) |
589 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len) |
590 | { |
591 | struct sd *sd = (struct sd *)gspca_dev; |
592 | u8 state; |
593 | |
594 | if (len != 2) |
595 | return -EINVAL; |
596 | |
597 | switch (data[0]) { |
598 | case 0: |
599 | case 1: |
600 | state = data[0]; |
601 | break; |
602 | default: |
603 | return -EINVAL; |
604 | } |
605 | if (sd->button_state != state) { |
606 | input_report_key(dev: gspca_dev->input_dev, KEY_CAMERA, value: state); |
607 | input_sync(dev: gspca_dev->input_dev); |
608 | sd->button_state = state; |
609 | } |
610 | |
611 | return 0; |
612 | } |
613 | #endif |
614 | |
615 | static int sd_s_ctrl(struct v4l2_ctrl *ctrl) |
616 | { |
617 | struct gspca_dev *gspca_dev = |
618 | container_of(ctrl->handler, struct gspca_dev, ctrl_handler); |
619 | struct sd *sd = (struct sd *)gspca_dev; |
620 | |
621 | gspca_dev->usb_err = 0; |
622 | |
623 | if (!gspca_dev->streaming) |
624 | return 0; |
625 | |
626 | switch (ctrl->id) { |
627 | case V4L2_CID_BRIGHTNESS: |
628 | setbrightness(gspca_dev, val: ctrl->val); |
629 | break; |
630 | case V4L2_CID_GAIN: |
631 | setgain(gspca_dev, val: ctrl->val); |
632 | break; |
633 | case V4L2_CID_EXPOSURE: |
634 | setexposure(gspca_dev, val: ctrl->val, freq: sd->freq->val); |
635 | break; |
636 | } |
637 | return gspca_dev->usb_err; |
638 | } |
639 | |
640 | static const struct v4l2_ctrl_ops sd_ctrl_ops = { |
641 | .s_ctrl = sd_s_ctrl, |
642 | }; |
643 | |
644 | static int sd_init_controls(struct gspca_dev *gspca_dev) |
645 | { |
646 | struct sd *sd = (struct sd *)gspca_dev; |
647 | struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; |
648 | |
649 | gspca_dev->vdev.ctrl_handler = hdl; |
650 | v4l2_ctrl_handler_init(hdl, 4); |
651 | if (sd->has_brightness) |
652 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
653 | V4L2_CID_BRIGHTNESS, min: 0, max: 255, step: 1, def: 15); |
654 | /* max is really 63 but > 50 is not pretty */ |
655 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
656 | V4L2_CID_GAIN, min: 0, max: 50, step: 1, def: 25); |
657 | sd->exposure = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
658 | V4L2_CID_EXPOSURE, min: 0, max: 32767, step: 1, def: 15000); |
659 | sd->freq = v4l2_ctrl_new_std_menu(hdl, ops: &sd_ctrl_ops, |
660 | V4L2_CID_POWER_LINE_FREQUENCY, |
661 | max: V4L2_CID_POWER_LINE_FREQUENCY_60HZ, mask: 0, def: 0); |
662 | |
663 | if (hdl->error) { |
664 | pr_err("Could not initialize controls\n" ); |
665 | return hdl->error; |
666 | } |
667 | v4l2_ctrl_cluster(ncontrols: 2, controls: &sd->exposure); |
668 | return 0; |
669 | } |
670 | |
671 | /* sub-driver description */ |
672 | static const struct sd_desc sd_desc = { |
673 | .name = MODULE_NAME, |
674 | .config = sd_config, |
675 | .init = sd_init, |
676 | .init_controls = sd_init_controls, |
677 | .isoc_init = sd_isoc_init, |
678 | .start = sd_start, |
679 | .stopN = sd_stopN, |
680 | .dq_callback = sd_dq_callback, |
681 | .pkt_scan = sd_pkt_scan, |
682 | #if IS_ENABLED(CONFIG_INPUT) |
683 | .int_pkt_scan = sd_int_pkt_scan, |
684 | #endif |
685 | }; |
686 | |
687 | /* -- module initialisation -- */ |
688 | static const struct usb_device_id device_table[] = { |
689 | {USB_DEVICE(0x03e8, 0x0004)}, /* Endpoints/Aox SE401 */ |
690 | {USB_DEVICE(0x0471, 0x030b)}, /* Philips PCVC665K */ |
691 | {USB_DEVICE(0x047d, 0x5001)}, /* Kensington 67014 */ |
692 | {USB_DEVICE(0x047d, 0x5002)}, /* Kensington 6701(5/7) */ |
693 | {USB_DEVICE(0x047d, 0x5003)}, /* Kensington 67016 */ |
694 | {} |
695 | }; |
696 | MODULE_DEVICE_TABLE(usb, device_table); |
697 | |
698 | /* -- device connect -- */ |
699 | static int sd_probe(struct usb_interface *intf, |
700 | const struct usb_device_id *id) |
701 | { |
702 | return gspca_dev_probe(intf, id, sd_desc: &sd_desc, dev_size: sizeof(struct sd), |
703 | THIS_MODULE); |
704 | } |
705 | |
706 | static int sd_pre_reset(struct usb_interface *intf) |
707 | { |
708 | return 0; |
709 | } |
710 | |
711 | static int sd_post_reset(struct usb_interface *intf) |
712 | { |
713 | return 0; |
714 | } |
715 | |
716 | static struct usb_driver sd_driver = { |
717 | .name = MODULE_NAME, |
718 | .id_table = device_table, |
719 | .probe = sd_probe, |
720 | .disconnect = gspca_disconnect, |
721 | #ifdef CONFIG_PM |
722 | .suspend = gspca_suspend, |
723 | .resume = gspca_resume, |
724 | .reset_resume = gspca_resume, |
725 | #endif |
726 | .pre_reset = sd_pre_reset, |
727 | .post_reset = sd_post_reset, |
728 | }; |
729 | |
730 | module_usb_driver(sd_driver); |
731 | |