3 * @author Nicolas VIVIEN
6 * @brief Driver for SN9C20X USB video camera
8 * @note Copyright (C) Nicolas VIVIEN
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
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>
45 #include "sn9c20x-bridge.h"
47 #include "omnivision.h"
51 * Module parameter to set frame per second
57 * Module parameter to enable/disable bulk transfers
63 * Module parameter to enable/disable JPEG format
69 * Module parameter to set the available bandwidth via the alternate setting
71 static __u8 bandwidth
= 8;
75 * Module parameter to enable/disable the horizontal flip process
81 * Module parameter to enable/disable vflip detection
83 static __u8 flip_detect
;
87 * Module parameter to enable/disable the vertical flip process
93 * Module parameter to set the brightness
95 static __u16 brightness
= SN9C20X_PERCENT(50, 0xFF);
99 * Module parameter to set the gamma
101 static __u16 gamma
= SN9C20X_PERCENT(20, 0xFF);
105 * Module parameter to set the contrast
107 static __u16 contrast
= SN9C20X_PERCENT(50, 0xFF);
111 * Module parameter to set the exposure
113 static __u16 exposure
= SN9C20X_PERCENT(20, 0xFF);
117 * Module parameter to set the gain
119 static __u16 gain
= SN9C20X_PERCENT(20, 0xFF);
123 * Module parameter to set the sharpness
125 static __u16 sharpness
= SN9C20X_PERCENT(50, 0x3F);
129 * Module parameter to set the red gain
131 static __u16 red_gain
= SN9C20X_PERCENT(25, 0x7F);
135 * Module parameter to set the blue gain
137 static __u16 blue_gain
= SN9C20X_PERCENT(25, 0x7F);
141 * Module parameter to set the minimum number of image buffers
143 static __u8 min_buffers
= 2;
147 * Module parameter to set the maximum number of image buffers
149 static __u8 max_buffers
= 5;
153 * Module parameter to set the exposure
155 static __u8 auto_exposure
= 1;
159 * Module parameter to set the gain
161 static __u8 auto_gain
;
165 * @var auto_whitebalance
166 * Module parameter to set the auto-whitebalance
168 static __u8 auto_whitebalance
= 1;
172 * Module parameter to set the log level
179 * Define all the hotplug supported devices by this driver
181 static struct usb_device_id sn9c20x_table
[] = {
182 /* SN9C201 + MI1300 */
183 {SN9C20X_USB_DEVICE(0x0C45, 0x6240, MT9M001_SENSOR
, 0x5d)},
184 /* SN9C201 + MI1310 */
185 {SN9C20X_USB_DEVICE(0x0C45, 0x6242, MT9M111_SENSOR
, 0x5d)},
186 /* SN9C201 + S5K4AAFX */
187 {SN9C20X_USB_DEVICE(0x0C45, 0x6243, 0, 0)},
188 /* SN9C201 + OV9655 */
189 {SN9C20X_USB_DEVICE(0x0C45, 0x6248, OV9655_SENSOR
, 0x30)},
190 /* SN9C201 + CX1332 */
191 {SN9C20X_USB_DEVICE(0x0C45, 0x624B, 0, 0)},
192 /* SN9C201 + MI1320 */
193 {SN9C20X_USB_DEVICE(0x0C45, 0x624C, 0, 0)},
194 /* SN9C201 + SOI968 */
195 {SN9C20X_USB_DEVICE(0x0C45, 0x624E, SOI968_SENSOR
, 0x30)},
196 /* SN9C201 + OV9650 */
197 {SN9C20X_USB_DEVICE(0x0C45, 0x624F, OV9650_SENSOR
, 0x30)},
198 /* SN9C201 + OV9650 */
199 {SN9C20X_USB_DEVICE(0x0C45, 0x6251, OV9650_SENSOR
, 0x30)},
200 /* SN9C201 + OV9650 */
201 {SN9C20X_USB_DEVICE(0x0C45, 0x6253, OV9650_SENSOR
, 0x30)},
202 /* SN9C201 + OV7670ISP */
203 {SN9C20X_USB_DEVICE(0x0C45, 0x6260, OV7670_SENSOR
, 0x21)},
204 /* SN9C201 + OM6802 */
205 {SN9C20X_USB_DEVICE(0x0C45, 0x6262, 0, 0)},
206 /* SN9C201 + MI0360/MT9V111 */
207 {SN9C20X_USB_DEVICE(0x0C45, 0x6270, 0, 0)},
208 /* SN9C201 + S5K53BEB */
209 {SN9C20X_USB_DEVICE(0x0C45, 0x627A, 0, 0)},
210 /* SN9C201 + OV7660 */
211 {SN9C20X_USB_DEVICE(0x0C45, 0x627B, OV7660_SENSOR
, 0x21)},
212 /* SN9C201 + HV7131R */
213 {SN9C20X_USB_DEVICE(0x0C45, 0x627C, HV7131R_SENSOR
, 0x11)},
215 {SN9C20X_USB_DEVICE(0x0C45, 0x627F, OV9650_SENSOR
, 0x30)},
216 /* SN9C202 + MI1300 */
217 {SN9C20X_USB_DEVICE(0x0C45, 0x6280, MT9M001_SENSOR
, 0x5d)},
218 /* SN9C202 + MI1310 */
219 {SN9C20X_USB_DEVICE(0x0C45, 0x6282, MT9M111_SENSOR
, 0x5d)},
220 /* SN9C202 + S5K4AAFX */
221 {SN9C20X_USB_DEVICE(0x0C45, 0x6283, 0, 0)},
222 /* SN9C202 + OV9655 */
223 {SN9C20X_USB_DEVICE(0x0C45, 0x6288, OV9655_SENSOR
, 0x30)},
224 /* SN9C202 + ICM107 */
225 {SN9C20X_USB_DEVICE(0x0C45, 0x628A, 0, 0)},
226 /* SN9C202 + CX1332 */
227 {SN9C20X_USB_DEVICE(0x0C45, 0x628B, 0, 0)},
228 /* SN9C202 + MI1320 */
229 {SN9C20X_USB_DEVICE(0x0C45, 0x628C, 0, 0)},
230 /* SN9C202 + SOI968 */
231 {SN9C20X_USB_DEVICE(0x0C45, 0x628E, SOI968_SENSOR
, 0x30)},
232 /* SN9C202 + OV9650 */
233 {SN9C20X_USB_DEVICE(0x0C45, 0x628F, OV9650_SENSOR
, 0x30)},
234 /* SN9C202 + OV7670ISP */
235 {SN9C20X_USB_DEVICE(0x0C45, 0x62A0, OV7670_SENSOR
, 0x21)},
236 /* SN9C202 + OM6802 */
237 {SN9C20X_USB_DEVICE(0x0C45, 0x62A2, 0, 0)},
238 /* SN9C202 + MI0360/MT9V111 */
239 {SN9C20X_USB_DEVICE(0x0C45, 0x62B0, 0, 0)},
240 /* SN9C202 + OV9655 */
241 {SN9C20X_USB_DEVICE(0x0C45, 0x62B3, OV9655_SENSOR
, 0x30)},
242 /* SN9C202 + S5K53BEB */
243 {SN9C20X_USB_DEVICE(0x0C45, 0x62BA, 0, 0)},
244 /* SN9C202 + OV7660 */
245 {SN9C20X_USB_DEVICE(0x0C45, 0x62BB, OV7660_SENSOR
, 0x21)},
246 /* SN9C202 + HV7131R */
247 {SN9C20X_USB_DEVICE(0x0C45, 0x62BC, HV7131R_SENSOR
, 0x11)},
248 /* SN9C202 + OV7663 */
249 {SN9C20X_USB_DEVICE(0x0C45, 0x62BE, 0, 0)},
250 /* => 628f (SN9C202 + OV9650) */
251 {SN9C20X_USB_DEVICE(0x045E, 0x00F4, OV9650_SENSOR
, 0x30)},
252 /* => 627b (SN9C201 + OV7660) */
253 {SN9C20X_USB_DEVICE(0x145F, 0x013D, OV7660_SENSOR
, 0x21)},
254 /* => 62be (SN9C202 + OV7663 + EEPROM) */
255 {SN9C20X_USB_DEVICE(0x04F2, 0xA128, 0, 0)},
256 /* => 627c (SN9C201 + HV7131R) */
257 {SN9C20X_USB_DEVICE(0x0458, 0x7029, HV7131R_SENSOR
, 0x11)},
258 /* SN9C201 + HV7131R (Dino Lite digital microscope)*/
259 {SN9C20X_USB_DEVICE(0xA168, 0x0614, HV7131R_SENSOR
, 0x5d)},
264 MODULE_DEVICE_TABLE(usb
, sn9c20x_table
); /**< Define the supported devices */
266 DEFINE_MUTEX(open_lock
); /**< Define global mutex */
268 struct usb_endpoint_descriptor
*find_endpoint(struct usb_host_interface
*alts
,
272 struct usb_endpoint_descriptor
*ep
;
274 for (i
= 0; i
< alts
->desc
.bNumEndpoints
; ++i
) {
275 ep
= &alts
->endpoint
[i
].desc
;
276 if ((ep
->bEndpointAddress
& 0xf) == epaddr
) {
277 UDIA_DEBUG("Found Endpoint 0x%X\n", epaddr
);
285 * @param dev Device structure
286 * @param ep Usb endpoint structure
288 * @returns 0 if all is OK
290 * @brief Initilize an isochronous pipe.
292 * This function permits to initialize an URB transfert (or isochronous pipe).
294 int usb_sn9c20x_isoc_init(struct usb_sn9c20x
*dev
,
295 struct usb_endpoint_descriptor
*ep
)
298 __u16 iso_max_frame_size
;
300 struct usb_device
*udev
;
304 UDIA_DEBUG("usb_sn9c20x_isoc_init()\n");
307 max_packet_sz(le16_to_cpu(ep
->wMaxPacketSize
)) *
308 hb_multiplier(le16_to_cpu(ep
->wMaxPacketSize
));
309 for (i
= 0; i
< MAX_URBS
; i
++) {
310 urb
= usb_alloc_urb(ISO_FRAMES_PER_DESC
, GFP_KERNEL
);
313 UDIA_ERROR("Failed to allocate URB %d\n", i
);
314 usb_sn9c20x_uninit_urbs(dev
, 1);
320 urb
->pipe
= usb_rcvisocpipe(udev
, ep
->bEndpointAddress
);
321 urb
->transfer_flags
= URB_ISO_ASAP
;
322 urb
->transfer_buffer_length
= iso_max_frame_size
* ISO_FRAMES_PER_DESC
;
323 urb
->complete
= usb_sn9c20x_completion_handler
;
325 urb
->start_frame
= 0;
326 urb
->number_of_packets
= ISO_FRAMES_PER_DESC
;
328 for (j
= 0; j
< ISO_FRAMES_PER_DESC
; j
++) {
329 urb
->iso_frame_desc
[j
].offset
= j
* iso_max_frame_size
;
330 urb
->iso_frame_desc
[j
].length
= iso_max_frame_size
;
333 if (dev
->urbs
[i
].data
== NULL
) {
334 dev
->urbs
[i
].data
= kzalloc(urb
->transfer_buffer_length
,
336 if (dev
->urbs
[i
].data
== NULL
) {
337 usb_sn9c20x_uninit_urbs(dev
, 1);
341 urb
->transfer_buffer
= dev
->urbs
[i
].data
;
342 dev
->urbs
[i
].urb
= urb
;
348 int usb_sn9c20x_bulk_init(struct usb_sn9c20x
*dev
,
349 struct usb_endpoint_descriptor
*ep
)
352 unsigned int pipe
, i
;
355 psize
= max_packet_sz(le16_to_cpu(ep
->wMaxPacketSize
));
356 size
= psize
* ISO_FRAMES_PER_DESC
;
357 pipe
= usb_rcvbulkpipe(dev
->udev
, ep
->bEndpointAddress
);
359 for (i
= 0; i
< MAX_URBS
; ++i
) {
360 urb
= usb_alloc_urb(0, GFP_KERNEL
);
362 usb_sn9c20x_uninit_urbs(dev
, 1);
365 if (dev
->urbs
[i
].data
== NULL
) {
366 dev
->urbs
[i
].data
= kzalloc(size
, GFP_KERNEL
);
367 if (dev
->urbs
[i
].data
== NULL
) {
368 usb_sn9c20x_uninit_urbs(dev
, 1);
373 usb_fill_bulk_urb(urb
, dev
->udev
, pipe
,
374 dev
->urbs
[i
].data
, size
,
375 usb_sn9c20x_completion_handler
,
378 dev
->urbs
[i
].urb
= urb
;
384 int usb_sn9c20x_init_urbs(struct usb_sn9c20x
*dev
)
388 struct usb_endpoint_descriptor
*ep
;
389 struct usb_interface
*intf
= dev
->interface
;
391 ret
= usb_sn9c20x_control_read(dev
, 0x1061, &value
, 1);
399 ep
= find_endpoint(usb_altnum_to_altsetting(intf
, bandwidth
), SN9C20X_VID_ISOC
);
403 ret
= usb_set_interface(dev
->udev
, 0, bandwidth
);
408 ret
= usb_sn9c20x_control_write(dev
, 0x1061, &value
, 1);
412 ret
= usb_sn9c20x_isoc_init(dev
, ep
);
414 ep
= find_endpoint(usb_altnum_to_altsetting(intf
, 0), SN9C20X_BULK
);
418 ret
= usb_set_interface(dev
->udev
, 0, 0);
423 ret
= usb_sn9c20x_control_write(dev
, 0x1061, &value
, 1);
427 ret
= usb_sn9c20x_bulk_init(dev
, ep
);
433 for (i
= 0; i
< MAX_URBS
; i
++) {
434 ret
= usb_submit_urb(dev
->urbs
[i
].urb
, GFP_KERNEL
);
436 UDIA_ERROR("isoc_init() submit_urb %d failed with error %d\n", i
, ret
);
443 * @param dev Device structure
445 * @brief Clean-up all the ISOC buffers
447 * This function permits to clean-up all the ISOC buffers.
449 void usb_sn9c20x_uninit_urbs(struct usb_sn9c20x
*dev
, int free_buffers
)
454 UDIA_DEBUG("Isoc cleanup\n");
459 for (i
= 0; i
< MAX_URBS
; i
++) {
460 urb
= dev
->urbs
[i
].urb
;
465 dev
->urbs
[i
].urb
= NULL
;
467 kfree(dev
->urbs
[i
].data
);
468 dev
->urbs
[i
].data
= NULL
;
473 int usb_sn9c20x_detect_frame(unsigned char *buf
, unsigned int buf_length
)
475 static unsigned char frame_header
[] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
479 if (buf_length
== 64) {
480 if (memcmp(buf
, frame_header
, 6) == 0)
485 for (index
= 0; index
< buf_length
- 63; index
++) {
486 if (memcmp(buf
+ index
, frame_header
, 6) == 0) {
487 UDIA_DEBUG("Found Header at %d\n", index
);
494 void usb_sn9c20x_assemble_video(struct usb_sn9c20x
*dev
,
495 unsigned char *transfer
, unsigned int transfer_length
,
496 struct sn9c20x_buffer
**buffer
)
499 unsigned char *header
;
502 struct sn9c20x_buffer
*buf
= *buffer
;
503 struct sn9c20x_video_queue
*queue
= &dev
->queue
;
505 if (buf
->state
!= SN9C20X_BUF_STATE_ACTIVE
)
506 buf
->state
= SN9C20X_BUF_STATE_ACTIVE
;
508 header_index
= usb_sn9c20x_detect_frame(transfer
, transfer_length
);
509 if (header_index
>= 0) {
510 if (header_index
+ buf
->buf
.bytesused
> buf
->buf
.length
) {
511 UDIA_WARNING("Frame Buffer overflow!\n");
512 dev
->vframes_overflow
++;
513 buf
->state
= SN9C20X_BUF_STATE_DONE
;
515 header_index
= min(buf
->buf
.length
- buf
->buf
.bytesused
,
516 (unsigned int)header_index
);
517 mem
= queue
->mem
+ buf
->buf
.m
.offset
+ buf
->buf
.bytesused
;
518 memcpy(mem
, transfer
, header_index
);
519 buf
->buf
.bytesused
+= header_index
;
520 header
= transfer
+header_index
;
521 /* UDIA_INFO("color window: %dx%d\n",
524 UDIA_INFO("Frame Size: %d\n", buf->buf.bytesused);*/
525 yavg
= ((header
[35] >> 2) & 3)|(header
[20] << 2)|(header
[19] << 10);
526 yavg
+= ((header
[35] >> 4) & 3)|(header
[22] << 2)|(header
[21] << 10);
527 yavg
+= ((header
[35] >> 6) & 3)|(header
[24] << 2)|(header
[23] << 10);
528 yavg
+= (header
[36] & 3)|(header
[26] << 2)|(header
[25] << 10);
529 yavg
+= ((header
[36] >> 2) & 3)|(header
[28] << 2)|(header
[27] << 10);
530 yavg
+= ((header
[36] >> 4) & 3)|(header
[30] << 2)|(header
[29] << 10);
531 yavg
+= ((header
[36] >> 6) & 3)|(header
[32] << 2)|(header
[31] << 10);
532 yavg
+= ((header
[44] >> 4) & 3)|(header
[34] << 2)|(header
[33] << 10);
533 UDIA_DEBUG("AVGY Total: %d (%d)\n", yavg
, yavg
>> 9);
535 atomic_set(&dev
->camera
.yavg
, yavg
);
537 if (buf
->buf
.bytesused
!= 0)
538 buf
->state
= SN9C20X_BUF_STATE_DONE
;
540 if (transfer_length
+ buf
->buf
.bytesused
> buf
->buf
.length
) {
541 UDIA_WARNING("Frame Buffer overflow!\n");
542 dev
->vframes_overflow
++;
543 buf
->state
= SN9C20X_BUF_STATE_DONE
;
545 transfer_length
= min(buf
->buf
.length
- buf
->buf
.bytesused
,
547 mem
= queue
->mem
+ buf
->buf
.m
.offset
+ buf
->buf
.bytesused
;
548 memcpy(mem
, transfer
, transfer_length
);
549 buf
->buf
.bytesused
+= transfer_length
;
551 if (buf
->state
== SN9C20X_BUF_STATE_DONE
||
552 buf
->state
== SN9C20X_BUF_STATE_ERROR
) {
553 buf
= sn9c20x_queue_next_buffer(queue
, buf
);
556 dev
->vframes_dropped
++;
558 if (header_index
+ 64 < transfer_length
) {
559 memcpy(queue
->mem
+ buf
->buf
.m
.offset
,
560 transfer
+ header_index
+ 64,
561 transfer_length
- (header_index
+ 64));
562 buf
->buf
.bytesused
+=
563 transfer_length
- (header_index
+ 64);
569 * @param urb URB structure
571 * @brief ISOC handler
573 * This function is called as an URB transfert is complete (Isochronous pipe).
574 * So, the traitement is done in interrupt time, so it has be fast, not crash,
575 * and not stall. Neat.
577 void usb_sn9c20x_completion_handler(struct urb
*urb
)
583 unsigned char *transfer
= NULL
;
584 unsigned int transfer_length
;
586 struct sn9c20x_buffer
*buf
= NULL
;
587 struct usb_sn9c20x
*dev
= urb
->context
;
588 struct sn9c20x_video_queue
*queue
= &dev
->queue
;
590 UDIA_STREAM("Isoc handler\n");
592 switch (urb
->status
) {
597 UDIA_WARNING("Non-zero status (%d) in video "
598 "completion handler.\n", urb
->status
);
600 case -ENOENT
: /* usb_kill_urb() called. */
604 case -ECONNRESET
: /* usb_unlink_urb() called. */
605 case -ESHUTDOWN
: /* The endpoint is being disabled. */
606 sn9c20x_queue_cancel(queue
, urb
->status
== -ESHUTDOWN
);
610 spin_lock_irqsave(&queue
->irqlock
, flags
);
611 if (!list_empty(&queue
->irqqueue
))
612 buf
= list_first_entry(&queue
->irqqueue
, struct sn9c20x_buffer
,
614 spin_unlock_irqrestore(&queue
->irqlock
, flags
);
616 for (i
= 0; i
< urb
->number_of_packets
; i
++) {
617 if (urb
->iso_frame_desc
[i
].status
!= 0) {
618 /*UDIA_ERROR("Iso frame %d of USB has error %d\n",
619 i, urb->iso_frame_desc[i].status);*/
623 transfer_length
= urb
->iso_frame_desc
[i
].actual_length
;
624 transfer
= urb
->transfer_buffer
+ urb
->iso_frame_desc
[i
].offset
;
628 usb_sn9c20x_assemble_video(dev
, transfer
, transfer_length
, &buf
);
632 usb_sn9c20x_assemble_video(dev
, urb
->transfer_buffer
,
633 urb
->actual_length
, &buf
);
636 ret
= usb_submit_urb(urb
, GFP_ATOMIC
);
639 UDIA_ERROR("Error (%d) re-submitting urb in "
640 "sn9c20x_isoc_handler.\n", ret
);
645 * @param dev Device structure
646 * @param value register to write to
648 * @param length number of bytes
650 * @returns 0 if all is OK
652 * @brief Write a 16-bit value to a 16-bit register
654 * This function permits to write a 16-bit value to a 16-bit register on the USB bus.
656 int usb_sn9c20x_control_write(struct usb_sn9c20x
*dev
, __u16 value
, __u8
*data
, __u16 length
)
659 struct usb_device
*udev
= dev
->udev
;
661 result
= usb_control_msg(udev
, usb_sndctrlpipe(udev
, 0),
663 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_INTERFACE
,
670 if (unlikely(result
< 0))
671 UDIA_ERROR("Write register failed index = 0x%02X\n", value
);
677 * @param dev Device structure
678 * @param index register to read from
680 * @param length number of bytes
682 * @returns 0 if all is OK
684 * @brief Read a 16-bit value from a 16-bit register
686 * This function permits to read a 16-bit value from a 16-bit register on the USB bus.
688 int usb_sn9c20x_control_read(struct usb_sn9c20x
*dev
, __u16 index
, __u8
*data
, __u16 length
)
692 struct usb_device
*udev
= dev
->udev
;
696 result
= usb_control_msg(udev
, usb_rcvctrlpipe(udev
, 0),
698 USB_DIR_IN
| USB_TYPE_VENDOR
| USB_RECIP_INTERFACE
,
705 if (unlikely(result
< 0))
706 UDIA_ERROR("Read register failed 0x%02X\n", index
);
715 * @returns 0 if all is OK
717 * @brief Set the default value about the video settings.
719 * This function permits to set the video settings for each video camera model.
722 static int usb_sn9c20x_default_settings(struct usb_sn9c20x
*dev
)
724 dev
->vframes_overflow
= 0;
725 dev
->vframes_incomplete
= 0;
726 dev
->vframes_dropped
= 0;
728 dev
->queue
.min_buffers
= min_buffers
;
729 dev
->queue
.max_buffers
= max_buffers
;
731 dev
->vsettings
.fps
= fps
;
733 v4l2_set_control_default(dev
, V4L2_CID_HFLIP
, hflip
);
734 v4l2_set_control_default(dev
, V4L2_CID_VFLIP
, vflip
);
735 v4l2_set_control_default(dev
, V4L2_CID_GAIN
, gain
);
736 v4l2_set_control_default(dev
, V4L2_CID_BRIGHTNESS
, brightness
);
737 v4l2_set_control_default(dev
, V4L2_CID_CONTRAST
, contrast
);
738 v4l2_set_control_default(dev
, V4L2_CID_GAMMA
, gamma
);
739 v4l2_set_control_default(dev
, V4L2_CID_SHARPNESS
, sharpness
);
740 v4l2_set_control_default(dev
, V4L2_CID_RED_BALANCE
, red_gain
);
741 v4l2_set_control_default(dev
, V4L2_CID_BLUE_BALANCE
, blue_gain
);
742 v4l2_set_control_default(dev
, V4L2_CID_EXPOSURE_AUTO
, auto_exposure
);
743 v4l2_set_control_default(dev
, V4L2_CID_AUTOGAIN
, auto_gain
);
744 v4l2_set_control_default(dev
, V4L2_CID_AUTO_WHITE_BALANCE
, auto_whitebalance
);
745 v4l2_set_control_default(dev
, V4L2_CID_EXPOSURE
, exposure
);
748 if (dev
->udev
->speed
== USB_SPEED_HIGH
&& bandwidth
== 8)
755 sn9c20x_set_resolution(dev
, 640, 480);
756 sn9c20x_set_format(dev
, sn9c20x_fmts
[0].pix_fmt
);
762 static int input_thread(void *data
)
764 struct usb_sn9c20x
*dev
= (struct usb_sn9c20x
*)data
;
768 DECLARE_WAIT_QUEUE_HEAD(wait
);
771 if (kthread_should_stop())
774 ret
= usb_sn9c20x_control_read(dev
, 0x1005, &gpio
, 1);
778 for (i
= 0; i
< 8; i
++) {
779 if (!(dev
->input_gpio
& (1 << i
)))
782 input_report_key(dev
->input_dev
,
785 input_sync(dev
->input_dev
);
788 wait_event_freezable_timeout(wait
,
789 kthread_should_stop(),
790 msecs_to_jiffies(100));
796 static int sn9c20x_input_init(struct usb_sn9c20x
*dev
)
800 dev
->input_dev
= input_allocate_device();
804 dev
->input_dev
->name
= "SN9C20X Webcam";
806 dev
->input_dev
->phys
= kasprintf(GFP_KERNEL
, "usb-%s-%s",
807 dev
->udev
->bus
->bus_name
,
810 if (!dev
->input_dev
->phys
)
813 usb_to_input_id(dev
->udev
, &dev
->input_dev
->id
);
814 dev
->input_dev
->dev
.parent
= &dev
->udev
->dev
;
816 set_bit(EV_KEY
, dev
->input_dev
->evbit
);
817 set_bit(BTN_0
, dev
->input_dev
->keybit
);
818 set_bit(BTN_1
, dev
->input_dev
->keybit
);
819 set_bit(BTN_2
, dev
->input_dev
->keybit
);
820 set_bit(BTN_3
, dev
->input_dev
->keybit
);
821 set_bit(BTN_4
, dev
->input_dev
->keybit
);
822 set_bit(BTN_5
, dev
->input_dev
->keybit
);
823 set_bit(BTN_6
, dev
->input_dev
->keybit
);
824 set_bit(BTN_7
, dev
->input_dev
->keybit
);
826 ret
= input_register_device(dev
->input_dev
);
830 dev
->input_task
= kthread_run(input_thread
, dev
, "sn9c20x/%d",
833 if (IS_ERR(dev
->input_task
))
839 static void sn9c20x_input_cleanup(struct usb_sn9c20x
*dev
)
841 if (!IS_ERR(dev
->input_task
))
842 kthread_stop(dev
->input_task
);
844 if (dev
->input_dev
!= NULL
) {
845 input_unregister_device(dev
->input_dev
);
846 kfree(dev
->input_dev
->phys
);
847 input_free_device(dev
->input_dev
);
848 dev
->input_dev
= NULL
;
853 * @brief Load the driver
858 * @returns 0 if all is OK
860 * This function detects the device and allocate the buffers for the device
861 * and the video interface.
863 static int usb_sn9c20x_probe(struct usb_interface
*interface
, const struct usb_device_id
*id
)
871 struct usb_sn9c20x
*dev
= NULL
;
872 struct usb_device
*udev
= interface_to_usbdev(interface
);
874 /* Get USB VendorID and ProductID */
875 vendor_id
= le16_to_cpu(udev
->descriptor
.idVendor
);
876 product_id
= le16_to_cpu(udev
->descriptor
.idProduct
);
878 /* Check if we can handle this device */
879 UDIA_DEBUG("Probe function called with VendorID=%04X, ProductID=%04X and InterfaceNumber=%d\n",
880 vendor_id
, product_id
, interface
->cur_altsetting
->desc
.bInterfaceNumber
);
882 UDIA_INFO("SN9C20X USB 2.0 Webcam - %04X:%04X plugged-in.\n",
883 vendor_id
, product_id
);
887 // Allocate structure, initialize pointers, mutexes, etc.
888 // and link it to the usb_device
890 dev
= kzalloc(sizeof(struct usb_sn9c20x
), GFP_KERNEL
);
893 UDIA_ERROR("Out of memory !\n");
898 kref_init(&dev
->vopen
);
901 dev
->interface
= interface
;
903 /* Read the product release */
904 dev
->release
= le16_to_cpu(udev
->descriptor
.bcdDevice
);
905 UDIA_DEBUG("Release: %04x\n", dev
->release
);
907 /* How many interfaces (1 or 3) ? */
908 bNumInterfaces
= udev
->config
->desc
.bNumInterfaces
;
909 UDIA_DEBUG("Number of interfaces : %d\n", bNumInterfaces
);
911 dev
->camera
.sensor
= id
->driver_info
& 0xFF;
912 dev
->camera
.address
= (id
->driver_info
>> 8) & 0xFF;
914 /* Initialize the camera */
915 ret
= sn9c20x_initialize(dev
);
919 /* Initialize the video device */
920 dev
->vdev
= video_device_alloc();
927 /* Register the video device */
928 ret
= v4l_sn9c20x_register_video_device(dev
);
933 /* Create the entries in the sys filesystem */
934 sn9c20x_create_sysfs_files(dev
->vdev
);
936 sn9c20x_create_debugfs_files(dev
);
938 #ifdef CONFIG_SN9C20X_EVDEV
939 ret
= sn9c20x_input_init(dev
);
944 /* Save our data pointer in this interface device */
945 usb_set_intfdata(interface
, dev
);
947 usb_sn9c20x_default_settings(dev
);
953 kref_put(&dev
->vopen
, usb_sn9c20x_delete
);
958 void usb_sn9c20x_delete(struct kref
*kref
)
960 struct usb_sn9c20x
*dev
;
961 dev
= container_of(kref
, struct usb_sn9c20x
, vopen
);
963 if (dev
->vdev
!= NULL
) {
964 sn9c20x_remove_sysfs_files(dev
->vdev
);
965 sn9c20x_remove_debugfs_files(dev
);
966 v4l_sn9c20x_unregister_video_device(dev
);
968 #ifdef CONFIG_SN9C20X_EVDEV
969 sn9c20x_input_cleanup(dev
);
977 * @brief This function is called when the device is disconnected
978 * or when the kernel module is unloaded.
980 static void usb_sn9c20x_disconnect(struct usb_interface
*interface
)
982 struct usb_sn9c20x
*dev
= usb_get_intfdata(interface
);
984 UDIA_INFO("SN9C20X USB 2.0 Webcam unplugged\n");
986 usb_set_intfdata(interface
, NULL
);
988 mutex_lock(&open_lock
);
989 kref_put(&dev
->vopen
, usb_sn9c20x_delete
);
990 mutex_unlock(&open_lock
);
993 static int usb_sn9c20x_suspend(struct usb_interface
*intf
, pm_message_t message
)
995 struct usb_sn9c20x
*dev
= usb_get_intfdata(intf
);
997 UDIA_INFO("Suspending interface: %u\n",
998 intf
->cur_altsetting
->desc
.bInterfaceNumber
);
1000 if (dev
->interface
!= intf
)
1003 if (!sn9c20x_queue_streaming(&dev
->queue
))
1007 usb_sn9c20x_uninit_urbs(dev
, 0);
1008 usb_set_interface(dev
->udev
, 0, 0);
1014 static int _usb_sn9c20x_resume(struct usb_interface
*intf
, int reset
)
1016 struct usb_sn9c20x
*dev
= usb_get_intfdata(intf
);
1018 UDIA_INFO("Resuming interface: %u\n",
1019 intf
->cur_altsetting
->desc
.bInterfaceNumber
);
1021 if (dev
->interface
!= intf
)
1024 if (reset
&& sn9c20x_reset_device(dev
) < 0)
1027 if (!sn9c20x_queue_streaming(&dev
->queue
))
1031 if (usb_sn9c20x_init_urbs(dev
) < 0)
1032 sn9c20x_queue_enable(&dev
->queue
, 0);
1034 sn9c20x_enable_video(dev
, 1);
1039 static int usb_sn9c20x_resume(struct usb_interface
*intf
)
1041 UDIA_DEBUG("usb_sn9c20x_resume()\n");
1042 return _usb_sn9c20x_resume(intf
, 0);
1045 static int usb_sn9c20x_reset_resume(struct usb_interface
*intf
)
1047 UDIA_DEBUG("usb_sn9c20x_reset_resume()\n");
1048 return _usb_sn9c20x_resume(intf
, 1);
1052 * @var usb_sn9c20x_driver
1054 * This variable contains some callback
1056 static struct usb_driver usb_sn9c20x_driver
= {
1058 .probe
= usb_sn9c20x_probe
,
1059 .disconnect
= usb_sn9c20x_disconnect
,
1060 .suspend
= usb_sn9c20x_suspend
,
1061 .resume
= usb_sn9c20x_resume
,
1062 .reset_resume
= usb_sn9c20x_reset_resume
,
1063 .id_table
= sn9c20x_table
,
1066 module_param(fps
, byte
, 0444); /**< @brief Module parameter frames per second */
1067 module_param(bulk
, byte
, 0444);
1068 module_param(jpeg
, byte
, 0444);
1069 module_param(bandwidth
, byte
, 0444);
1070 module_param(hflip
, byte
, 0444); /**< @brief Module parameter horizontal flip process */
1071 module_param(vflip
, byte
, 0444); /**< @brief Module parameter vertical flip process */
1072 module_param(flip_detect
, byte
, 0444); /**< @brief Module parameter flip detect */
1073 module_param(auto_exposure
, byte
, 0444); /**< @brief Module parameter automatic exposure control */
1074 module_param(auto_gain
, byte
, 0444); /**< @brief Module parameter automatic gain control */
1075 module_param(auto_whitebalance
, byte
, 0444); /**< @brief Module parameter automatic whitebalance control */
1076 module_param(brightness
, ushort
, 0444); /**< @brief Module parameter brightness */
1077 module_param(gamma
, ushort
, 0444); /**< @brief Module parameter gamma */
1078 module_param(contrast
, ushort
, 0444); /**< @brief Module parameter contrast */
1079 module_param(exposure
, ushort
, 0444); /**< @brief Module parameter exposure */
1080 module_param(sharpness
, ushort
, 0444); /**< @brief Module parameter sharpness */
1081 module_param(red_gain
, ushort
, 0444); /**< @brief Module parameter red gain */
1082 module_param(blue_gain
, ushort
, 0444); /**< @brief Module parameter blue gain */
1084 module_param(min_buffers
, byte
, 0444);
1085 module_param(max_buffers
, byte
, 0444);
1087 module_param(log_level
, byte
, 0444);
1090 * @returns 0 if all is OK
1092 * @brief Initialize the driver.
1094 * This function is called at first.
1095 * This function permits to define the default values from the command line.
1097 static int __init
usb_sn9c20x_init(void)
1101 UDIA_DEBUG(DRIVER_DESC
" initializing\n");
1103 sn9c20x_init_debugfs();
1105 if (fps
< 10 || fps
> 30) {
1106 UDIA_WARNING("Framerate out of bounds [10-30]! Defaulting to 25\n");
1110 if (bandwidth
< 1 || bandwidth
> 8) {
1111 UDIA_WARNING("Bandwidth out of bounds [1-8]! Defaulting to 8\n");
1115 if (bulk
!= 0 && bulk
!= 1) {
1116 UDIA_WARNING("Bulk transfer should be 0 or 1! Defaulting to 0\n");
1121 UDIA_WARNING("JPEG should be 0 or 1 or 2! Defaulting to 2\n");
1125 if (vflip
!= 0 && vflip
!= 1) {
1126 UDIA_WARNING("Vertical flip should be 0 or 1! Defaulting to 0\n");
1130 if (hflip
!= 0 && hflip
!= 1) {
1131 UDIA_WARNING("Horizontal flip should be 0 or 1! Defaulting to 0\n");
1135 if (sharpness
> 0x3f) {
1136 UDIA_WARNING("Sharpness should be 0 to 63 ! Defaulting to 31\n");
1140 if (red_gain
> 0x7f) {
1141 UDIA_WARNING("Red Gain should be 0 to 127 ! Defaulting to 31\n");
1145 if (blue_gain
> 0x7f) {
1146 UDIA_WARNING("Blue Gain should be 0 to 127 ! Defaulting to 31\n");
1150 if (auto_exposure
!= 0 && auto_exposure
!= 1) {
1151 UDIA_WARNING("Automatic exposure should be 0 or 1! "
1152 "Defaulting to 0\n");
1156 if (auto_gain
!= 0 && auto_gain
!= 1) {
1157 UDIA_WARNING("Automatic gain should be 0 or 1! "
1158 "Defaulting to 0\n");
1162 if (auto_whitebalance
!= 0 && auto_whitebalance
!= 1) {
1163 UDIA_WARNING("Automatic whitebalance should be 0 or 1! "
1164 "Defaulting to 1\n");
1165 auto_whitebalance
= 1;
1168 if (min_buffers
< 2) {
1169 UDIA_WARNING("Minimum buffers can't be less then 2! "
1170 "Defaulting to 2\n");
1175 if (min_buffers
> max_buffers
) {
1176 UDIA_WARNING("Minimum buffers must be less then or equal to "
1177 "max buffers! Defaulting to 2, 10\n");
1182 /* Register the driver with the USB subsystem */
1183 result
= usb_register(&usb_sn9c20x_driver
);
1186 UDIA_ERROR("usb_register failed ! Error number %d\n", result
);
1188 UDIA_INFO(DRIVER_DESC
" " DRIVER_VERSION
" loaded\n");
1195 * @brief Close the driver
1197 * This function is called at last when you unload the driver.
1199 static void __exit
usb_sn9c20x_exit(void)
1201 UDIA_INFO("usb_sn9c20x_exit: SN9C20X USB 2.0 webcam driver unloaded\n");
1203 sn9c20x_uninit_debugfs();
1205 /* Deregister this driver with the USB subsystem */
1206 usb_deregister(&usb_sn9c20x_driver
);
1210 module_init(usb_sn9c20x_init
); /**< @brief Module initialize */
1211 module_exit(usb_sn9c20x_exit
); /**< @brief Module exit */
1214 MODULE_PARM_DESC(fps
, "Frames per second [10-30]"); /**< @brief Description of 'fps' parameter */
1215 MODULE_PARM_DESC(jpeg
, "Enable JPEG support (default is auto-detect)");
1216 MODULE_PARM_DESC(bulk
, "Enable Bulk transfer (default is to use ISOC)");
1217 MODULE_PARM_DESC(bandwidth
, "Bandwidth Setting (only for ISOC)");
1218 MODULE_PARM_DESC(hflip
, "Horizontal image flip"); /**< @brief Description of 'hflip' parameter */
1219 MODULE_PARM_DESC(vflip
, "Vertical image flip"); /**< @brief Description of 'vflip' parameter */
1220 MODULE_PARM_DESC(flip_detect
, "Image flip detection"); /**< @brief Description of 'vflip_detect' parameter */
1221 MODULE_PARM_DESC(auto_exposure
, "Automatic exposure control"); /**< @brief Description of 'auto_exposure' parameter */
1222 MODULE_PARM_DESC(auto_gain
, "Automatic gain control"); /**< @brief Description of 'auto_gain' parameter */
1223 MODULE_PARM_DESC(auto_whitebalance
, "Automatic whitebalance"); /**< @brief Description of 'auto_whitebalance' parameter */
1224 MODULE_PARM_DESC(brightness
, "Brightness setting"); /**< @brief Description of 'brightness' parameter */
1225 MODULE_PARM_DESC(gamma
, "Gamma setting"); /**< @brief Description of 'gamma' parameter */
1226 MODULE_PARM_DESC(exposure
, "Exposure setting"); /**< @brief Description of 'exposure' parameter */
1227 MODULE_PARM_DESC(gain
, "Gain setting"); /**< @brief Description of 'gain' parameter */
1228 MODULE_PARM_DESC(contrast
, "Contrast setting"); /**< @brief Description of 'contrast' parameter */
1229 MODULE_PARM_DESC(sharpness
, "Sharpness setting"); /**< @brief Description of 'sharpness' parameter */
1230 MODULE_PARM_DESC(red_gain
, "Red Gain setting"); /**< @brief Description of 'Red Gain' parameter */
1231 MODULE_PARM_DESC(blue_gain
, "Blue Gain setting"); /**< @brief Description of 'Blue Gain' parameter */
1233 MODULE_PARM_DESC(min_buffers
, "Minimum number of image buffers");
1234 MODULE_PARM_DESC(max_buffers
, "Maximum number of image buffers");
1235 MODULE_PARM_DESC(log_level
, " <n>\n"
1236 "Driver log level\n"
1237 "1 = info (default)\n"
1243 MODULE_LICENSE("GPL"); /**< @brief Driver is under licence GPL */
1244 MODULE_AUTHOR(DRIVER_AUTHOR
); /**< @brief Driver is written by Nicolas VIVIEN */
1245 MODULE_DESCRIPTION(DRIVER_DESC
); /**< @brief Define the description of the driver */
1246 MODULE_SUPPORTED_DEVICE(DRIVER_SUPPORT
); /**< @brief List of supported device */