Fix SXGA support to enforce bayer format
[microdia.git] / sn9c20x-usb.c
blobfdff28fa65ad406af66859dd5ec4c1fd7dab7724
1 /**
2 * @file sn9c20x-usb.c
3 * @author Nicolas VIVIEN
4 * @date 2008-02-01
6 * @brief Driver for SN9C20X USB video camera
8 * @note Copyright (C) Nicolas VIVIEN
10 * @par Licences
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/kernel.h>
30 #include <linux/version.h>
31 #include <linux/errno.h>
32 #include <linux/slab.h>
33 #include <linux/kref.h>
34 #include <linux/stat.h>
35 #include <linux/usb.h>
36 #include <media/v4l2-common.h>
38 #ifdef CONFIG_SN9C20X_EVDEV
39 #include <linux/kthread.h>
40 #include <linux/freezer.h>
41 #include <linux/usb/input.h>
42 #endif
44 #include "sn9c20x.h"
45 #include "sn9c20x-bridge.h"
46 #include "micron.h"
47 #include "omnivision.h"
49 /**
50 * @var fps
51 * Module parameter to set frame per second
53 static __u8 fps = 25;
55 /**
56 * @var bulk
57 * Module parameter to enable/disable bulk transfers
59 static __u8 bulk;
61 /**
62 * @var jpeg
63 * Module parameter to enable/disable JPEG format
65 __u8 jpeg = 2;
67 /**
68 * @var bandwidth
69 * Module parameter to set the available bandwidth via the alternate setting
71 static __u8 bandwidth = 8;
73 /**
74 * @var hflip
75 * Module parameter to enable/disable the horizontal flip process
77 static __u8 hflip;
79 /**
80 * @var flip_detect
81 * Module parameter to enable/disable vflip detection
83 static __u8 flip_detect;
85 /**
86 * @var vflip
87 * Module parameter to enable/disable the vertical flip process
89 static __u8 vflip;
91 /**
92 * @var brightness
93 * Module parameter to set the brightness
95 static __u16 brightness = SN9C20X_PERCENT(50, 0xFF);
97 /**
98 * @var gamma
99 * Module parameter to set the gamma
101 static __u16 gamma = SN9C20X_PERCENT(20, 0xFF);
104 * @var saturation
105 * Module parameter to set the gamma
107 static __u16 saturation = SN9C20X_PERCENT(50, 0xFF);
110 * @var hue
111 * Module parameter to set the gamma
113 static __s16 hue;
116 * @var contrast
117 * Module parameter to set the contrast
119 static __u16 contrast = SN9C20X_PERCENT(50, 0xFF);
122 * @var exposure
123 * Module parameter to set the exposure
125 static __u16 exposure = SN9C20X_PERCENT(20, 0xFF);
128 * @var gain
129 * Module parameter to set the gain
131 static __u16 gain = SN9C20X_PERCENT(20, 0xFF);
134 * @var sharpness
135 * Module parameter to set the sharpness
137 static __u16 sharpness = SN9C20X_PERCENT(50, 0x3F);
140 * @var red_gain
141 * Module parameter to set the red gain
143 static __u16 red_gain = SN9C20X_PERCENT(25, 0x7F);
146 * @var blue_gain
147 * Module parameter to set the blue gain
149 static __u16 blue_gain = SN9C20X_PERCENT(25, 0x7F);
152 * @var min_buffers
153 * Module parameter to set the minimum number of image buffers
155 static __u8 min_buffers = 2;
158 * @var max_buffers
159 * Module parameter to set the maximum number of image buffers
161 static __u8 max_buffers = 5;
164 * @var auto_exposure
165 * Module parameter to set the exposure
167 static __u8 auto_exposure = 1;
170 * @var auto_gain
171 * Module parameter to set the gain
173 static __u8 auto_gain;
177 * @var auto_whitebalance
178 * Module parameter to set the auto-whitebalance
180 static __u8 auto_whitebalance = 1;
183 * @var log_level
184 * Module parameter to set the log level
186 __u8 log_level = 5;
190 * @var sn9c20x_table
191 * Define all the hotplug supported devices by this driver
193 static struct usb_device_id sn9c20x_table[] = {
194 /* SN9C201 + MI1300 */
195 {SN9C20X_USB_DEVICE(0x0C45, 0x6240, MT9M001_SENSOR, 0x5d)},
196 /* SN9C201 + MI1310 */
197 {SN9C20X_USB_DEVICE(0x0C45, 0x6242, MT9M111_SENSOR, 0x5d)},
198 /* SN9C201 + S5K4AAFX */
199 {SN9C20X_USB_DEVICE(0x0C45, 0x6243, 0, 0)},
200 /* SN9C201 + OV9655 */
201 {SN9C20X_USB_DEVICE(0x0C45, 0x6248, OV9655_SENSOR, 0x30)},
202 /* SN9C201 + CX1332 */
203 {SN9C20X_USB_DEVICE(0x0C45, 0x624B, 0, 0)},
204 /* SN9C201 + MI1320 */
205 {SN9C20X_USB_DEVICE(0x0C45, 0x624C, 0, 0)},
206 /* SN9C201 + SOI968 */
207 {SN9C20X_USB_DEVICE(0x0C45, 0x624E, SOI968_SENSOR, 0x30)},
208 /* SN9C201 + OV9650 */
209 {SN9C20X_USB_DEVICE(0x0C45, 0x624F, OV9650_SENSOR, 0x30)},
210 /* SN9C201 + OV9650 */
211 {SN9C20X_USB_DEVICE(0x0C45, 0x6251, OV9650_SENSOR, 0x30)},
212 /* SN9C201 + OV9650 */
213 {SN9C20X_USB_DEVICE(0x0C45, 0x6253, OV9650_SENSOR, 0x30)},
214 /* SN9C201 + OV7670ISP */
215 {SN9C20X_USB_DEVICE(0x0C45, 0x6260, OV7670_SENSOR, 0x21)},
216 /* SN9C201 + OM6802 */
217 {SN9C20X_USB_DEVICE(0x0C45, 0x6262, 0, 0)},
218 /* SN9C201 + MI0360/MT9V111 */
219 {SN9C20X_USB_DEVICE(0x0C45, 0x6270, 0, 0)},
220 /* SN9C201 + S5K53BEB */
221 {SN9C20X_USB_DEVICE(0x0C45, 0x627A, 0, 0)},
222 /* SN9C201 + OV7660 */
223 {SN9C20X_USB_DEVICE(0x0C45, 0x627B, OV7660_SENSOR, 0x21)},
224 /* SN9C201 + HV7131R */
225 {SN9C20X_USB_DEVICE(0x0C45, 0x627C, HV7131R_SENSOR, 0x11)},
226 /* EEPROM */
227 {SN9C20X_USB_DEVICE(0x0C45, 0x627F, OV9650_SENSOR, 0x30)},
228 /* SN9C202 + MI1300 */
229 {SN9C20X_USB_DEVICE(0x0C45, 0x6280, MT9M001_SENSOR, 0x5d)},
230 /* SN9C202 + MI1310 */
231 {SN9C20X_USB_DEVICE(0x0C45, 0x6282, MT9M111_SENSOR, 0x5d)},
232 /* SN9C202 + S5K4AAFX */
233 {SN9C20X_USB_DEVICE(0x0C45, 0x6283, 0, 0)},
234 /* SN9C202 + OV9655 */
235 {SN9C20X_USB_DEVICE(0x0C45, 0x6288, OV9655_SENSOR, 0x30)},
236 /* SN9C202 + ICM107 */
237 {SN9C20X_USB_DEVICE(0x0C45, 0x628A, 0, 0)},
238 /* SN9C202 + CX1332 */
239 {SN9C20X_USB_DEVICE(0x0C45, 0x628B, 0, 0)},
240 /* SN9C202 + MI1320 */
241 {SN9C20X_USB_DEVICE(0x0C45, 0x628C, 0, 0)},
242 /* SN9C202 + SOI968 */
243 {SN9C20X_USB_DEVICE(0x0C45, 0x628E, SOI968_SENSOR, 0x30)},
244 /* SN9C202 + OV9650 */
245 {SN9C20X_USB_DEVICE(0x0C45, 0x628F, OV9650_SENSOR, 0x30)},
246 /* SN9C202 + OV7670ISP */
247 {SN9C20X_USB_DEVICE(0x0C45, 0x62A0, OV7670_SENSOR, 0x21)},
248 /* SN9C202 + OM6802 */
249 {SN9C20X_USB_DEVICE(0x0C45, 0x62A2, 0, 0)},
250 /* SN9C202 + MI0360/MT9V111 */
251 {SN9C20X_USB_DEVICE(0x0C45, 0x62B0, 0, 0)},
252 /* SN9C202 + OV9655 */
253 {SN9C20X_USB_DEVICE(0x0C45, 0x62B3, OV9655_SENSOR, 0x30)},
254 /* SN9C202 + S5K53BEB */
255 {SN9C20X_USB_DEVICE(0x0C45, 0x62BA, 0, 0)},
256 /* SN9C202 + OV7660 */
257 {SN9C20X_USB_DEVICE(0x0C45, 0x62BB, OV7660_SENSOR, 0x21)},
258 /* SN9C202 + HV7131R */
259 {SN9C20X_USB_DEVICE(0x0C45, 0x62BC, HV7131R_SENSOR, 0x11)},
260 /* SN9C202 + OV7663 */
261 {SN9C20X_USB_DEVICE(0x0C45, 0x62BE, 0, 0)},
262 /* => 628f (SN9C202 + OV9650) */
263 {SN9C20X_USB_DEVICE(0x045E, 0x00F4, OV9650_SENSOR, 0x30)},
264 /* => 627b (SN9C201 + OV7660) */
265 {SN9C20X_USB_DEVICE(0x145F, 0x013D, OV7660_SENSOR, 0x21)},
266 /* => 62be (SN9C202 + OV7663 + EEPROM) */
267 {SN9C20X_USB_DEVICE(0x04F2, 0xA128, 0, 0)},
268 /* => 627c (SN9C201 + HV7131R) */
269 {SN9C20X_USB_DEVICE(0x0458, 0x7029, HV7131R_SENSOR, 0x11)},
270 /* SN9C201 + HV7131R (Dino Lite - Digital Microscope) */
271 {SN9C20X_USB_DEVICE(0xA168, 0x0610, HV7131R_SENSOR, 0x11)},
272 {SN9C20X_USB_DEVICE(0xA168, 0x0611, HV7131R_SENSOR, 0x11)},
273 {SN9C20X_USB_DEVICE(0xA168, 0x0613, HV7131R_SENSOR, 0x11)},
274 {SN9C20X_USB_DEVICE(0xA168, 0x0618, HV7131R_SENSOR, 0x11)},
275 /* SN9C201 + MI1310 (Dino Lite Pro - Digital Microscope) */
276 {SN9C20X_USB_DEVICE(0xA168, 0x0614, MT9M111_SENSOR, 0x5d)},
277 {SN9C20X_USB_DEVICE(0xA168, 0x0615, MT9M111_SENSOR, 0x5d)},
278 {SN9C20X_USB_DEVICE(0xA168, 0x0617, MT9M111_SENSOR, 0x5d)},
283 MODULE_DEVICE_TABLE(usb, sn9c20x_table); /**< Define the supported devices */
285 DEFINE_MUTEX(open_lock); /**< Define global mutex */
287 struct usb_endpoint_descriptor *find_endpoint(struct usb_host_interface *alts,
288 __u8 epaddr)
290 unsigned long i;
291 struct usb_endpoint_descriptor *ep;
293 for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
294 ep = &alts->endpoint[i].desc;
295 if ((ep->bEndpointAddress & 0xf) == epaddr) {
296 UDIA_DEBUG("Found Endpoint 0x%X\n", epaddr);
297 return ep;
301 return NULL;
304 * @param dev Device structure
305 * @param ep Usb endpoint structure
307 * @returns 0 if all is OK
309 * @brief Initilize an isochronous pipe.
311 * This function permits to initialize an URB transfert (or isochronous pipe).
313 int usb_sn9c20x_isoc_init(struct usb_sn9c20x *dev,
314 struct usb_endpoint_descriptor *ep)
316 int i, j;
317 __u16 iso_max_frame_size;
318 struct urb *urb;
319 struct usb_device *udev;
321 udev = dev->udev;
323 UDIA_DEBUG("usb_sn9c20x_isoc_init()\n");
325 iso_max_frame_size =
326 max_packet_sz(le16_to_cpu(ep->wMaxPacketSize)) *
327 hb_multiplier(le16_to_cpu(ep->wMaxPacketSize));
328 for (i = 0; i < MAX_URBS; i++) {
329 urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
331 if (urb == NULL) {
332 UDIA_ERROR("Failed to allocate URB %d\n", i);
333 usb_sn9c20x_uninit_urbs(dev, 1);
334 return -ENOMEM;
337 urb->interval = 1;
338 urb->dev = udev;
339 urb->pipe = usb_rcvisocpipe(udev, ep->bEndpointAddress);
340 urb->transfer_flags = URB_ISO_ASAP;
341 urb->transfer_buffer_length = iso_max_frame_size * ISO_FRAMES_PER_DESC;
342 urb->complete = usb_sn9c20x_completion_handler;
343 urb->context = dev;
344 urb->start_frame = 0;
345 urb->number_of_packets = ISO_FRAMES_PER_DESC;
347 for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
348 urb->iso_frame_desc[j].offset = j * iso_max_frame_size;
349 urb->iso_frame_desc[j].length = iso_max_frame_size;
352 if (dev->urbs[i].data == NULL) {
353 dev->urbs[i].data = kzalloc(urb->transfer_buffer_length,
354 GFP_KERNEL);
355 if (dev->urbs[i].data == NULL) {
356 usb_sn9c20x_uninit_urbs(dev, 1);
357 return -ENOMEM;
360 urb->transfer_buffer = dev->urbs[i].data;
361 dev->urbs[i].urb = urb;
364 return 0;
367 int usb_sn9c20x_bulk_init(struct usb_sn9c20x *dev,
368 struct usb_endpoint_descriptor *ep)
370 struct urb *urb;
371 unsigned int pipe, i;
372 __u16 psize;
373 __u32 size;
374 psize = max_packet_sz(le16_to_cpu(ep->wMaxPacketSize));
375 size = psize * ISO_FRAMES_PER_DESC;
376 pipe = usb_rcvbulkpipe(dev->udev, ep->bEndpointAddress);
378 for (i = 0; i < MAX_URBS; ++i) {
379 urb = usb_alloc_urb(0, GFP_KERNEL);
380 if (urb == NULL) {
381 usb_sn9c20x_uninit_urbs(dev, 1);
382 return -ENOMEM;
384 if (dev->urbs[i].data == NULL) {
385 dev->urbs[i].data = kzalloc(size, GFP_KERNEL);
386 if (dev->urbs[i].data == NULL) {
387 usb_sn9c20x_uninit_urbs(dev, 1);
388 return -ENOMEM;
392 usb_fill_bulk_urb(urb, dev->udev, pipe,
393 dev->urbs[i].data, size,
394 usb_sn9c20x_completion_handler,
395 dev);
397 dev->urbs[i].urb = urb;
400 return 0;
403 int usb_sn9c20x_init_urbs(struct usb_sn9c20x *dev)
405 int ret, i;
406 __u8 value;
407 struct usb_endpoint_descriptor *ep;
408 struct usb_interface *intf = dev->interface;
410 ret = usb_sn9c20x_control_read(dev, 0x1061, &value, 1);
411 if (ret < 0)
412 return ret;
414 if (!bulk) {
415 if (bandwidth > 8)
416 return -EINVAL;
418 ep = find_endpoint(usb_altnum_to_altsetting(intf, bandwidth), SN9C20X_VID_ISOC);
419 if (ep == NULL)
420 return -EIO;
422 ret = usb_set_interface(dev->udev, 0, bandwidth);
423 if (ret < 0)
424 return ret;
426 value |= 0x01;
427 ret = usb_sn9c20x_control_write(dev, 0x1061, &value, 1);
428 if (ret < 0)
429 return ret;
431 ret = usb_sn9c20x_isoc_init(dev, ep);
432 } else {
433 ep = find_endpoint(usb_altnum_to_altsetting(intf, 0), SN9C20X_BULK);
434 if (ep == NULL)
435 return -EIO;
437 ret = usb_set_interface(dev->udev, 0, 0);
438 if (ret < 0)
439 return ret;
441 value &= ~0x01;
442 ret = usb_sn9c20x_control_write(dev, 0x1061, &value, 1);
443 if (ret < 0)
444 return ret;
446 ret = usb_sn9c20x_bulk_init(dev, ep);
449 if (ret < 0)
450 return ret;
452 for (i = 0; i < MAX_URBS; i++) {
453 ret = usb_submit_urb(dev->urbs[i].urb, GFP_KERNEL);
454 if (ret)
455 UDIA_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
458 return 0;
462 * @param dev Device structure
464 * @brief Clean-up all the ISOC buffers
466 * This function permits to clean-up all the ISOC buffers.
468 void usb_sn9c20x_uninit_urbs(struct usb_sn9c20x *dev, int free_buffers)
470 int i;
471 struct urb *urb;
473 UDIA_DEBUG("Isoc cleanup\n");
475 if (dev == NULL)
476 return;
478 for (i = 0; i < MAX_URBS; i++) {
479 urb = dev->urbs[i].urb;
480 if (urb == NULL)
481 continue;
482 usb_kill_urb(urb);
483 usb_free_urb(urb);
484 dev->urbs[i].urb = NULL;
485 if (free_buffers) {
486 kfree(dev->urbs[i].data);
487 dev->urbs[i].data = NULL;
492 int usb_sn9c20x_detect_frame(unsigned char *buf, unsigned int buf_length)
494 static unsigned char frame_header[] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
495 int index;
496 if (buf_length < 64)
497 return -1;
498 if (buf_length == 64) {
499 if (memcmp(buf, frame_header, 6) == 0)
500 return 0;
501 else
502 return -1;
504 if (bulk) {
505 for (index = 0; index < buf_length - 63; index++) {
506 if (memcmp(buf + index, frame_header, 6) == 0) {
507 UDIA_DEBUG("Found Header at %d\n", index);
508 return index;
512 return -1;
515 void usb_sn9c20x_assemble_video(struct usb_sn9c20x *dev,
516 unsigned char *transfer, unsigned int transfer_length,
517 struct sn9c20x_buffer **buffer)
519 void *mem = NULL;
520 unsigned char *header;
521 int header_index;
522 int yavg;
523 struct sn9c20x_buffer *buf = *buffer;
524 struct sn9c20x_video_queue *queue = &dev->queue;
526 if (buf->state != SN9C20X_BUF_STATE_ACTIVE)
527 buf->state = SN9C20X_BUF_STATE_ACTIVE;
529 header_index = usb_sn9c20x_detect_frame(transfer, transfer_length);
530 if (header_index >= 0) {
531 if (header_index + buf->buf.bytesused > buf->buf.length) {
532 UDIA_WARNING("Frame Buffer overflow!\n");
533 dev->vframes_overflow++;
534 buf->state = SN9C20X_BUF_STATE_DONE;
536 header_index = min(buf->buf.length - buf->buf.bytesused,
537 (unsigned int)header_index);
538 mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
539 memcpy(mem, transfer, header_index);
540 buf->buf.bytesused += header_index;
541 header = transfer+header_index;
542 /* UDIA_INFO("color window: %dx%d\n",
543 header[0x3a] << 4,
544 header[0x3b] << 3);
545 UDIA_INFO("Frame Size: %d\n", buf->buf.bytesused);*/
546 yavg = ((header[35] >> 2) & 3)|(header[20] << 2)|(header[19] << 10);
547 yavg += ((header[35] >> 4) & 3)|(header[22] << 2)|(header[21] << 10);
548 yavg += ((header[35] >> 6) & 3)|(header[24] << 2)|(header[23] << 10);
549 yavg += (header[36] & 3)|(header[26] << 2)|(header[25] << 10);
550 yavg += ((header[36] >> 2) & 3)|(header[28] << 2)|(header[27] << 10);
551 yavg += ((header[36] >> 4) & 3)|(header[30] << 2)|(header[29] << 10);
552 yavg += ((header[36] >> 6) & 3)|(header[32] << 2)|(header[31] << 10);
553 yavg += ((header[44] >> 4) & 3)|(header[34] << 2)|(header[33] << 10);
554 UDIA_DEBUG("AVGY Total: %d (%d)\n", yavg, yavg >> 9);
555 yavg >>= 9;
556 atomic_set(&dev->camera.yavg, yavg);
558 if (buf->buf.bytesused != 0)
559 buf->state = SN9C20X_BUF_STATE_DONE;
560 } else {
561 if (transfer_length + buf->buf.bytesused > buf->buf.length) {
562 UDIA_WARNING("Frame Buffer overflow!\n");
563 dev->vframes_overflow++;
564 buf->state = SN9C20X_BUF_STATE_DONE;
566 transfer_length = min(buf->buf.length - buf->buf.bytesused,
567 transfer_length);
568 mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
569 memcpy(mem, transfer, transfer_length);
570 buf->buf.bytesused += transfer_length;
572 if (buf->state == SN9C20X_BUF_STATE_DONE ||
573 buf->state == SN9C20X_BUF_STATE_ERROR) {
574 buf = sn9c20x_queue_next_buffer(queue, buf);
575 *buffer = buf;
576 if (buf == NULL) {
577 dev->vframes_dropped++;
578 } else {
579 if (header_index + 64 < transfer_length) {
580 memcpy(queue->mem + buf->buf.m.offset,
581 transfer + header_index + 64,
582 transfer_length - (header_index + 64));
583 buf->buf.bytesused +=
584 transfer_length - (header_index + 64);
590 * @param urb URB structure
592 * @brief ISOC handler
594 * This function is called as an URB transfert is complete (Isochronous pipe).
595 * So, the traitement is done in interrupt time, so it has be fast, not crash,
596 * and not stall. Neat.
598 void usb_sn9c20x_completion_handler(struct urb *urb)
600 int i;
601 int ret;
602 unsigned long flags;
604 unsigned char *transfer = NULL;
605 unsigned int transfer_length;
607 struct sn9c20x_buffer *buf = NULL;
608 struct usb_sn9c20x *dev = urb->context;
609 struct sn9c20x_video_queue *queue = &dev->queue;
611 UDIA_STREAM("Isoc handler\n");
613 switch (urb->status) {
614 case 0:
615 break;
617 default:
618 UDIA_WARNING("Non-zero status (%d) in video "
619 "completion handler.\n", urb->status);
621 case -ENOENT: /* usb_kill_urb() called. */
622 if (dev->frozen)
623 return;
625 case -ECONNRESET: /* usb_unlink_urb() called. */
626 case -ESHUTDOWN: /* The endpoint is being disabled. */
627 sn9c20x_queue_cancel(queue, urb->status == -ESHUTDOWN);
628 return;
631 spin_lock_irqsave(&queue->irqlock, flags);
632 if (!list_empty(&queue->irqqueue))
633 buf = list_first_entry(&queue->irqqueue, struct sn9c20x_buffer,
634 queue);
635 spin_unlock_irqrestore(&queue->irqlock, flags);
636 if (!bulk) {
637 for (i = 0; i < urb->number_of_packets; i++) {
638 if (urb->iso_frame_desc[i].status != 0) {
639 /*UDIA_ERROR("Iso frame %d of USB has error %d\n",
640 i, urb->iso_frame_desc[i].status);*/
641 mdelay(1);
642 continue;
644 transfer_length = urb->iso_frame_desc[i].actual_length;
645 transfer = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
646 if (buf == NULL)
647 continue;
649 usb_sn9c20x_assemble_video(dev, transfer, transfer_length, &buf);
651 } else {
652 if (buf != NULL) {
653 usb_sn9c20x_assemble_video(dev, urb->transfer_buffer,
654 urb->actual_length, &buf);
657 ret = usb_submit_urb(urb, GFP_ATOMIC);
659 if (ret != 0) {
660 UDIA_ERROR("Error (%d) re-submitting urb in "
661 "sn9c20x_isoc_handler.\n", ret);
666 * @param dev Device structure
667 * @param value register to write to
668 * @param data
669 * @param length number of bytes
671 * @returns 0 if all is OK
673 * @brief Write a 16-bit value to a 16-bit register
675 * This function permits to write a 16-bit value to a 16-bit register on the USB bus.
677 int usb_sn9c20x_control_write(struct usb_sn9c20x *dev, __u16 value, __u8 *data, __u16 length)
679 int result;
680 struct usb_device *udev = dev->udev;
682 result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
683 0x08,
684 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
685 value,
686 0x00,
687 data,
688 length,
689 500);
691 if (unlikely(result < 0)) {
692 UDIA_ERROR("Write register failed index = 0x%02X\n", value);
693 return result;
696 return 0;
700 * @param dev Device structure
701 * @param index register to read from
702 * @param data
703 * @param length number of bytes
705 * @returns 0 if all is OK
707 * @brief Read a 16-bit value from a 16-bit register
709 * This function permits to read a 16-bit value from a 16-bit register on the USB bus.
711 int usb_sn9c20x_control_read(struct usb_sn9c20x *dev, __u16 index, __u8 *data, __u16 length)
713 int result;
715 struct usb_device *udev = dev->udev;
717 *data = 0;
719 result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
720 0x00,
721 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
722 index,
723 0x00,
724 data,
725 length,
726 500);
728 if (unlikely(result < 0)) {
729 UDIA_ERROR("Read register failed 0x%02X\n", index);
730 return result;
733 return 0;
738 * @param dev
740 * @returns 0 if all is OK
742 * @brief Set the default value about the video settings.
744 * This function permits to set the video settings for each video camera model.
747 static int usb_sn9c20x_default_settings(struct usb_sn9c20x *dev)
749 dev->vframes_overflow = 0;
750 dev->vframes_incomplete = 0;
751 dev->vframes_dropped = 0;
753 dev->queue.min_buffers = min_buffers;
754 dev->queue.max_buffers = max_buffers;
756 dev->vsettings.fps = fps;
758 v4l2_set_control_default(dev, V4L2_CID_HFLIP, hflip);
759 v4l2_set_control_default(dev, V4L2_CID_VFLIP, vflip);
760 v4l2_set_control_default(dev, V4L2_CID_GAIN, gain);
761 v4l2_set_control_default(dev, V4L2_CID_BRIGHTNESS, brightness);
762 v4l2_set_control_default(dev, V4L2_CID_CONTRAST, contrast);
763 v4l2_set_control_default(dev, V4L2_CID_GAMMA, gamma);
764 v4l2_set_control_default(dev, V4L2_CID_SATURATION, saturation);
765 v4l2_set_control_default(dev, V4L2_CID_HUE, hue);
766 v4l2_set_control_default(dev, V4L2_CID_SHARPNESS, sharpness);
767 v4l2_set_control_default(dev, V4L2_CID_RED_BALANCE, red_gain);
768 v4l2_set_control_default(dev, V4L2_CID_BLUE_BALANCE, blue_gain);
769 v4l2_set_control_default(dev, V4L2_CID_EXPOSURE_AUTO, auto_exposure);
770 v4l2_set_control_default(dev, V4L2_CID_AUTOGAIN, auto_gain);
771 v4l2_set_control_default(dev, V4L2_CID_AUTO_WHITE_BALANCE, auto_whitebalance);
772 v4l2_set_control_default(dev, V4L2_CID_EXPOSURE, exposure);
774 if (jpeg == 2) {
775 if (dev->udev->speed == USB_SPEED_HIGH && bandwidth == 8)
776 dev->jpeg = 0;
777 else
778 dev->jpeg = 1;
779 } else
780 dev->jpeg = jpeg;
782 sn9c20x_set_resolution(dev, 640, 480);
783 sn9c20x_set_format(dev, sn9c20x_fmts[0].pix_fmt);
785 return 0;
789 static int input_thread(void *data)
791 struct usb_sn9c20x *dev = (struct usb_sn9c20x *)data;
792 __u8 gpio;
793 int ret, i;
795 DECLARE_WAIT_QUEUE_HEAD(wait);
796 set_freezable();
797 for (;;) {
798 if (kthread_should_stop())
799 break;
801 ret = usb_sn9c20x_control_read(dev, 0x1005, &gpio, 1);
802 if (ret < 0)
803 continue;
805 for (i = 0; i < 8; i++) {
806 if (!(dev->input_gpio & (1 << i)))
807 continue;
809 input_report_key(dev->input_dev,
810 BTN_0 + i,
811 gpio & (1 << i));
812 input_sync(dev->input_dev);
815 wait_event_freezable_timeout(wait,
816 kthread_should_stop(),
817 msecs_to_jiffies(100));
819 return 0;
823 static int sn9c20x_input_init(struct usb_sn9c20x *dev)
825 int ret;
827 dev->input_dev = input_allocate_device();
828 if (!dev->input_dev)
829 return -ENOMEM;
831 dev->input_dev->name = "SN9C20X Webcam";
833 dev->input_dev->phys = kasprintf(GFP_KERNEL, "usb-%s-%s",
834 dev->udev->bus->bus_name,
835 dev->udev->devpath);
837 if (!dev->input_dev->phys)
838 return -ENOMEM;
840 usb_to_input_id(dev->udev, &dev->input_dev->id);
841 dev->input_dev->dev.parent = &dev->udev->dev;
843 set_bit(EV_KEY, dev->input_dev->evbit);
844 set_bit(BTN_0, dev->input_dev->keybit);
845 set_bit(BTN_1, dev->input_dev->keybit);
846 set_bit(BTN_2, dev->input_dev->keybit);
847 set_bit(BTN_3, dev->input_dev->keybit);
848 set_bit(BTN_4, dev->input_dev->keybit);
849 set_bit(BTN_5, dev->input_dev->keybit);
850 set_bit(BTN_6, dev->input_dev->keybit);
851 set_bit(BTN_7, dev->input_dev->keybit);
853 ret = input_register_device(dev->input_dev);
854 if (ret)
855 return ret;
857 dev->input_task = kthread_run(input_thread, dev, "sn9c20x/%d",
858 dev->vdev->minor);
860 if (IS_ERR(dev->input_task))
861 return -EINVAL;
863 return 0;
866 static void sn9c20x_input_cleanup(struct usb_sn9c20x *dev)
868 if (!IS_ERR(dev->input_task))
869 kthread_stop(dev->input_task);
871 if (dev->input_dev != NULL) {
872 input_unregister_device(dev->input_dev);
873 kfree(dev->input_dev->phys);
874 input_free_device(dev->input_dev);
875 dev->input_dev = NULL;
880 * @brief Load the driver
882 * @param interface
883 * @param id
885 * @returns 0 if all is OK
887 * This function detects the device and allocate the buffers for the device
888 * and the video interface.
890 static int usb_sn9c20x_probe(struct usb_interface *interface, const struct usb_device_id *id)
892 int ret;
894 int vendor_id;
895 int product_id;
896 int bNumInterfaces;
898 struct usb_sn9c20x *dev = NULL;
899 struct usb_device *udev = interface_to_usbdev(interface);
901 /* Get USB VendorID and ProductID */
902 vendor_id = le16_to_cpu(udev->descriptor.idVendor);
903 product_id = le16_to_cpu(udev->descriptor.idProduct);
905 /* Check if we can handle this device */
906 UDIA_DEBUG("Probe function called with VendorID=%04X, ProductID=%04X and InterfaceNumber=%d\n",
907 vendor_id, product_id, interface->cur_altsetting->desc.bInterfaceNumber);
909 UDIA_INFO("SN9C20X USB 2.0 Webcam - %04X:%04X plugged-in.\n",
910 vendor_id, product_id);
914 // Allocate structure, initialize pointers, mutexes, etc.
915 // and link it to the usb_device
917 dev = kzalloc(sizeof(struct usb_sn9c20x), GFP_KERNEL);
919 if (dev == NULL) {
920 UDIA_ERROR("Out of memory !\n");
921 ret = -ENOMEM;
922 goto error;
925 kref_init(&dev->vopen);
927 dev->udev = udev;
928 dev->interface = interface;
930 /* Read the product release */
931 dev->release = le16_to_cpu(udev->descriptor.bcdDevice);
932 UDIA_DEBUG("Release: %04x\n", dev->release);
934 /* How many interfaces (1 or 3) ? */
935 bNumInterfaces = udev->config->desc.bNumInterfaces;
936 UDIA_DEBUG("Number of interfaces : %d\n", bNumInterfaces);
938 dev->camera.sensor = id->driver_info & 0xFF;
939 dev->camera.address = (id->driver_info >> 8) & 0xFF;
941 /* Initialize the camera */
942 ret = sn9c20x_initialize(dev);
943 if (ret < 0)
944 goto error;
946 /* Initialize the video device */
947 dev->vdev = video_device_alloc();
949 if (!dev->vdev) {
950 ret = -ENOMEM;
951 goto free_dev;
954 /* Register the video device */
955 ret = v4l_sn9c20x_register_video_device(dev);
957 if (ret)
958 goto free_dev;
960 /* Create the entries in the sys filesystem */
961 sn9c20x_create_sysfs_files(dev->vdev);
963 sn9c20x_create_debugfs_files(dev);
965 #ifdef CONFIG_SN9C20X_EVDEV
966 ret = sn9c20x_input_init(dev);
967 if (ret < 0)
968 goto free_dev;
969 #endif
971 /* Save our data pointer in this interface device */
972 usb_set_intfdata(interface, dev);
974 usb_sn9c20x_default_settings(dev);
977 return 0;
979 free_dev:
980 kref_put(&dev->vopen, usb_sn9c20x_delete);
981 error:
982 return ret;
985 void usb_sn9c20x_delete(struct kref *kref)
987 struct usb_sn9c20x *dev;
988 dev = container_of(kref, struct usb_sn9c20x, vopen);
990 if (dev->vdev != NULL) {
991 sn9c20x_remove_sysfs_files(dev->vdev);
992 sn9c20x_remove_debugfs_files(dev);
993 v4l_sn9c20x_unregister_video_device(dev);
995 #ifdef CONFIG_SN9C20X_EVDEV
996 sn9c20x_input_cleanup(dev);
997 #endif
998 kfree(dev);
1002 * @param interface
1004 * @brief This function is called when the device is disconnected
1005 * or when the kernel module is unloaded.
1007 static void usb_sn9c20x_disconnect(struct usb_interface *interface)
1009 struct usb_sn9c20x *dev = usb_get_intfdata(interface);
1011 UDIA_INFO("SN9C20X USB 2.0 Webcam unplugged\n");
1013 usb_set_intfdata(interface, NULL);
1015 mutex_lock(&open_lock);
1016 kref_put(&dev->vopen, usb_sn9c20x_delete);
1017 mutex_unlock(&open_lock);
1020 static int usb_sn9c20x_suspend(struct usb_interface *intf, pm_message_t message)
1022 struct usb_sn9c20x *dev = usb_get_intfdata(intf);
1024 UDIA_INFO("Suspending interface: %u\n",
1025 intf->cur_altsetting->desc.bInterfaceNumber);
1027 if (dev->interface != intf)
1028 return -EINVAL;
1030 if (!sn9c20x_queue_streaming(&dev->queue))
1031 return 0;
1033 dev->frozen = 1;
1034 usb_sn9c20x_uninit_urbs(dev, 0);
1035 usb_set_interface(dev->udev, 0, 0);
1036 return 0;
1041 static int _usb_sn9c20x_resume(struct usb_interface *intf, int reset)
1043 struct usb_sn9c20x *dev = usb_get_intfdata(intf);
1045 UDIA_INFO("Resuming interface: %u\n",
1046 intf->cur_altsetting->desc.bInterfaceNumber);
1048 if (dev->interface != intf)
1049 return -EINVAL;
1051 if (reset && sn9c20x_reset_device(dev) < 0)
1052 return -EINVAL;
1054 if (!sn9c20x_queue_streaming(&dev->queue))
1055 return 0;
1057 dev->frozen = 0;
1058 if (usb_sn9c20x_init_urbs(dev) < 0)
1059 sn9c20x_queue_enable(&dev->queue, 0);
1061 sn9c20x_enable_video(dev, 1);
1062 return 0;
1066 static int usb_sn9c20x_resume(struct usb_interface *intf)
1068 UDIA_DEBUG("usb_sn9c20x_resume()\n");
1069 return _usb_sn9c20x_resume(intf, 0);
1072 static int usb_sn9c20x_reset_resume(struct usb_interface *intf)
1074 UDIA_DEBUG("usb_sn9c20x_reset_resume()\n");
1075 return _usb_sn9c20x_resume(intf, 1);
1079 * @var usb_sn9c20x_driver
1081 * This variable contains some callback
1083 static struct usb_driver usb_sn9c20x_driver = {
1084 .name = "sn9c20x",
1085 .probe = usb_sn9c20x_probe,
1086 .disconnect = usb_sn9c20x_disconnect,
1087 .suspend = usb_sn9c20x_suspend,
1088 .resume = usb_sn9c20x_resume,
1089 .reset_resume = usb_sn9c20x_reset_resume,
1090 .id_table = sn9c20x_table,
1093 module_param(fps, byte, 0444); /**< @brief Module parameter frames per second */
1094 module_param(bulk, byte, 0444);
1095 module_param(jpeg, byte, 0444);
1096 module_param(bandwidth, byte, 0444);
1097 module_param(hflip, byte, 0444); /**< @brief Module parameter horizontal flip process */
1098 module_param(vflip, byte, 0444); /**< @brief Module parameter vertical flip process */
1099 module_param(flip_detect, byte, 0444); /**< @brief Module parameter flip detect */
1100 module_param(auto_exposure, byte, 0444); /**< @brief Module parameter automatic exposure control */
1101 module_param(auto_gain, byte, 0444); /**< @brief Module parameter automatic gain control */
1102 module_param(auto_whitebalance, byte, 0444); /**< @brief Module parameter automatic whitebalance control */
1103 module_param(brightness, ushort, 0444); /**< @brief Module parameter brightness */
1104 module_param(gamma, ushort, 0444); /**< @brief Module parameter gamma */
1105 module_param(saturation, ushort, 0444); /**< @brief Module parameter saturation */
1106 module_param(contrast, ushort, 0444); /**< @brief Module parameter contrast */
1107 module_param(hue, short, 0444); /**< @brief Module parameter hue */
1108 module_param(exposure, ushort, 0444); /**< @brief Module parameter exposure */
1109 module_param(sharpness, ushort, 0444); /**< @brief Module parameter sharpness */
1110 module_param(red_gain, ushort, 0444); /**< @brief Module parameter red gain */
1111 module_param(blue_gain, ushort, 0444); /**< @brief Module parameter blue gain */
1112 module_param(gain, ushort, 0444); /**< @brief Module parameter gain */
1114 module_param(min_buffers, byte, 0444);
1115 module_param(max_buffers, byte, 0444);
1117 module_param(log_level, byte, 0444);
1120 * @returns 0 if all is OK
1122 * @brief Initialize the driver.
1124 * This function is called at first.
1125 * This function permits to define the default values from the command line.
1127 static int __init usb_sn9c20x_init(void)
1129 int result;
1131 UDIA_DEBUG(DRIVER_DESC " initializing\n");
1133 sn9c20x_init_debugfs();
1135 if (fps < 10 || fps > 30) {
1136 UDIA_WARNING("Framerate out of bounds [10-30]! Defaulting to 25\n");
1137 fps = 25;
1140 if (bandwidth < 1 || bandwidth > 8) {
1141 UDIA_WARNING("Bandwidth out of bounds [1-8]! Defaulting to 8\n");
1142 bandwidth = 8;
1145 if (bulk != 0 && bulk != 1) {
1146 UDIA_WARNING("Bulk transfer should be 0 or 1! Defaulting to 0\n");
1147 bulk = 0;
1150 if (jpeg > 2) {
1151 UDIA_WARNING("JPEG should be 0 or 1 or 2! Defaulting to 2\n");
1152 jpeg = 2;
1155 if (vflip != 0 && vflip != 1) {
1156 UDIA_WARNING("Vertical flip should be 0 or 1! Defaulting to 0\n");
1157 vflip = 0;
1160 if (hflip != 0 && hflip != 1) {
1161 UDIA_WARNING("Horizontal flip should be 0 or 1! Defaulting to 0\n");
1162 hflip = 0;
1165 if (sharpness > 0x3f) {
1166 UDIA_WARNING("Sharpness should be 0 to 63 ! Defaulting to 31\n");
1167 sharpness = 0x1f;
1170 if (red_gain > 0x7f) {
1171 UDIA_WARNING("Red Gain should be 0 to 127 ! Defaulting to 31\n");
1172 red_gain = 31;
1175 if (blue_gain > 0x7f) {
1176 UDIA_WARNING("Blue Gain should be 0 to 127 ! Defaulting to 31\n");
1177 blue_gain = 31;
1180 if (hue > 180 || hue < -180) {
1181 UDIA_WARNING("Hue should be between -180 and 180 ! Defaulting to 0\n");
1182 hue = 0;
1185 if (auto_exposure != 0 && auto_exposure != 1) {
1186 UDIA_WARNING("Automatic exposure should be 0 or 1! "
1187 "Defaulting to 0\n");
1188 auto_exposure = 1;
1191 if (auto_gain != 0 && auto_gain != 1) {
1192 UDIA_WARNING("Automatic gain should be 0 or 1! "
1193 "Defaulting to 0\n");
1194 auto_gain = 0;
1197 if (auto_whitebalance != 0 && auto_whitebalance != 1) {
1198 UDIA_WARNING("Automatic whitebalance should be 0 or 1! "
1199 "Defaulting to 1\n");
1200 auto_whitebalance = 1;
1203 if (min_buffers < 2) {
1204 UDIA_WARNING("Minimum buffers can't be less then 2! "
1205 "Defaulting to 2\n");
1206 min_buffers = 2;
1210 if (min_buffers > max_buffers) {
1211 UDIA_WARNING("Minimum buffers must be less then or equal to "
1212 "max buffers! Defaulting to 2, 10\n");
1213 min_buffers = 2;
1214 max_buffers = 5;
1217 /* Register the driver with the USB subsystem */
1218 result = usb_register(&usb_sn9c20x_driver);
1220 if (result)
1221 UDIA_ERROR("usb_register failed ! Error number %d\n", result);
1223 UDIA_INFO(DRIVER_DESC " " DRIVER_VERSION " loaded\n");
1225 return result;
1230 * @brief Close the driver
1232 * This function is called at last when you unload the driver.
1234 static void __exit usb_sn9c20x_exit(void)
1236 UDIA_INFO("usb_sn9c20x_exit: SN9C20X USB 2.0 webcam driver unloaded\n");
1238 sn9c20x_uninit_debugfs();
1240 /* Deregister this driver with the USB subsystem */
1241 usb_deregister(&usb_sn9c20x_driver);
1245 module_init(usb_sn9c20x_init); /**< @brief Module initialize */
1246 module_exit(usb_sn9c20x_exit); /**< @brief Module exit */
1249 MODULE_PARM_DESC(fps, "Frames per second [10-30]"); /**< @brief Description of 'fps' parameter */
1250 MODULE_PARM_DESC(jpeg, "Enable JPEG support (default is auto-detect)");
1251 MODULE_PARM_DESC(bulk, "Enable Bulk transfer (default is to use ISOC)");
1252 MODULE_PARM_DESC(bandwidth, "Bandwidth Setting (only for ISOC)");
1253 MODULE_PARM_DESC(hflip, "Horizontal image flip"); /**< @brief Description of 'hflip' parameter */
1254 MODULE_PARM_DESC(vflip, "Vertical image flip"); /**< @brief Description of 'vflip' parameter */
1255 MODULE_PARM_DESC(flip_detect, "Image flip detection"); /**< @brief Description of 'vflip_detect' parameter */
1256 MODULE_PARM_DESC(auto_exposure, "Automatic exposure control"); /**< @brief Description of 'auto_exposure' parameter */
1257 MODULE_PARM_DESC(auto_gain, "Automatic gain control"); /**< @brief Description of 'auto_gain' parameter */
1258 MODULE_PARM_DESC(auto_whitebalance, "Automatic whitebalance"); /**< @brief Description of 'auto_whitebalance' parameter */
1259 MODULE_PARM_DESC(brightness, "Brightness setting"); /**< @brief Description of 'brightness' parameter */
1260 MODULE_PARM_DESC(gamma, "Gamma setting"); /**< @brief Description of 'gamma' parameter */
1261 MODULE_PARM_DESC(saturation, "Saturation setting"); /**< @brief Description of 'saturation' parameter */
1262 MODULE_PARM_DESC(hue, "Hue setting"); /**< @brief Description of 'hue' parameter */
1263 MODULE_PARM_DESC(exposure, "Exposure setting"); /**< @brief Description of 'exposure' parameter */
1264 MODULE_PARM_DESC(gain, "Gain setting"); /**< @brief Description of 'gain' parameter */
1265 MODULE_PARM_DESC(contrast, "Contrast setting"); /**< @brief Description of 'contrast' parameter */
1266 MODULE_PARM_DESC(sharpness, "Sharpness setting"); /**< @brief Description of 'sharpness' parameter */
1267 MODULE_PARM_DESC(red_gain, "Red Gain setting"); /**< @brief Description of 'Red Gain' parameter */
1268 MODULE_PARM_DESC(blue_gain, "Blue Gain setting"); /**< @brief Description of 'Blue Gain' parameter */
1270 MODULE_PARM_DESC(min_buffers, "Minimum number of image buffers");
1271 MODULE_PARM_DESC(max_buffers, "Maximum number of image buffers");
1272 MODULE_PARM_DESC(log_level, " <n>\n"
1273 "Driver log level\n"
1274 "1 = info (default)\n"
1275 "2 = warning\n"
1276 "4 = error\n"
1277 "8 = debug\n"
1278 "16 = stream\n");
1280 MODULE_LICENSE("GPL"); /**< @brief Driver is under licence GPL */
1281 MODULE_AUTHOR(DRIVER_AUTHOR); /**< @brief Driver is written by Nicolas VIVIEN */
1282 MODULE_DESCRIPTION(DRIVER_DESC); /**< @brief Define the description of the driver */
1283 MODULE_SUPPORTED_DEVICE(DRIVER_SUPPORT); /**< @brief List of supported device */