1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Driver for USB webcams based on Konica chipset. This |
4 | * chipset is used in Intel YC76 camera. |
5 | * |
6 | * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.com> |
7 | * |
8 | * Based on the usbvideo v4l1 konicawc driver which is: |
9 | * |
10 | * Copyright (C) 2002 Simon Evans <spse@secret.org.uk> |
11 | * |
12 | * The code for making gspca work with a webcam with 2 isoc endpoints was |
13 | * taken from the benq gspca subdriver which is: |
14 | * |
15 | * Copyright (C) 2009 Jean-Francois Moine (http://moinejf.free.fr) |
16 | */ |
17 | |
18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
19 | |
20 | #define MODULE_NAME "konica" |
21 | |
22 | #include <linux/input.h> |
23 | #include "gspca.h" |
24 | |
25 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>" ); |
26 | MODULE_DESCRIPTION("Konica chipset USB Camera Driver" ); |
27 | MODULE_LICENSE("GPL" ); |
28 | |
29 | #define WHITEBAL_REG 0x01 |
30 | #define BRIGHTNESS_REG 0x02 |
31 | #define SHARPNESS_REG 0x03 |
32 | #define CONTRAST_REG 0x04 |
33 | #define SATURATION_REG 0x05 |
34 | |
35 | /* specific webcam descriptor */ |
36 | struct sd { |
37 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
38 | struct urb *last_data_urb; |
39 | u8 snapshot_pressed; |
40 | }; |
41 | |
42 | |
43 | /* .priv is what goes to register 8 for this mode, known working values: |
44 | 0x00 -> 176x144, cropped |
45 | 0x01 -> 176x144, cropped |
46 | 0x02 -> 176x144, cropped |
47 | 0x03 -> 176x144, cropped |
48 | 0x04 -> 176x144, binned |
49 | 0x05 -> 320x240 |
50 | 0x06 -> 320x240 |
51 | 0x07 -> 160x120, cropped |
52 | 0x08 -> 160x120, cropped |
53 | 0x09 -> 160x120, binned (note has 136 lines) |
54 | 0x0a -> 160x120, binned (note has 136 lines) |
55 | 0x0b -> 160x120, cropped |
56 | */ |
57 | static const struct v4l2_pix_format vga_mode[] = { |
58 | {160, 120, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE, |
59 | .bytesperline = 160, |
60 | .sizeimage = 160 * 136 * 3 / 2 + 960, |
61 | .colorspace = V4L2_COLORSPACE_SRGB, |
62 | .priv = 0x0a}, |
63 | {176, 144, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE, |
64 | .bytesperline = 176, |
65 | .sizeimage = 176 * 144 * 3 / 2 + 960, |
66 | .colorspace = V4L2_COLORSPACE_SRGB, |
67 | .priv = 0x04}, |
68 | {320, 240, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE, |
69 | .bytesperline = 320, |
70 | .sizeimage = 320 * 240 * 3 / 2 + 960, |
71 | .colorspace = V4L2_COLORSPACE_SRGB, |
72 | .priv = 0x05}, |
73 | }; |
74 | |
75 | static void sd_isoc_irq(struct urb *urb); |
76 | |
77 | static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index) |
78 | { |
79 | struct usb_device *dev = gspca_dev->dev; |
80 | int ret; |
81 | |
82 | if (gspca_dev->usb_err < 0) |
83 | return; |
84 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
85 | request: 0x02, |
86 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
87 | value, |
88 | index, |
89 | NULL, |
90 | size: 0, |
91 | timeout: 1000); |
92 | if (ret < 0) { |
93 | pr_err("reg_w err writing %02x to %02x: %d\n" , |
94 | value, index, ret); |
95 | gspca_dev->usb_err = ret; |
96 | } |
97 | } |
98 | |
99 | static void reg_r(struct gspca_dev *gspca_dev, u16 value, u16 index) |
100 | { |
101 | struct usb_device *dev = gspca_dev->dev; |
102 | int ret; |
103 | |
104 | if (gspca_dev->usb_err < 0) |
105 | return; |
106 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
107 | request: 0x03, |
108 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
109 | value, |
110 | index, |
111 | data: gspca_dev->usb_buf, |
112 | size: 2, |
113 | timeout: 1000); |
114 | if (ret < 0) { |
115 | pr_err("reg_r err %d\n" , ret); |
116 | gspca_dev->usb_err = ret; |
117 | /* |
118 | * Make sure the buffer is zeroed to avoid uninitialized |
119 | * values. |
120 | */ |
121 | memset(gspca_dev->usb_buf, 0, 2); |
122 | } |
123 | } |
124 | |
125 | static void konica_stream_on(struct gspca_dev *gspca_dev) |
126 | { |
127 | reg_w(gspca_dev, value: 1, index: 0x0b); |
128 | } |
129 | |
130 | static void konica_stream_off(struct gspca_dev *gspca_dev) |
131 | { |
132 | reg_w(gspca_dev, value: 0, index: 0x0b); |
133 | } |
134 | |
135 | /* this function is called at probe time */ |
136 | static int sd_config(struct gspca_dev *gspca_dev, |
137 | const struct usb_device_id *id) |
138 | { |
139 | gspca_dev->cam.cam_mode = vga_mode; |
140 | gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); |
141 | gspca_dev->cam.no_urb_create = 1; |
142 | |
143 | return 0; |
144 | } |
145 | |
146 | /* this function is called at probe and resume time */ |
147 | static int sd_init(struct gspca_dev *gspca_dev) |
148 | { |
149 | int i; |
150 | |
151 | /* |
152 | * The konica needs a freaking large time to "boot" (approx 6.5 sec.), |
153 | * and does not want to be bothered while doing so :| |
154 | * Register 0x10 counts from 1 - 3, with 3 being "ready" |
155 | */ |
156 | msleep(msecs: 6000); |
157 | for (i = 0; i < 20; i++) { |
158 | reg_r(gspca_dev, value: 0, index: 0x10); |
159 | if (gspca_dev->usb_buf[0] == 3) |
160 | break; |
161 | msleep(msecs: 100); |
162 | } |
163 | reg_w(gspca_dev, value: 0, index: 0x0d); |
164 | |
165 | return gspca_dev->usb_err; |
166 | } |
167 | |
168 | static int sd_start(struct gspca_dev *gspca_dev) |
169 | { |
170 | struct sd *sd = (struct sd *) gspca_dev; |
171 | struct urb *urb; |
172 | int i, n, packet_size; |
173 | struct usb_host_interface *alt; |
174 | struct usb_interface *intf; |
175 | |
176 | intf = usb_ifnum_to_if(dev: sd->gspca_dev.dev, ifnum: sd->gspca_dev.iface); |
177 | alt = usb_altnum_to_altsetting(intf, altnum: sd->gspca_dev.alt); |
178 | if (!alt) { |
179 | pr_err("Couldn't get altsetting\n" ); |
180 | return -EIO; |
181 | } |
182 | |
183 | if (alt->desc.bNumEndpoints < 2) |
184 | return -ENODEV; |
185 | |
186 | packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); |
187 | |
188 | n = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
189 | reg_w(gspca_dev, value: n, index: 0x08); |
190 | |
191 | konica_stream_on(gspca_dev); |
192 | |
193 | if (gspca_dev->usb_err) |
194 | return gspca_dev->usb_err; |
195 | |
196 | /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */ |
197 | #if MAX_NURBS < 4 |
198 | #error "Not enough URBs in the gspca table" |
199 | #endif |
200 | #define SD_NPKT 32 |
201 | for (n = 0; n < 4; n++) { |
202 | i = n & 1 ? 0 : 1; |
203 | packet_size = |
204 | le16_to_cpu(alt->endpoint[i].desc.wMaxPacketSize); |
205 | urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL); |
206 | if (!urb) |
207 | return -ENOMEM; |
208 | gspca_dev->urb[n] = urb; |
209 | urb->transfer_buffer = usb_alloc_coherent(dev: gspca_dev->dev, |
210 | size: packet_size * SD_NPKT, |
211 | GFP_KERNEL, |
212 | dma: &urb->transfer_dma); |
213 | if (urb->transfer_buffer == NULL) { |
214 | pr_err("usb_buffer_alloc failed\n" ); |
215 | return -ENOMEM; |
216 | } |
217 | |
218 | urb->dev = gspca_dev->dev; |
219 | urb->context = gspca_dev; |
220 | urb->transfer_buffer_length = packet_size * SD_NPKT; |
221 | urb->pipe = usb_rcvisocpipe(gspca_dev->dev, |
222 | n & 1 ? 0x81 : 0x82); |
223 | urb->transfer_flags = URB_ISO_ASAP |
224 | | URB_NO_TRANSFER_DMA_MAP; |
225 | urb->interval = 1; |
226 | urb->complete = sd_isoc_irq; |
227 | urb->number_of_packets = SD_NPKT; |
228 | for (i = 0; i < SD_NPKT; i++) { |
229 | urb->iso_frame_desc[i].length = packet_size; |
230 | urb->iso_frame_desc[i].offset = packet_size * i; |
231 | } |
232 | } |
233 | |
234 | return 0; |
235 | } |
236 | |
237 | static void sd_stopN(struct gspca_dev *gspca_dev) |
238 | { |
239 | struct sd *sd __maybe_unused = (struct sd *) gspca_dev; |
240 | |
241 | konica_stream_off(gspca_dev); |
242 | #if IS_ENABLED(CONFIG_INPUT) |
243 | /* Don't keep the button in the pressed state "forever" if it was |
244 | pressed when streaming is stopped */ |
245 | if (sd->snapshot_pressed) { |
246 | input_report_key(dev: gspca_dev->input_dev, KEY_CAMERA, value: 0); |
247 | input_sync(dev: gspca_dev->input_dev); |
248 | sd->snapshot_pressed = 0; |
249 | } |
250 | #endif |
251 | } |
252 | |
253 | /* reception of an URB */ |
254 | static void sd_isoc_irq(struct urb *urb) |
255 | { |
256 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; |
257 | struct sd *sd = (struct sd *) gspca_dev; |
258 | struct urb *data_urb, *status_urb; |
259 | u8 *data; |
260 | int i, st; |
261 | |
262 | gspca_dbg(gspca_dev, D_PACK, "sd isoc irq\n" ); |
263 | if (!gspca_dev->streaming) |
264 | return; |
265 | |
266 | if (urb->status != 0) { |
267 | if (urb->status == -ESHUTDOWN) |
268 | return; /* disconnection */ |
269 | #ifdef CONFIG_PM |
270 | if (gspca_dev->frozen) |
271 | return; |
272 | #endif |
273 | gspca_err(gspca_dev, "urb status: %d\n" , urb->status); |
274 | st = usb_submit_urb(urb, GFP_ATOMIC); |
275 | if (st < 0) |
276 | pr_err("resubmit urb error %d\n" , st); |
277 | return; |
278 | } |
279 | |
280 | /* if this is a data URB (ep 0x82), wait */ |
281 | if (urb->transfer_buffer_length > 32) { |
282 | sd->last_data_urb = urb; |
283 | return; |
284 | } |
285 | |
286 | status_urb = urb; |
287 | data_urb = sd->last_data_urb; |
288 | sd->last_data_urb = NULL; |
289 | |
290 | if (!data_urb || data_urb->start_frame != status_urb->start_frame) { |
291 | gspca_err(gspca_dev, "lost sync on frames\n" ); |
292 | goto resubmit; |
293 | } |
294 | |
295 | if (data_urb->number_of_packets != status_urb->number_of_packets) { |
296 | gspca_err(gspca_dev, "no packets does not match, data: %d, status: %d\n" , |
297 | data_urb->number_of_packets, |
298 | status_urb->number_of_packets); |
299 | goto resubmit; |
300 | } |
301 | |
302 | for (i = 0; i < status_urb->number_of_packets; i++) { |
303 | if (data_urb->iso_frame_desc[i].status || |
304 | status_urb->iso_frame_desc[i].status) { |
305 | gspca_err(gspca_dev, "pkt %d data-status %d, status-status %d\n" , |
306 | i, |
307 | data_urb->iso_frame_desc[i].status, |
308 | status_urb->iso_frame_desc[i].status); |
309 | gspca_dev->last_packet_type = DISCARD_PACKET; |
310 | continue; |
311 | } |
312 | |
313 | if (status_urb->iso_frame_desc[i].actual_length != 1) { |
314 | gspca_err(gspca_dev, "bad status packet length %d\n" , |
315 | status_urb->iso_frame_desc[i].actual_length); |
316 | gspca_dev->last_packet_type = DISCARD_PACKET; |
317 | continue; |
318 | } |
319 | |
320 | st = *((u8 *)status_urb->transfer_buffer |
321 | + status_urb->iso_frame_desc[i].offset); |
322 | |
323 | data = (u8 *)data_urb->transfer_buffer |
324 | + data_urb->iso_frame_desc[i].offset; |
325 | |
326 | /* st: 0x80-0xff: frame start with frame number (ie 0-7f) |
327 | * otherwise: |
328 | * bit 0 0: keep packet |
329 | * 1: drop packet (padding data) |
330 | * |
331 | * bit 4 0 button not clicked |
332 | * 1 button clicked |
333 | * button is used to `take a picture' (in software) |
334 | */ |
335 | if (st & 0x80) { |
336 | gspca_frame_add(gspca_dev, packet_type: LAST_PACKET, NULL, len: 0); |
337 | gspca_frame_add(gspca_dev, packet_type: FIRST_PACKET, NULL, len: 0); |
338 | } else { |
339 | #if IS_ENABLED(CONFIG_INPUT) |
340 | u8 button_state = st & 0x40 ? 1 : 0; |
341 | if (sd->snapshot_pressed != button_state) { |
342 | input_report_key(dev: gspca_dev->input_dev, |
343 | KEY_CAMERA, |
344 | value: button_state); |
345 | input_sync(dev: gspca_dev->input_dev); |
346 | sd->snapshot_pressed = button_state; |
347 | } |
348 | #endif |
349 | if (st & 0x01) |
350 | continue; |
351 | } |
352 | gspca_frame_add(gspca_dev, packet_type: INTER_PACKET, data, |
353 | len: data_urb->iso_frame_desc[i].actual_length); |
354 | } |
355 | |
356 | resubmit: |
357 | if (data_urb) { |
358 | st = usb_submit_urb(urb: data_urb, GFP_ATOMIC); |
359 | if (st < 0) |
360 | gspca_err(gspca_dev, "usb_submit_urb(data_urb) ret %d\n" , |
361 | st); |
362 | } |
363 | st = usb_submit_urb(urb: status_urb, GFP_ATOMIC); |
364 | if (st < 0) |
365 | gspca_err(gspca_dev, "usb_submit_urb(status_urb) ret %d\n" , st); |
366 | } |
367 | |
368 | static int sd_s_ctrl(struct v4l2_ctrl *ctrl) |
369 | { |
370 | struct gspca_dev *gspca_dev = |
371 | container_of(ctrl->handler, struct gspca_dev, ctrl_handler); |
372 | |
373 | gspca_dev->usb_err = 0; |
374 | |
375 | if (!gspca_dev->streaming) |
376 | return 0; |
377 | |
378 | switch (ctrl->id) { |
379 | case V4L2_CID_BRIGHTNESS: |
380 | konica_stream_off(gspca_dev); |
381 | reg_w(gspca_dev, value: ctrl->val, BRIGHTNESS_REG); |
382 | konica_stream_on(gspca_dev); |
383 | break; |
384 | case V4L2_CID_CONTRAST: |
385 | konica_stream_off(gspca_dev); |
386 | reg_w(gspca_dev, value: ctrl->val, CONTRAST_REG); |
387 | konica_stream_on(gspca_dev); |
388 | break; |
389 | case V4L2_CID_SATURATION: |
390 | konica_stream_off(gspca_dev); |
391 | reg_w(gspca_dev, value: ctrl->val, SATURATION_REG); |
392 | konica_stream_on(gspca_dev); |
393 | break; |
394 | case V4L2_CID_WHITE_BALANCE_TEMPERATURE: |
395 | konica_stream_off(gspca_dev); |
396 | reg_w(gspca_dev, value: ctrl->val, WHITEBAL_REG); |
397 | konica_stream_on(gspca_dev); |
398 | break; |
399 | case V4L2_CID_SHARPNESS: |
400 | konica_stream_off(gspca_dev); |
401 | reg_w(gspca_dev, value: ctrl->val, SHARPNESS_REG); |
402 | konica_stream_on(gspca_dev); |
403 | break; |
404 | } |
405 | return gspca_dev->usb_err; |
406 | } |
407 | |
408 | static const struct v4l2_ctrl_ops sd_ctrl_ops = { |
409 | .s_ctrl = sd_s_ctrl, |
410 | }; |
411 | |
412 | static int sd_init_controls(struct gspca_dev *gspca_dev) |
413 | { |
414 | struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; |
415 | |
416 | gspca_dev->vdev.ctrl_handler = hdl; |
417 | v4l2_ctrl_handler_init(hdl, 5); |
418 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
419 | V4L2_CID_BRIGHTNESS, min: 0, max: 9, step: 1, def: 4); |
420 | /* Needs to be verified */ |
421 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
422 | V4L2_CID_CONTRAST, min: 0, max: 9, step: 1, def: 4); |
423 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
424 | V4L2_CID_SATURATION, min: 0, max: 9, step: 1, def: 4); |
425 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
426 | V4L2_CID_WHITE_BALANCE_TEMPERATURE, |
427 | min: 0, max: 33, step: 1, def: 25); |
428 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
429 | V4L2_CID_SHARPNESS, min: 0, max: 9, step: 1, def: 4); |
430 | |
431 | if (hdl->error) { |
432 | pr_err("Could not initialize controls\n" ); |
433 | return hdl->error; |
434 | } |
435 | return 0; |
436 | } |
437 | |
438 | /* sub-driver description */ |
439 | static const struct sd_desc sd_desc = { |
440 | .name = MODULE_NAME, |
441 | .config = sd_config, |
442 | .init = sd_init, |
443 | .init_controls = sd_init_controls, |
444 | .start = sd_start, |
445 | .stopN = sd_stopN, |
446 | #if IS_ENABLED(CONFIG_INPUT) |
447 | .other_input = 1, |
448 | #endif |
449 | }; |
450 | |
451 | /* -- module initialisation -- */ |
452 | static const struct usb_device_id device_table[] = { |
453 | {USB_DEVICE(0x04c8, 0x0720)}, /* Intel YC 76 */ |
454 | {} |
455 | }; |
456 | MODULE_DEVICE_TABLE(usb, device_table); |
457 | |
458 | /* -- device connect -- */ |
459 | static int sd_probe(struct usb_interface *intf, |
460 | const struct usb_device_id *id) |
461 | { |
462 | return gspca_dev_probe(intf, id, sd_desc: &sd_desc, dev_size: sizeof(struct sd), |
463 | THIS_MODULE); |
464 | } |
465 | |
466 | static struct usb_driver sd_driver = { |
467 | .name = MODULE_NAME, |
468 | .id_table = device_table, |
469 | .probe = sd_probe, |
470 | .disconnect = gspca_disconnect, |
471 | #ifdef CONFIG_PM |
472 | .suspend = gspca_suspend, |
473 | .resume = gspca_resume, |
474 | .reset_resume = gspca_resume, |
475 | #endif |
476 | }; |
477 | |
478 | module_usb_driver(sd_driver); |
479 | |