3 * @author Nicolas VIVIEN
7 * @brief Driver for Microdia USB video camera
9 * @note Copyright (C) Nicolas VIVIEN
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/kernel.h>
31 #include <linux/version.h>
32 #include <linux/errno.h>
33 #include <linux/slab.h>
34 #include <linux/kref.h>
35 #include <linux/stat.h>
37 #include <linux/usb.h>
38 #include <media/v4l2-common.h>
47 * Module parameter to set frame per second
53 * Module parameter to enable/disable the horizontal flip process
59 * Module parameter to enable/disable vflip detection
61 static int flip_detect
= 0;
65 * Module parameter to enable/disable the vertical flip process
71 * Module parameter to set the brightness
73 static int brightness
= MICRODIA_PERCENT(50, 0xFFFF);
77 * Module parameter to set the whiteness
79 static int whiteness
= MICRODIA_PERCENT(20, 0xFFFF);
83 * Module parameter to set the contrast
85 static int contrast
= MICRODIA_PERCENT(50, 0xFFFF);
89 * Module parameter to set the exposure
91 static int exposure
= MICRODIA_PERCENT(20, 0xFFFF);
95 * Module parameter to set the sharpness
97 static int sharpness
= MICRODIA_PERCENT(50, 0x3F);
101 * Module parameter to set the red/green/blue gain
103 static int rgb_gain
= MICRODIA_PERCENT(25, 0x7F) |
104 (MICRODIA_PERCENT(25, 0x7F) << 8) |
105 (MICRODIA_PERCENT(25, 0x7F) << 16);
109 * Module parameter to set the minimum number of image buffers
111 static int min_buffers
= 2;
115 * Module parameter to set the maximum number of image buffers
117 static int max_buffers
= 5;
121 * Module parameter to set the exposure
123 static int auto_exposure
= 1;
126 * @var auto_whitebalance
127 * Module parameter to set the exposure
129 static int auto_whitebalance
= 1;
133 * Module parameter to set the log level
139 * @var microdia_table
140 * Define all the hotplug supported devices by this driver
142 static struct usb_device_id microdia_table
[] = {
143 /* SN9C201 + MI1300 */
144 { USB_DEVICE(USB_0C45_VID
, USB_6240_PID
) },
145 /* SN9C201 + MI1310 */
146 { USB_DEVICE(USB_0C45_VID
, USB_6242_PID
) },
147 /* SN9C201 + S5K4AAFX */
148 { USB_DEVICE(USB_0C45_VID
, USB_6243_PID
) },
149 /* SN9C201 + OV9655 */
150 { USB_DEVICE(USB_0C45_VID
, USB_6248_PID
) },
151 /* SN9C201 + CX1332 */
152 { USB_DEVICE(USB_0C45_VID
, USB_624B_PID
) },
153 /* SN9C201 + MI1320 */
154 { USB_DEVICE(USB_0C45_VID
, USB_624C_PID
) },
155 /* SN9C201 + SOI968 */
156 { USB_DEVICE(USB_0C45_VID
, USB_624E_PID
) },
157 /* SN9C201 + OV9650 */
158 { USB_DEVICE(USB_0C45_VID
, USB_624F_PID
) },
159 /* SN9C201 + OV9650 */
160 { USB_DEVICE(USB_0C45_VID
, USB_6253_PID
) },
161 /* SN9C201 + OV7670ISP */
162 { USB_DEVICE(USB_0C45_VID
, USB_6260_PID
) },
163 /* SN9C201 + OM6802 */
164 { USB_DEVICE(USB_0C45_VID
, USB_6262_PID
) },
165 /* SN9C201 + MI0360/MT9V111 */
166 { USB_DEVICE(USB_0C45_VID
, USB_6270_PID
) },
167 /* SN9C201 + S5K53BEB */
168 { USB_DEVICE(USB_0C45_VID
, USB_627A_PID
) },
169 /* SN9C201 + OV7660 */
170 { USB_DEVICE(USB_0C45_VID
, USB_627B_PID
) },
171 /* SN9C201 + HV7131R */
172 { USB_DEVICE(USB_0C45_VID
, USB_627C_PID
) },
174 { USB_DEVICE(USB_0C45_VID
, USB_627F_PID
) },
175 /* SN9C202 + MI1300 */
176 { USB_DEVICE(USB_0C45_VID
, USB_6280_PID
) },
177 /* SN9C202 + MI1310 */
178 { USB_DEVICE(USB_0C45_VID
, USB_6282_PID
) },
179 /* SN9C202 + S5K4AAFX */
180 { USB_DEVICE(USB_0C45_VID
, USB_6283_PID
) },
181 /* SN9C202 + OV9655 */
182 { USB_DEVICE(USB_0C45_VID
, USB_6288_PID
) },
183 /* SN9C202 + ICM107 */
184 { USB_DEVICE(USB_0C45_VID
, USB_628A_PID
) },
185 /* SN9C202 + CX1332 */
186 { USB_DEVICE(USB_0C45_VID
, USB_628B_PID
) },
187 /* SN9C202 + MI1320 */
188 { USB_DEVICE(USB_0C45_VID
, USB_628C_PID
) },
189 /* SN9C202 + SOI968 */
190 { USB_DEVICE(USB_0C45_VID
, USB_628E_PID
) },
191 /* SN9C202 + OV9650 */
192 { USB_DEVICE(USB_0C45_VID
, USB_628F_PID
) },
193 /* SN9C202 + OV7670ISP */
194 { USB_DEVICE(USB_0C45_VID
, USB_62A0_PID
) },
195 /* SN9C202 + OM6802 */
196 { USB_DEVICE(USB_0C45_VID
, USB_62A2_PID
) },
197 /* SN9C202 + MI0360/MT9V111 */
198 { USB_DEVICE(USB_0C45_VID
, USB_62B0_PID
) },
199 /* SN9C202 + OV9655 */
200 { USB_DEVICE(USB_0C45_VID
, USB_62B3_PID
) },
201 /* SN9C202 + S5K53BEB */
202 { USB_DEVICE(USB_0C45_VID
, USB_62BA_PID
) },
203 /* SN9C202 + OV7660 */
204 { USB_DEVICE(USB_0C45_VID
, USB_62BB_PID
) },
205 /* SN9C202 + HV7131R */
206 { USB_DEVICE(USB_0C45_VID
, USB_62BC_PID
) },
207 /* SN9C202 + OV7663 */
208 { USB_DEVICE(USB_0C45_VID
, USB_62BE_PID
) },
209 /* => 628f (SN9C202 + OV9650) */
210 { USB_DEVICE(USB_045E_VID
, USB_00F4_PID
) },
211 /* => 627b (SN9C201 + OV7660) */
212 { USB_DEVICE(USB_145F_VID
, USB_013D_PID
) },
213 /* => 62be (SN9C202 + OV7663 + EEPROM) */
214 { USB_DEVICE(USB_04F2_VID
, USB_A128_PID
) },
219 MODULE_DEVICE_TABLE(usb
, microdia_table
); /**< Define the supported devices */
221 DEFINE_MUTEX(open_lock
); /**< Define global mutex */
223 extern int microdia_6240_initialize(struct usb_microdia
*dev
);
224 extern int microdia_6240_start_stream(struct usb_microdia
*dev
);
225 extern int microdia_6240_stop_stream(struct usb_microdia
*dev
);
226 extern int microdia_6242_start_stream(struct usb_microdia
*dev
);
227 extern int microdia_6242_stop_stream(struct usb_microdia
*dev
);
228 extern int microdia_624e_initialize(struct usb_microdia
*dev
);
229 extern int microdia_624e_start_stream(struct usb_microdia
*dev
);
230 extern int microdia_624e_stop_stream(struct usb_microdia
*dev
);
231 extern int microdia_624f_initialize(struct usb_microdia
*dev
);
232 extern int microdia_624f_stop_stream(struct usb_microdia
*dev
);
233 extern int microdia_624f_start_stream(struct usb_microdia
*dev
);
234 extern int microdia_624f_set_exposure(struct usb_microdia
*dev
);
235 extern int microdia_624f_flip_detect(struct usb_microdia
*dev
);
236 extern int microdia_6260_initialize(struct usb_microdia
*dev
);
237 extern int microdia_6260_start_stream(struct usb_microdia
*dev
);
238 extern int microdia_6260_stop_stream(struct usb_microdia
*dev
);
239 extern int microdia_6260_flip_detect(struct usb_microdia
*dev
);
240 extern int microdia_6270_initialize(struct usb_microdia
*dev
);
241 extern int microdia_6270_start_stream(struct usb_microdia
*dev
);
242 extern int microdia_6270_stop_stream(struct usb_microdia
*dev
);
243 extern int microdia_627b_initialize(struct usb_microdia
*dev
);
244 extern int microdia_627b_start_stream(struct usb_microdia
*dev
);
245 extern int microdia_627b_stop_stream(struct usb_microdia
*dev
);
246 extern int microdia_627f_initialize(struct usb_microdia
*dev
);
247 extern int microdia_6288_initialize(struct usb_microdia
*dev
);
248 extern int microdia_6288_start_stream(struct usb_microdia
*dev
);
249 extern int microdia_6288_stop_stream(struct usb_microdia
*dev
);
251 struct microdia_camera cameras
[] = {
253 .model
= CAMERA_MODEL(USB_0C45_VID
, USB_6240_PID
),
254 .type
= MICRODIA_VGA
,
255 .sensor_slave_address
= 0x5d,
256 .sensor_flags
= SN9C20X_I2C_2WIRE
,
257 .supported_fmts
= 0x03,
258 .initialize
= microdia_6240_initialize
,
259 .start_stream
= microdia_6240_start_stream
,
260 .stop_stream
= microdia_6240_stop_stream
,
263 .model
= CAMERA_MODEL(USB_0C45_VID
, USB_6242_PID
),
264 .type
= MICRODIA_VGA
,
265 .sensor_slave_address
= 0x5d,
266 .sensor_flags
= SN9C20X_I2C_2WIRE
,
267 .supported_fmts
= 0x03,
268 .initialize
= microdia_624e_initialize
,
269 .start_stream
= microdia_6242_start_stream
,
270 .stop_stream
= microdia_6242_stop_stream
,
273 .model
= CAMERA_MODEL(USB_0C45_VID
, USB_624E_PID
),
274 .type
= MICRODIA_VGA
,
275 .sensor_slave_address
= 0x30,
276 .sensor_flags
= SN9C20X_I2C_2WIRE
,
277 .supported_fmts
= 0x03,
278 .initialize
= microdia_624e_initialize
,
279 .start_stream
= microdia_624e_start_stream
,
280 .stop_stream
= microdia_624e_stop_stream
,
281 .set_auto_exposure
= ov965x_set_autoexposure
,
284 .model
= CAMERA_MODEL(USB_0C45_VID
, USB_624F_PID
),
285 .type
= MICRODIA_VGA
,
286 .sensor_slave_address
= 0x30,
287 .sensor_flags
= SN9C20X_I2C_2WIRE
,
288 .supported_fmts
= 0x03,
289 .initialize
= microdia_624f_initialize
,
290 .sensor_init
= ov965x_initialize
,
291 .start_stream
= microdia_624f_start_stream
,
292 .stop_stream
= microdia_624f_stop_stream
,
293 .flip_detect
= microdia_624f_flip_detect
,
294 .set_auto_exposure
= ov965x_set_autoexposure
,
295 .set_exposure
= ov965x_set_exposure
,
296 .set_hvflip
= ov965x_set_hvflip
,
299 .model
= CAMERA_MODEL(USB_0C45_VID
, USB_6253_PID
),
300 .type
= MICRODIA_VGA
,
301 .sensor_slave_address
= 0x30,
302 .sensor_flags
= SN9C20X_I2C_2WIRE
,
303 .supported_fmts
= 0x03,
304 .initialize
= microdia_624f_initialize
,
305 .sensor_init
= ov965x_initialize
,
306 .start_stream
= microdia_624f_start_stream
,
307 .stop_stream
= microdia_624f_stop_stream
,
308 .flip_detect
= microdia_624f_flip_detect
,
309 .set_auto_exposure
= ov965x_set_autoexposure
,
310 .set_exposure
= ov965x_set_exposure
,
311 .set_hvflip
= ov965x_set_hvflip
,
314 .model
= CAMERA_MODEL(USB_0C45_VID
, USB_6260_PID
),
315 .type
= MICRODIA_VGA
,
316 .sensor_slave_address
= 0x21,
317 .sensor_flags
= SN9C20X_I2C_2WIRE
,
318 .supported_fmts
= 0x08,
319 .initialize
= microdia_6260_initialize
,
320 .start_stream
= microdia_6260_start_stream
,
321 .stop_stream
= microdia_6260_stop_stream
,
322 .flip_detect
= microdia_6260_flip_detect
,
325 .model
= CAMERA_MODEL(USB_0C45_VID
, USB_6270_PID
),
326 .type
= MICRODIA_VGA
,
327 .sensor_slave_address
= 0,
328 .sensor_flags
= SN9C20X_I2C_2WIRE
,
329 .supported_fmts
= 0x07,
330 .initialize
= microdia_6270_initialize
,
331 .start_stream
= microdia_6270_start_stream
,
332 .stop_stream
= microdia_6270_stop_stream
,
333 .set_exposure
= mt9vx11_set_exposure
,
334 .set_hvflip
= mt9vx11_set_hvflip
,
335 .set_auto_exposure
= mt9v111_set_autoexposure
,
336 .set_auto_whitebalance
= mt9v111_set_autowhitebalance
,
339 .model
= CAMERA_MODEL(USB_0C45_VID
, USB_627B_PID
),
340 .type
= MICRODIA_VGA
,
341 .sensor_slave_address
= 0x21,
342 .sensor_flags
= SN9C20X_I2C_2WIRE
,
343 .supported_fmts
= 0x07,
344 .initialize
= microdia_627b_initialize
,
345 .start_stream
= microdia_627b_start_stream
,
346 .stop_stream
= microdia_627b_stop_stream
,
349 .model
= CAMERA_MODEL(USB_0C45_VID
, USB_627F_PID
),
350 .type
= MICRODIA_VGA
,
351 .sensor_slave_address
= 0x30,
352 .sensor_flags
= SN9C20X_I2C_2WIRE
,
353 .supported_fmts
= 0x03,
354 .initialize
= microdia_624f_initialize
,
355 .sensor_init
= ov965x_initialize
,
356 .start_stream
= microdia_624f_start_stream
,
357 .stop_stream
= microdia_624f_stop_stream
,
358 .flip_detect
= microdia_624f_flip_detect
,
359 .set_exposure
= ov965x_set_exposure
,
360 .set_hvflip
= ov965x_set_hvflip
,
363 .model
= CAMERA_MODEL(USB_0C45_VID
, USB_6288_PID
),
364 .type
= MICRODIA_VGA
,
365 .sensor_slave_address
= 0x30,
366 .sensor_flags
= SN9C20X_I2C_2WIRE
,
367 .supported_fmts
= 0x03,
368 .initialize
= microdia_6288_initialize
,
369 .start_stream
= microdia_6288_start_stream
,
370 .stop_stream
= microdia_6288_stop_stream
,
371 .set_auto_exposure
= ov965x_set_autoexposure
,
374 .model
= CAMERA_MODEL(USB_0C45_VID
, USB_62B3_PID
),
375 .type
= MICRODIA_VGA
,
376 .sensor_slave_address
= 0x30,
377 .sensor_flags
= SN9C20X_I2C_2WIRE
,
378 .supported_fmts
= 0x03,
379 .initialize
= microdia_6288_initialize
,
380 .start_stream
= microdia_6288_start_stream
,
381 .stop_stream
= microdia_6288_stop_stream
,
384 .model
= CAMERA_MODEL(USB_0C45_VID
, USB_62BB_PID
),
385 .type
= MICRODIA_VGA
,
386 .sensor_slave_address
= 0x21,
387 .sensor_flags
= SN9C20X_I2C_2WIRE
,
388 .supported_fmts
= 0x07,
389 .initialize
= microdia_627b_initialize
,
390 .start_stream
= microdia_627b_start_stream
,
391 .stop_stream
= microdia_627b_stop_stream
,
394 .model
= CAMERA_MODEL(USB_145F_VID
, USB_013D_PID
),
395 .type
= MICRODIA_VGA
,
396 .sensor_slave_address
= 0x21,
397 .sensor_flags
= SN9C20X_I2C_2WIRE
,
398 .supported_fmts
= 0x07,
399 .initialize
= microdia_627b_initialize
,
400 .start_stream
= microdia_627b_start_stream
,
401 .stop_stream
= microdia_627b_stop_stream
,
406 static inline struct microdia_camera
*find_camera(__u32 model
)
409 for (i
= 0; i
< ARRAY_SIZE(cameras
); i
++) {
410 if (cameras
[i
].model
== model
)
417 * @param dev Device structure
419 * @returns 0 if all is OK
421 * @brief Initilize an isochronous pipe.
423 * This function permits to initialize an URB transfert (or isochronous pipe).
425 int usb_microdia_isoc_init(struct usb_microdia
*dev
)
429 __u16 iso_max_frame_size
;
431 struct usb_device
*udev
;
438 UDIA_DEBUG("usb_microdia_isoc_init()\n");
440 iso_max_frame_size
= max_packet_sz(le16_to_cpu(dev
->isoc_in_size
)) *
441 hb_multiplier(le16_to_cpu(dev
->isoc_in_size
));
443 for (i
= 0; i
< MAX_ISO_BUFS
; i
++) {
444 urb
= usb_alloc_urb(ISO_FRAMES_PER_DESC
, GFP_KERNEL
);
447 UDIA_ERROR("Failed to allocate URB %d\n", i
);
448 usb_microdia_isoc_cleanup(dev
);
454 urb
->pipe
= usb_rcvisocpipe(udev
, dev
->isoc_in_endpointAddr
);
455 urb
->transfer_flags
= URB_ISO_ASAP
;
456 urb
->transfer_buffer_length
= iso_max_frame_size
* ISO_FRAMES_PER_DESC
;
457 urb
->complete
= usb_microdia_isoc_handler
;
459 urb
->start_frame
= 0;
460 urb
->number_of_packets
= ISO_FRAMES_PER_DESC
;
462 for (j
= 0; j
< ISO_FRAMES_PER_DESC
; j
++) {
463 urb
->iso_frame_desc
[j
].offset
= j
* iso_max_frame_size
;
464 urb
->iso_frame_desc
[j
].length
= iso_max_frame_size
;
467 dev
->isobuf
[i
].data
= kzalloc(urb
->transfer_buffer_length
,
469 if (dev
->isobuf
[i
].data
== NULL
) {
470 usb_microdia_isoc_cleanup(dev
);
474 urb
->transfer_buffer
= dev
->isobuf
[i
].data
;
475 dev
->isobuf
[i
].urb
= urb
;
478 UDIA_DEBUG("dev->isoc_in_size = %X\n", (unsigned int)dev
->isoc_in_size
);
479 UDIA_DEBUG("dev->isoc_in_endpointAddr = %X\n", dev
->isoc_in_endpointAddr
);
481 for (i
= 0; i
< MAX_ISO_BUFS
; i
++) {
482 ret
= usb_submit_urb(dev
->isobuf
[i
].urb
, GFP_KERNEL
);
485 UDIA_ERROR("isoc_init() submit_urb %d failed with error %d\n", i
, ret
);
493 * @param urb URB structure
495 * @brief ISOC handler
497 * This function is called as an URB transfert is complete (Isochronous pipe).
498 * So, the traitement is done in interrupt time, so it has be fast, not crash,
499 * and not stall. Neat.
501 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
502 void usb_microdia_isoc_handler(struct urb
*urb
, struct pt_regs
*regs
)
504 void usb_microdia_isoc_handler(struct urb
*urb
)
511 unsigned int framelen
;
514 unsigned char *iso_buf
= NULL
;
517 struct microdia_buffer
*buf
= NULL
;
518 struct usb_microdia
*dev
= urb
->context
;
519 struct microdia_video_queue
*queue
= &dev
->queue
;
521 unsigned char frame_header
[] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
523 UDIA_STREAM("Isoc handler\n");
525 switch (urb
->status
) {
530 UDIA_WARNING("Non-zero status (%d) in video "
531 "completion handler.\n", urb
->status
);
533 case -ENOENT
: /* usb_kill_urb() called. */
537 case -ECONNRESET
: /* usb_unlink_urb() called. */
538 case -ESHUTDOWN
: /* The endpoint is being disabled. */
539 microdia_queue_cancel(queue
);
543 spin_lock_irqsave(&queue
->irqlock
, flags
);
544 if (!list_empty(&queue
->irqqueue
))
545 buf
= list_first_entry(&queue
->irqqueue
, struct microdia_buffer
,
547 spin_unlock_irqrestore(&queue
->irqlock
, flags
);
549 for (i
= 0; i
< urb
->number_of_packets
; i
++) {
550 framestatus
= urb
->iso_frame_desc
[i
].status
;
551 if (framestatus
!= 0) {
552 UDIA_ERROR("Iso frame %d of USB has error %d\n",
556 framelen
= urb
->iso_frame_desc
[i
].actual_length
;
557 iso_buf
= urb
->transfer_buffer
+ urb
->iso_frame_desc
[i
].offset
;
562 if (memcmp(iso_buf
, frame_header
, 6) == 0 && framelen
== 64) {
563 UDIA_DEBUG("Frame Resolution: %dx%d\n",
564 iso_buf
[0x3a] << 4, iso_buf
[0x3b] << 3);
565 if (buf
->buf
.bytesused
!= 0)
566 buf
->state
= MICRODIA_BUF_STATE_DONE
;
568 if (buf
->state
!= MICRODIA_BUF_STATE_ACTIVE
)
569 buf
->state
= MICRODIA_BUF_STATE_ACTIVE
;
571 if (framelen
+ buf
->buf
.bytesused
> queue
->frame_size
) {
572 UDIA_WARNING("Frame Buffer overflow!\n");
573 dev
->vframes_overflow
++;
574 buf
->state
= MICRODIA_BUF_STATE_DONE
;
576 framelen
= min(queue
->frame_size
- buf
->buf
.bytesused
,
578 mem
= queue
->mem
+ buf
->buf
.m
.offset
+
580 memcpy(mem
, iso_buf
, framelen
);
581 buf
->buf
.bytesused
+= framelen
;
583 if (buf
->state
== MICRODIA_BUF_STATE_DONE
||
584 buf
->state
== MICRODIA_BUF_STATE_ERROR
) {
585 buf
= microdia_queue_next_buffer(queue
, buf
);
587 dev
->vframes_dropped
++;
591 urb
->dev
= dev
->udev
;
593 ret
= usb_submit_urb(urb
, GFP_ATOMIC
);
596 UDIA_ERROR("Error (%d) re-submitting urb in "
597 "microdia_isoc_handler.\n", ret
);
603 * @param dev Device structure
605 * @brief Clean-up all the ISOC buffers
607 * This function permits to clean-up all the ISOC buffers.
609 void usb_microdia_isoc_cleanup(struct usb_microdia
*dev
)
614 UDIA_DEBUG("Isoc cleanup\n");
619 for (i
= 0; i
< MAX_ISO_BUFS
; i
++) {
620 urb
= dev
->isobuf
[i
].urb
;
625 if (dev
->isobuf
[i
].data
) {
626 kfree(dev
->isobuf
[i
].data
);
627 dev
->isobuf
[i
].data
= NULL
;
630 dev
->isobuf
[i
].urb
= NULL
;
637 * @param dev Device structure
638 * @param index Choice of the interface
640 * @returns 0 if all is OK
642 * @brief Send the message SET_FEATURE and choose the interface
644 * This function permits to send the message SET_FEATURE on the USB bus.
646 int usb_microdia_set_feature(struct usb_microdia
*dev
, int index
)
649 struct usb_device
*udev
= dev
->udev
;
651 result
= usb_control_msg(udev
, usb_sndctrlpipe(udev
, 0),
653 USB_TYPE_STANDARD
| USB_DIR_OUT
| USB_RECIP_DEVICE
,
654 USB_DEVICE_REMOTE_WAKEUP
,
661 UDIA_ERROR("SET FEATURE fail !\n");
663 UDIA_DEBUG("SET FEATURE\n");
670 * @param dev Device structure
672 * @returns 0 if all is OK
674 * @brief Send the message SET_CONFIGURATION
676 * This function permits to send the message SET_CONFIGURATION on the USB bus.
678 int usb_microdia_set_configuration(struct usb_microdia
*dev
)
681 struct usb_device
*udev
= dev
->udev
;
683 result
= usb_control_msg(udev
, usb_sndctrlpipe(udev
, 0),
684 USB_REQ_SET_CONFIGURATION
,
685 USB_TYPE_STANDARD
| USB_DIR_OUT
| USB_RECIP_DEVICE
,
687 udev
->config
[0].desc
.bConfigurationValue
,
693 UDIA_ERROR("SET CONFIGURATION fail !\n");
695 UDIA_DEBUG("SET CONFIGURATION %d\n", udev
->config
[0].desc
.bConfigurationValue
);
702 * @param dev Device structure
703 * @param value register to write to
705 * @param length number of bytes
707 * @returns 0 if all is OK
709 * @brief Write a 16-bit value to a 16-bit register
711 * This function permits to write a 16-bit value to a 16-bit register on the USB bus.
713 int usb_microdia_control_write(struct usb_microdia
*dev
, __u16 value
, __u8
*data
, __u16 length
)
716 struct usb_device
*udev
= dev
->udev
;
718 result
= usb_control_msg(udev
, usb_sndctrlpipe(udev
, 0),
720 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_INTERFACE
,
728 UDIA_ERROR("Write register failed index = 0x%02X\n", value
);
740 * @returns 0 if all is OK
742 * @brief Write a series of 16-bit "commands" using the same buffer
744 int usb_microdia_control_write_multi(struct usb_microdia
*dev
, __u16
*commands
, __u8
*data
,
745 __u16 cmdlen
, __u16 datalen
)
749 for (i
= 0; i
< cmdlen
; i
++) {
750 result
= usb_microdia_control_write(dev
, commands
[i
], data
, datalen
);
760 * @param dev Device structure
761 * @param index register to read from
763 * @param length number of bytes
765 * @returns 0 if all is OK
767 * @brief Read a 16-bit value from a 16-bit register
769 * This function permits to read a 16-bit value from a 16-bit register on the USB bus.
771 int usb_microdia_control_read(struct usb_microdia
*dev
, __u16 index
, __u8
*data
, __u16 length
)
775 struct usb_device
*udev
= dev
->udev
;
779 result
= usb_control_msg(udev
, usb_rcvctrlpipe(udev
, 0),
781 USB_DIR_IN
| USB_TYPE_VENDOR
| USB_RECIP_INTERFACE
,
789 UDIA_ERROR("Read register failed 0x%02X\n", index
);
798 * @returns 0 if all is OK
800 * @brief Set the default value about the video settings.
802 * This function permits to set the video settings for each video camera model.
805 static int usb_microdia_default_settings(struct usb_microdia
*dev
)
807 struct v4l2_pix_format
*def_fmt
;
809 dev
->vframes_overflow
= 0;
810 dev
->vframes_incomplete
= 0;
811 dev
->vframes_dropped
= 0;
813 dev
->queue
.min_buffers
= min_buffers
;
814 dev
->queue
.max_buffers
= max_buffers
;
816 def_fmt
= v4l2_enum_supported_formats(dev
, 0);
818 switch (dev
->webcam_model
) {
820 dev
->vsettings
.fps
= fps
;
821 dev
->vsettings
.vflip
= vflip
;
822 dev
->vsettings
.hflip
= hflip
;
823 dev
->vsettings
.brightness
= brightness
& 0xffff;
824 dev
->vsettings
.contrast
= contrast
& 0xffff;
825 dev
->vsettings
.whiteness
= whiteness
& 0xffff;
826 dev
->vsettings
.exposure
= exposure
& 0xffff;
827 dev
->vsettings
.sharpness
= sharpness
& 0x3f;
828 dev
->vsettings
.rgb_gain
[0] = (rgb_gain
>> 16) & 0x7f;
829 dev
->vsettings
.rgb_gain
[1] = (rgb_gain
>> 8) & 0x7f;
830 dev
->vsettings
.rgb_gain
[2] = (rgb_gain
>> 8) & 0x7f;
831 dev
->vsettings
.rgb_gain
[3] = rgb_gain
& 0x7f;
832 dev
->vsettings
.auto_exposure
= auto_exposure
& 1;
833 dev
->vsettings
.auto_whitebalance
= auto_whitebalance
& 1;
834 dev
->vsettings
.hue
= 0xffff;
837 memcpy(&(dev
->vsettings
.format
),
839 sizeof(struct v4l2_pix_format
));
842 sn9c20x_set_resolution(dev
, 640, 480);
852 * @returns 0 if all is OK
854 * @brief Load the driver
856 * This function detects the device and allocate the buffers for the device
857 * and the video interface.
859 static int usb_microdia_probe(struct usb_interface
*interface
, const struct usb_device_id
*id
)
869 struct usb_microdia
*dev
= NULL
;
870 struct usb_device
*udev
= interface_to_usbdev(interface
);
871 struct usb_host_interface
*iface_desc
;
872 struct usb_endpoint_descriptor
*endpoint
;
873 struct microdia_camera
*camera
= NULL
;
875 /* Get USB VendorID and ProductID */
876 vendor_id
= le16_to_cpu(udev
->descriptor
.idVendor
);
877 product_id
= le16_to_cpu(udev
->descriptor
.idProduct
);
879 /* Check if we can handle this device */
880 UDIA_DEBUG("Probe function called with VendorID=%04X, ProductID=%04X and InterfaceNumber=%d\n",
881 vendor_id
, product_id
, interface
->cur_altsetting
->desc
.bInterfaceNumber
);
884 //The interface are probed one by one.
885 // We are interested in the video interface (always the interface '0')
886 // The interfaces '1' or '2' (if presents) are the audio control.
888 if (interface
->cur_altsetting
->desc
.bInterfaceNumber
> 0) {
894 camera
= find_camera(CAMERA_MODEL(vendor_id
, product_id
));
895 if (camera
== NULL
) {
896 UDIA_INFO("Camera %04X:%04X not supported.\n",
897 vendor_id
, product_id
);
902 UDIA_INFO("Microdia USB2.0 Webcam - %04X:%04X found.\n",
903 vendor_id
, product_id
);
907 // Allocate structure, initialize pointers, mutexes, etc.
908 // and link it to the usb_device
910 dev
= kzalloc(sizeof(struct usb_microdia
), GFP_KERNEL
);
913 UDIA_ERROR("Out of memory !\n");
918 /* Init mutexes, spinlock, etc. */
919 mutex_init(&dev
->mutex
);
920 kref_init(&dev
->vopen
);
923 dev
->webcam_model
= camera
->model
;
924 dev
->webcam_type
= camera
->type
;
925 if (dev
->webcam_model
== CAMERA_MODEL(USB_0C45_VID
, USB_6260_PID
))
926 dev
->frame_size_divisor
= MICRODIA_FRAME_SIZE_DIVISOR_6260
;
928 dev
->frame_size_divisor
= MICRODIA_FRAME_SIZE_DIVISOR_DEFAULT
;
929 dev
->initialize
= camera
->initialize
;
930 dev
->sensor_init
= camera
->sensor_init
;
931 dev
->stop_stream
= camera
->stop_stream
;
932 dev
->start_stream
= camera
->start_stream
;
933 dev
->set_contrast
= camera
->set_contrast
== NULL
?
934 sn9c20x_set_contrast
: camera
->set_contrast
;
935 dev
->set_brightness
= camera
->set_brightness
== NULL
?
936 sn9c20x_set_brightness
: camera
->set_brightness
;
937 dev
->set_gamma
= camera
->set_gamma
== NULL
?
938 sn9c20x_set_gamma
: camera
->set_gamma
;
939 dev
->set_sharpness
= camera
->set_sharpness
== NULL
?
940 sn9c20x_set_sharpness
: camera
->set_sharpness
;
941 dev
->set_rgb_gain
= camera
->set_rgb_gain
== NULL
?
942 sn9c20x_set_rgb_gain
: camera
->set_rgb_gain
;
943 dev
->set_exposure
= camera
->set_exposure
;
945 UDIA_INFO("Rotate detection enabled\n");
946 dev
->flip_detect
= camera
->flip_detect
;
948 dev
->set_hvflip
= camera
->set_hvflip
;
949 dev
->set_auto_exposure
= camera
->set_auto_exposure
;
950 dev
->set_auto_whitebalance
= camera
->set_auto_whitebalance
;
952 dev
->interface
= interface
;
954 dev
->sensor_slave_address
= camera
->sensor_slave_address
;
955 dev
->sensor_flags
= camera
->sensor_flags
;
956 dev
->supported_fmts
= camera
->supported_fmts
;
958 /* Read the product release */
959 dev
->release
= le16_to_cpu(udev
->descriptor
.bcdDevice
);
960 UDIA_INFO("Release: %04x\n", dev
->release
);
962 /* How many interfaces (1 or 3) ? */
963 bNumInterfaces
= udev
->config
->desc
.bNumInterfaces
;
964 UDIA_INFO("Number of interfaces : %d\n", bNumInterfaces
);
967 /* Switch on the camera (to detect size of buffers) */
968 dev_microdia_camera_on(dev
);
971 // Set up the endpoint information
972 // use only the first int-in and isoc-in endpoints
973 // for the current alternate setting
975 iface_desc
= interface
->cur_altsetting
;
977 for (i
= 0; i
< iface_desc
->desc
.bNumEndpoints
; ++i
) {
978 endpoint
= &iface_desc
->endpoint
[i
].desc
;
980 if (!dev
->int_in_endpointAddr
981 && ((endpoint
->bEndpointAddress
& USB_ENDPOINT_DIR_MASK
) == USB_DIR_IN
)
982 && ((endpoint
->bmAttributes
& USB_ENDPOINT_XFERTYPE_MASK
) == USB_ENDPOINT_XFER_INT
)) {
983 /* we found an interrupt in endpoint */
984 buffer_size
= le16_to_cpu(endpoint
->wMaxPacketSize
);
986 dev
->int_in_size
= buffer_size
;
987 dev
->int_in_endpointAddr
= (endpoint
->bEndpointAddress
& 0xf);
990 if (!dev
->isoc_in_endpointAddr
991 && ((endpoint
->bEndpointAddress
& USB_ENDPOINT_DIR_MASK
) == USB_DIR_IN
)
992 && ((endpoint
->bmAttributes
& USB_ENDPOINT_XFERTYPE_MASK
) == USB_ENDPOINT_XFER_ISOC
)) {
993 /* we found an isoc in endpoint */
994 buffer_size
= le16_to_cpu(endpoint
->wMaxPacketSize
);
996 dev
->isoc_in_size
= buffer_size
;
997 dev
->isoc_in_endpointAddr
= (endpoint
->bEndpointAddress
& 0xf);
1001 if (!(dev
->int_in_endpointAddr
&& dev
->isoc_in_endpointAddr
)) {
1002 UDIA_ERROR("Could not find both int-in and isoc-in endpoints");
1007 usb_microdia_default_settings(dev
);
1009 dev_microdia_camera_off(dev
);
1011 /* Initialize the video device */
1012 dev
->vdev
= video_device_alloc();
1019 /* Initialize the camera */
1020 dev_microdia_initialize_device(dev
);
1022 /* Register the video device */
1023 ret
= v4l_microdia_register_video_device(dev
);
1028 /* Create the entries in the sys filesystem */
1029 microdia_create_sysfs_files(dev
->vdev
);
1031 #ifdef CONFIG_MICRODIA_DEBUGFS
1032 microdia_create_debugfs_files(dev
);
1035 /* Save our data pointer in this interface device */
1036 usb_set_intfdata(interface
, dev
);
1041 kref_put(&dev
->vopen
, usb_microdia_delete
);
1046 void usb_microdia_delete(struct kref
*kref
)
1048 struct usb_microdia
*dev
;
1049 dev
= container_of(kref
, struct usb_microdia
, vopen
);
1051 if (dev
->vdev
!= NULL
) {
1052 microdia_remove_sysfs_files(dev
->vdev
);
1053 #ifdef CONFIG_MICRODIA_DEBUGFS
1054 microdia_remove_debugfs_files(dev
);
1056 v4l_microdia_unregister_video_device(dev
);
1064 * @brief This function is called when the device is disconnected
1065 * or when the kernel module is unloaded.
1067 static void usb_microdia_disconnect(struct usb_interface
*interface
)
1069 struct usb_microdia
*dev
= usb_get_intfdata(interface
);
1071 UDIA_INFO("Microdia USB2.0 Camera disconnected\n");
1073 usb_set_intfdata(interface
, NULL
);
1075 mutex_lock(&open_lock
);
1076 kref_put(&dev
->vopen
, usb_microdia_delete
);
1077 mutex_unlock(&open_lock
);
1082 * @var usb_microdia_driver
1084 * This variable contains some callback
1086 static struct usb_driver usb_microdia_driver
= {
1087 .name
= "usb_microdia_driver",
1088 .probe
= usb_microdia_probe
,
1089 .disconnect
= usb_microdia_disconnect
,
1090 .id_table
= microdia_table
,
1093 module_param(fps
, int, 0444); /**< @brief Module parameter frames per second */
1094 module_param(hflip
, int, 0444); /**< @brief Module parameter horizontal flip process */
1095 module_param(vflip
, int, 0444); /**< @brief Module parameter vertical flip process */
1096 module_param(flip_detect
, int, 0444); /**< @brief Module parameter flip detect */
1097 module_param(auto_exposure
, int, 0444); /**< @brief Module parameter automatic exposure control */
1098 module_param(auto_whitebalance
, int, 0444); /**< @brief Module parameter automatic whitebalance control */
1099 module_param(brightness
, int, 0444); /**< @brief Module parameter brightness */
1100 module_param(whiteness
, int, 0444); /**< @brief Module parameter whiteness */
1101 module_param(contrast
, int, 0444); /**< @brief Module parameter contrast */
1102 module_param(exposure
, int, 0444); /**< @brief Module parameter exposure */
1103 module_param(sharpness
, int, 0444); /**< @brief Module parameter sharpness */
1104 module_param(rgb_gain
, int, 0444); /**< @brief Module parameter red/green/blue gain */
1106 module_param(min_buffers
, int, 0444);
1107 module_param(max_buffers
, int, 0444);
1109 module_param(log_level
, byte
, 0444);
1112 * @returns 0 if all is OK
1114 * @brief Initialize the driver.
1116 * This function is called at first.
1117 * This function permits to define the default values from the command line.
1119 static int __init
usb_microdia_init(void)
1123 UDIA_INFO("Microdia USB2.0 webcam driver startup\n");
1125 #ifdef CONFIG_MICRODIA_DEBUGFS
1126 microdia_init_debugfs();
1129 if (fps
< 10 || fps
> 30) {
1130 UDIA_WARNING("Framerate out of bounds [10-30]! Defaulting to 25\n");
1134 if (vflip
!= 0 && vflip
!= 1) {
1135 UDIA_WARNING("Vertical flip should be 0 or 1! Defaulting to 0\n");
1139 if (hflip
!= 0 && hflip
!= 1) {
1140 UDIA_WARNING("Horizontal flip should be 0 or 1! Defaulting to 0\n");
1144 if (sharpness
< 0 || sharpness
> 0x3f) {
1145 UDIA_WARNING("Sharpness should be 0 to 63 ! Defaulting to 31\n");
1149 if ((rgb_gain
>> 16) < 0 || (rgb_gain
>> 16) > 0x7f) {
1150 UDIA_WARNING("Red Gain should be 0 to 127 ! Defaulting to 32\n");
1151 rgb_gain
= (rgb_gain
& 0x0000ffff) | 0x200000;
1154 if (((rgb_gain
>> 8) & 0xFF) < 0 || ((rgb_gain
>> 8) & 0xFF) > 0x7f) {
1155 UDIA_WARNING("Green Gain should be 0 to 127 ! Defaulting to 32\n");
1156 rgb_gain
= (rgb_gain
& 0x00ff00ff) | 0x002000;
1159 if ((rgb_gain
& 0xFF) < 0 || (rgb_gain
& 0xFF) > 0x7f) {
1160 UDIA_WARNING("Blue Gain should be 0 to 127 ! Defaulting to 32\n");
1161 rgb_gain
= (rgb_gain
& 0x00ffff00) | 0x20;
1164 if (auto_exposure
!= 0 && auto_exposure
!= 1) {
1165 UDIA_WARNING("Automatic exposure should be 0 or 1! "
1166 "Defaulting to 1\n");
1170 if (auto_whitebalance
!= 0 && auto_whitebalance
!= 1) {
1171 UDIA_WARNING("Automatic whitebalance should be 0 or 1! "
1172 "Defaulting to 1\n");
1173 auto_whitebalance
= 1;
1176 if (min_buffers
< 2) {
1177 UDIA_WARNING("Minimum buffers can't be less then 2! "
1178 "Defaulting to 2\n");
1183 if (min_buffers
> max_buffers
) {
1184 UDIA_WARNING("Minimum buffers must be less then or equal to "
1185 "max buffers! Defaulting to 2, 10\n");
1190 /* Register the driver with the USB subsystem */
1191 result
= usb_register(&usb_microdia_driver
);
1194 UDIA_ERROR("usb_register failed ! Error number %d\n", result
);
1196 UDIA_INFO(DRIVER_VERSION
" : " DRIVER_DESC
"\n");
1203 * @brief Close the driver
1205 * This function is called at last when you unload the driver.
1207 static void __exit
usb_microdia_exit(void)
1209 UDIA_INFO("usb_microdia_exit: Microdia USB2.0 webcam driver shutdown\n");
1211 #ifdef CONFIG_MICRODIA_DEBUGFS
1212 microdia_uninit_debugfs();
1215 /* Deregister this driver with the USB subsystem */
1216 usb_deregister(&usb_microdia_driver
);
1220 module_init(usb_microdia_init
); /**< @brief Module initialize */
1221 module_exit(usb_microdia_exit
); /**< @brief Module exit */
1224 MODULE_PARM_DESC(fps
, "Frames per second [10-30]"); /**< @brief Description of 'fps' parameter */
1225 MODULE_PARM_DESC(hflip
, "Horizontal image flip"); /**< @brief Description of 'hflip' parameter */
1226 MODULE_PARM_DESC(vflip
, "Vertical image flip"); /**< @brief Description of 'vflip' parameter */
1227 MODULE_PARM_DESC(flip_detect
, "Image flip detection"); /**< @brief Description of 'vflip_detect' parameter */
1228 MODULE_PARM_DESC(auto_exposure
, "Automatic exposure control"); /**< @brief Description of 'auto_exposure' parameter */
1229 MODULE_PARM_DESC(auto_whitebalance
, "Automatic whitebalance"); /**< @brief Description of 'auto_whitebalance' parameter */
1230 MODULE_PARM_DESC(brightness
, "Brightness setting"); /**< @brief Description of 'brightness' parameter */
1231 MODULE_PARM_DESC(whiteness
, "Whiteness setting"); /**< @brief Description of 'whiteness' parameter */
1232 MODULE_PARM_DESC(exposure
, "Exposure setting"); /**< @brief Description of 'exposure' parameter */
1233 MODULE_PARM_DESC(contrast
, "Contrast setting"); /**< @brief Description of 'contrast' parameter */
1234 MODULE_PARM_DESC(sharpness
, "Sharpness setting"); /**< @brief Description of 'sharpness' parameter */
1235 MODULE_PARM_DESC(rgb_gain
, "Red/Green/Blue Gain setting"); /**< @brief Description of 'RGB Gain' parameter */
1237 MODULE_PARM_DESC(min_buffers
, "Minimum number of image buffers");
1238 MODULE_PARM_DESC(max_buffers
, "Maximum number of image buffers");
1239 MODULE_PARM_DESC(log_level
, " <n>\n"
1240 "Driver log level\n"
1241 "1 = info (default)\n"
1247 MODULE_LICENSE("GPL"); /**< @brief Driver is under licence GPL */
1248 MODULE_AUTHOR(DRIVER_AUTHOR
); /**< @brief Driver is written by Nicolas VIVIEN */
1249 MODULE_DESCRIPTION(DRIVER_DESC
); /**< @brief Define the description of the driver */
1250 MODULE_SUPPORTED_DEVICE(DRIVER_SUPPORT
); /**< @brief List of supported device */