Implement RGB gain/balance
[microdia.git] / microdia-usb.c
blob63c082270fe00fce9b3a7f7e30ebf79d83f6af75
1 /**
2 * @file microdia-usb.c
3 * @author Nicolas VIVIEN
4 * @date 2008-02-01
5 * @version v0.0.0
7 * @brief Driver for Microdia USB video camera
9 * @note Copyright (C) Nicolas VIVIEN
11 * @par Licences
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
16 * any later version.
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/debugfs.h>
36 #include <linux/stat.h>
38 #include <linux/usb.h>
39 #include <media/v4l2-common.h>
41 #include "microdia.h"
42 #include "sn9c20x.h"
43 #include "mt9vx11.h"
45 /**
46 * @var fps
47 * Module parameter to set frame per second
49 static int fps = 25;
51 /**
52 * @var hflip
53 * Module parameter to enable/disable the horizontal flip process
55 static int hflip = 0;
57 /**
58 * @var flip_detect
59 * Module parameter to enable/disable vflip detection
61 static int flip_detect = 0;
63 /**
64 * @var vflip
65 * Module parameter to enable/disable the vertical flip process
67 static int vflip = 0;
69 /**
70 * @var brightness
71 * Module parameter to set the brightness
73 static int brightness = MICRODIA_PERCENT(50, 0xFFFF);
75 /**
76 * @var whiteness
77 * Module parameter to set the whiteness
79 static int whiteness = MICRODIA_PERCENT(20, 0xFFFF);
81 /**
82 * @var contrast
83 * Module parameter to set the contrast
85 static int contrast = MICRODIA_PERCENT(50, 0xFFFF);
87 /**
88 * @var exposure
89 * Module parameter to set the exposure
91 static int exposure = MICRODIA_PERCENT(20, 0xFFFF);
93 /**
94 * @var sharpness
95 * Module parameter to set the sharpness
97 static int sharpness = MICRODIA_PERCENT(50, 0x3F);
99 /**
100 * @var rgb_gain
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);
108 * @var min_buffers
109 * Module parameter to set the minimum number of image buffers
111 static int min_buffers = 2;
114 * @var max_buffers
115 * Module parameter to set the maximum number of image buffers
117 static int max_buffers = 5;
120 * @var auto_exposure
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;
132 * @var debug_dir_name
133 * Name of our directory in debugfs
135 static const char * debug_dir_name = "microdia";
138 * @var debug_file_name
139 * Name of our debug file in debugfs
141 static const char * debug_file_name = "debug_level";
144 * @var debug_dir
145 * Dentry for our debug dir (for cleanup)
147 static struct dentry * debug_dir;
150 * @var debug_file
151 * Dentry for our debug file (for cleanup)
153 static struct dentry * debug_file;
156 * @var debug_level
157 * Level at which we do debugging
159 static __u8 debug_level = 0;
163 * @var microdia_table
164 * Define all the hotplug supported devices by this driver
166 static struct usb_device_id microdia_table[] = {
167 /* SN9C201 + MI1300 */
168 { USB_DEVICE(USB_0C45_VID, USB_6240_PID) },
169 /* SN9C201 + MI1310 */
170 { USB_DEVICE(USB_0C45_VID, USB_6242_PID) },
171 /* SN9C201 + S5K4AAFX */
172 { USB_DEVICE(USB_0C45_VID, USB_6243_PID) },
173 /* SN9C201 + OV9655 */
174 { USB_DEVICE(USB_0C45_VID, USB_6248_PID) },
175 /* SN9C201 + CX1332 */
176 { USB_DEVICE(USB_0C45_VID, USB_624B_PID) },
177 /* SN9C201 + MI1320 */
178 { USB_DEVICE(USB_0C45_VID, USB_624C_PID) },
179 /* SN9C201 + SOI968 */
180 { USB_DEVICE(USB_0C45_VID, USB_624E_PID) },
181 /* SN9C201 + OV9650 */
182 { USB_DEVICE(USB_0C45_VID, USB_624F_PID) },
183 /* SN9C201 + OV9650 */
184 { USB_DEVICE(USB_0C45_VID, USB_6253_PID) },
185 /* SN9C201 + OV7670ISP */
186 { USB_DEVICE(USB_0C45_VID, USB_6260_PID) },
187 /* SN9C201 + OM6802 */
188 { USB_DEVICE(USB_0C45_VID, USB_6262_PID) },
189 /* SN9C201 + MI0360/MT9V111 */
190 { USB_DEVICE(USB_0C45_VID, USB_6270_PID) },
191 /* SN9C201 + S5K53BEB */
192 { USB_DEVICE(USB_0C45_VID, USB_627A_PID) },
193 /* SN9C201 + OV7660 */
194 { USB_DEVICE(USB_0C45_VID, USB_627B_PID) },
195 /* SN9C201 + HV7131R */
196 { USB_DEVICE(USB_0C45_VID, USB_627C_PID) },
197 /* EEPROM */
198 { USB_DEVICE(USB_0C45_VID, USB_627F_PID) },
199 /* SN9C202 + MI1300 */
200 { USB_DEVICE(USB_0C45_VID, USB_6280_PID) },
201 /* SN9C202 + MI1310 */
202 { USB_DEVICE(USB_0C45_VID, USB_6282_PID) },
203 /* SN9C202 + S5K4AAFX */
204 { USB_DEVICE(USB_0C45_VID, USB_6283_PID) },
205 /* SN9C202 + OV9655 */
206 { USB_DEVICE(USB_0C45_VID, USB_6288_PID) },
207 /* SN9C202 + ICM107 */
208 { USB_DEVICE(USB_0C45_VID, USB_628A_PID) },
209 /* SN9C202 + CX1332 */
210 { USB_DEVICE(USB_0C45_VID, USB_628B_PID) },
211 /* SN9C202 + MI1320 */
212 { USB_DEVICE(USB_0C45_VID, USB_628C_PID) },
213 /* SN9C202 + SOI968 */
214 { USB_DEVICE(USB_0C45_VID, USB_628E_PID) },
215 /* SN9C202 + OV9650 */
216 { USB_DEVICE(USB_0C45_VID, USB_628F_PID) },
217 /* SN9C202 + OV7670ISP */
218 { USB_DEVICE(USB_0C45_VID, USB_62A0_PID) },
219 /* SN9C202 + OM6802 */
220 { USB_DEVICE(USB_0C45_VID, USB_62A2_PID) },
221 /* SN9C202 + MI0360/MT9V111 */
222 { USB_DEVICE(USB_0C45_VID, USB_62B0_PID) },
223 /* SN9C202 + OV9655 */
224 { USB_DEVICE(USB_0C45_VID, USB_62B3_PID) },
225 /* SN9C202 + S5K53BEB */
226 { USB_DEVICE(USB_0C45_VID, USB_62BA_PID) },
227 /* SN9C202 + OV7660 */
228 { USB_DEVICE(USB_0C45_VID, USB_62BB_PID) },
229 /* SN9C202 + HV7131R */
230 { USB_DEVICE(USB_0C45_VID, USB_62BC_PID) },
231 /* SN9C202 + OV7663 */
232 { USB_DEVICE(USB_0C45_VID, USB_62BE_PID) },
233 /* SN9C325 + OM6802 */
234 { USB_DEVICE(USB_0C45_VID, USB_6128_PID) },
235 /* SN9C325 + OV7648 + POx1030xC + SOI768 +
236 * PO2030N + OV7660 + OV7670 + HV7131R */
237 { USB_DEVICE(USB_0C45_VID, USB_612A_PID) },
238 /* => 628f (SN9C202 + OV9650) */
239 { USB_DEVICE(USB_045E_VID, USB_00F4_PID) },
240 /* => 627b (SN9C201 + OV7660) */
241 { USB_DEVICE(USB_145F_VID, USB_013D_PID) },
242 /* => 62be (SN9C202 + OV7663 + EEPROM) */
243 { USB_DEVICE(USB_04F2_VID, USB_A128_PID) },
248 MODULE_DEVICE_TABLE(usb, microdia_table); /**< Define the supported devices */
250 DEFINE_MUTEX(open_lock); /**< Define global mutex */
252 extern int microdia_6240_initialize(struct usb_microdia *dev);
253 extern int microdia_6240_start_stream(struct usb_microdia *dev);
254 extern int microdia_6240_stop_stream(struct usb_microdia *dev);
255 extern int microdia_6242_start_stream(struct usb_microdia *dev);
256 extern int microdia_6242_stop_stream(struct usb_microdia *dev);
257 extern int microdia_624e_initialize(struct usb_microdia *dev);
258 extern int microdia_624e_start_stream(struct usb_microdia *dev);
259 extern int microdia_624e_stop_stream(struct usb_microdia *dev);
260 extern int microdia_624f_initialize(struct usb_microdia *dev);
261 extern int microdia_624f_stop_stream(struct usb_microdia *dev);
262 extern int microdia_624f_start_stream(struct usb_microdia *dev);
263 extern int microdia_624f_set_exposure(struct usb_microdia *dev);
264 extern int microdia_624f_flip_detect(struct usb_microdia *dev);
265 extern int microdia_6260_initialize(struct usb_microdia *dev);
266 extern int microdia_6260_start_stream(struct usb_microdia *dev);
267 extern int microdia_6260_stop_stream(struct usb_microdia *dev);
268 extern int microdia_6260_flip_detect(struct usb_microdia *dev);
269 extern int microdia_6270_initialize(struct usb_microdia *dev);
270 extern int microdia_6270_start_stream(struct usb_microdia *dev);
271 extern int microdia_6270_stop_stream(struct usb_microdia *dev);
272 extern int microdia_627b_initialize(struct usb_microdia *dev);
273 extern int microdia_627b_start_stream(struct usb_microdia *dev);
274 extern int microdia_627b_stop_stream(struct usb_microdia *dev);
275 extern int microdia_627f_initialize(struct usb_microdia *dev);
276 extern int microdia_6288_initialize(struct usb_microdia *dev);
277 extern int microdia_6288_start_stream(struct usb_microdia *dev);
278 extern int microdia_6288_stop_stream(struct usb_microdia *dev);
279 extern int microdia_6128_initialize(struct usb_microdia *dev);
280 extern int microdia_6128_start_stream(struct usb_microdia *dev);
281 extern int microdia_6128_stop_stream(struct usb_microdia *dev);
283 struct microdia_camera cameras[] = {
285 .model = CAMERA_MODEL(USB_0C45_VID, USB_6240_PID),
286 .type = MICRODIA_VGA,
287 .sensor_slave_address = 0x5d,
288 .sensor_flags = SN9C20X_I2C_2WIRE,
289 .supported_fmts = 0x03,
290 .initialize = microdia_6240_initialize,
291 .start_stream = microdia_6240_start_stream,
292 .stop_stream = microdia_6240_stop_stream,
295 .model = CAMERA_MODEL(USB_0C45_VID, USB_6242_PID),
296 .type = MICRODIA_VGA,
297 .sensor_slave_address = 0x5d,
298 .sensor_flags = SN9C20X_I2C_2WIRE,
299 .supported_fmts = 0x03,
300 .initialize = microdia_624e_initialize,
301 .start_stream = microdia_6242_start_stream,
302 .stop_stream = microdia_6242_stop_stream,
305 .model = CAMERA_MODEL(USB_0C45_VID, USB_624E_PID),
306 .type = MICRODIA_VGA,
307 .sensor_slave_address = 0x30,
308 .sensor_flags = SN9C20X_I2C_2WIRE,
309 .supported_fmts = 0x03,
310 .initialize = microdia_624e_initialize,
311 .start_stream = microdia_624e_start_stream,
312 .stop_stream = microdia_624e_stop_stream,
315 .model = CAMERA_MODEL(USB_0C45_VID, USB_624F_PID),
316 .type = MICRODIA_VGA,
317 .sensor_slave_address = 0x30,
318 .sensor_flags = SN9C20X_I2C_2WIRE,
319 .supported_fmts = 0x03,
320 .initialize = microdia_624f_initialize,
321 .start_stream = microdia_624f_start_stream,
322 .stop_stream = microdia_624f_stop_stream,
323 .flip_detect = microdia_624f_flip_detect,
324 .set_exposure = microdia_624f_set_exposure,
327 .model = CAMERA_MODEL(USB_0C45_VID, USB_6260_PID),
328 .type = MICRODIA_VGA,
329 .sensor_slave_address = 0x21,
330 .sensor_flags = SN9C20X_I2C_2WIRE,
331 .supported_fmts = 0x08,
332 .initialize = microdia_6260_initialize,
333 .start_stream = microdia_6260_start_stream,
334 .stop_stream = microdia_6260_stop_stream,
335 .flip_detect = microdia_6260_flip_detect,
338 .model = CAMERA_MODEL(USB_0C45_VID, USB_6270_PID),
339 .type = MICRODIA_VGA,
340 .sensor_slave_address = 0,
341 .sensor_flags = SN9C20X_I2C_2WIRE,
342 .supported_fmts = 0x07,
343 .initialize = microdia_6270_initialize,
344 .start_stream = microdia_6270_start_stream,
345 .stop_stream = microdia_6270_stop_stream,
346 .set_exposure = mt9vx11_set_exposure,
347 .set_hvflip = mt9vx11_set_hvflip,
348 .set_auto_exposure = mt9v111_set_autoexposure,
349 .set_auto_whitebalance = mt9v111_set_autowhitebalance,
352 .model = CAMERA_MODEL(USB_0C45_VID, USB_627B_PID),
353 .type = MICRODIA_VGA,
354 .sensor_slave_address = 0x21,
355 .sensor_flags = SN9C20X_I2C_2WIRE,
356 .supported_fmts = 0x07,
357 .initialize = microdia_627b_initialize,
358 .start_stream = microdia_627b_start_stream,
359 .stop_stream = microdia_627b_stop_stream,
362 .model = CAMERA_MODEL(USB_0C45_VID, USB_6288_PID),
363 .type = MICRODIA_VGA,
364 .sensor_slave_address = 0x30,
365 .sensor_flags = SN9C20X_I2C_2WIRE,
366 .supported_fmts = 0x03,
367 .initialize = microdia_6288_initialize,
368 .start_stream = microdia_6288_start_stream,
369 .stop_stream = microdia_6288_stop_stream,
372 .model = CAMERA_MODEL(USB_0C45_VID, USB_62B3_PID),
373 .type = MICRODIA_VGA,
374 .sensor_slave_address = 0x30,
375 .sensor_flags = SN9C20X_I2C_2WIRE,
376 .supported_fmts = 0x03,
377 .initialize = microdia_6288_initialize,
378 .start_stream = microdia_6288_start_stream,
379 .stop_stream = microdia_6288_stop_stream,
382 .model = CAMERA_MODEL(USB_145F_VID, USB_013D_PID),
383 .type = MICRODIA_VGA,
384 .sensor_slave_address = 0x21,
385 .sensor_flags = SN9C20X_I2C_2WIRE,
386 .supported_fmts = 0x07,
387 .initialize = microdia_627b_initialize,
388 .start_stream = microdia_627b_start_stream,
389 .stop_stream = microdia_627b_stop_stream,
394 static inline struct microdia_camera *find_camera(__u32 model)
396 int i;
397 for (i = 0; i < ARRAY_SIZE(cameras); i++) {
398 if (cameras[i].model == model)
399 return &cameras[i];
401 return NULL;
404 /**
405 * @param dev Device structure
407 * @returns 0 if all is OK
409 * @brief Initilize an isochronous pipe.
411 * This function permits to initialize an URB transfert (or isochronous pipe).
413 int usb_microdia_isoc_init(struct usb_microdia *dev)
415 int i, j;
416 int ret = 0;
417 __u16 iso_max_frame_size;
418 struct urb *urb;
419 struct usb_device *udev;
421 if (dev == NULL)
422 return -EFAULT;
424 udev = dev->udev;
426 UDIA_DEBUG("usb_microdia_isoc_init()\n");
428 iso_max_frame_size = max_packet_sz(le16_to_cpu(dev->isoc_in_size)) *
429 hb_multiplier(le16_to_cpu(dev->isoc_in_size));
431 for (i = 0; i < MAX_ISO_BUFS; i++) {
432 urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
434 if (urb == NULL) {
435 UDIA_ERROR("Failed to allocate URB %d\n", i);
436 usb_microdia_isoc_cleanup(dev);
437 return -ENOMEM;
440 urb->interval = 1;
441 urb->dev = udev;
442 urb->pipe = usb_rcvisocpipe(udev, dev->isoc_in_endpointAddr);
443 urb->transfer_flags = URB_ISO_ASAP;
444 urb->transfer_buffer_length = iso_max_frame_size * ISO_FRAMES_PER_DESC;
445 urb->complete = usb_microdia_isoc_handler;
446 urb->context = dev;
447 urb->start_frame = 0;
448 urb->number_of_packets = ISO_FRAMES_PER_DESC;
450 for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
451 urb->iso_frame_desc[j].offset = j * iso_max_frame_size;
452 urb->iso_frame_desc[j].length = iso_max_frame_size;
455 dev->isobuf[i].data = kzalloc(urb->transfer_buffer_length,
456 GFP_KERNEL);
457 if (dev->isobuf[i].data == NULL) {
458 usb_microdia_isoc_cleanup(dev);
459 return -ENOMEM;
462 urb->transfer_buffer = dev->isobuf[i].data;
463 dev->isobuf[i].urb = urb;
466 UDIA_DEBUG("dev->isoc_in_size = %X\n", dev->isoc_in_size);
467 UDIA_DEBUG("dev->isoc_in_endpointAddr = %X\n", dev->isoc_in_endpointAddr);
469 for (i = 0; i < MAX_ISO_BUFS; i++) {
470 ret = usb_submit_urb(dev->isobuf[i].urb, GFP_KERNEL);
472 if (ret) {
473 UDIA_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
477 return 0;
481 /**
482 * @param urb URB structure
484 * @brief ISOC handler
486 * This function is called as an URB transfert is complete (Isochronous pipe).
487 * So, the traitement is done in interrupt time, so it has be fast, not crash,
488 * and not stall. Neat.
490 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
491 void usb_microdia_isoc_handler(struct urb *urb, struct pt_regs *regs)
492 #else
493 void usb_microdia_isoc_handler(struct urb *urb)
494 #endif
496 int i;
497 int ret;
499 int framestatus;
500 unsigned int framelen;
501 int flags;
503 unsigned char *iso_buf = NULL;
505 void *mem = NULL;
506 struct microdia_buffer *buf = NULL;
507 struct usb_microdia *dev = urb->context;
508 struct microdia_video_queue *queue = &dev->queue;
510 unsigned char frame_header[] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
512 UDIA_STREAM("Isoc handler\n");
514 switch (urb->status) {
515 case 0:
516 break;
518 default:
519 UDIA_WARNING("Non-zero status (%d) in video "
520 "completion handler.\n", urb->status);
522 case -ENOENT: /* usb_kill_urb() called. */
523 if (queue->frozen)
524 return;
526 case -ECONNRESET: /* usb_unlink_urb() called. */
527 case -ESHUTDOWN: /* The endpoint is being disabled. */
528 microdia_queue_cancel(queue);
529 return;
532 spin_lock_irqsave(&queue->irqlock, flags);
533 if (!list_empty(&queue->irqqueue))
534 buf = list_first_entry(&queue->irqqueue, struct microdia_buffer,
535 queue);
536 spin_unlock_irqrestore(&queue->irqlock, flags);
538 for (i=0; i<urb->number_of_packets; i++) {
539 framestatus = urb->iso_frame_desc[i].status;
540 if (framestatus != 0) {
541 UDIA_ERROR("Iso frame %d of USB has error %d\n",
542 i, framestatus);
543 continue;
545 framelen = urb->iso_frame_desc[i].actual_length;
546 iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
548 if (buf == NULL)
549 continue;
551 if (memcmp(iso_buf, frame_header, 6) == 0 && framelen == 64) {
552 UDIA_DEBUG("Frame Resolution: %dx%d\n",
553 iso_buf[0x3a] << 4, iso_buf[0x3b] << 3);
554 if (buf->buf.bytesused != 0)
555 buf->state = MICRODIA_BUF_STATE_DONE;
556 } else {
557 if (buf->state != MICRODIA_BUF_STATE_ACTIVE)
558 buf->state = MICRODIA_BUF_STATE_ACTIVE;
560 if (framelen + buf->buf.bytesused > queue->frame_size) {
561 UDIA_WARNING("Frame Buffer overflow!\n");
562 dev->vframes_overflow++;
563 buf->state = MICRODIA_BUF_STATE_DONE;
565 framelen = min(queue->frame_size - buf->buf.bytesused,
566 framelen);
567 mem = queue->mem + buf->buf.m.offset +
568 buf->buf.bytesused;
569 memcpy(mem, iso_buf, framelen);
570 buf->buf.bytesused += framelen;
572 if (buf->state == MICRODIA_BUF_STATE_DONE ||
573 buf->state == MICRODIA_BUF_STATE_ERROR) {
574 buf = microdia_queue_next_buffer(queue, buf);
575 if (buf == NULL)
576 dev->vframes_dropped++;
580 urb->dev = dev->udev;
582 ret = usb_submit_urb(urb, GFP_ATOMIC);
584 if (ret != 0) {
585 UDIA_ERROR("Error (%d) re-submitting urb in "
586 "microdia_isoc_handler.\n", ret);
591 /**
592 * @param dev Device structure
594 * @brief Clean-up all the ISOC buffers
596 * This function permits to clean-up all the ISOC buffers.
598 void usb_microdia_isoc_cleanup(struct usb_microdia *dev)
600 int i;
601 struct urb *urb;
603 UDIA_DEBUG("Isoc cleanup\n");
605 if (dev == NULL)
606 return;
608 for (i=0; i<MAX_ISO_BUFS; i++) {
609 urb = dev->isobuf[i].urb;
610 if (urb == NULL)
611 continue;
613 usb_kill_urb(urb);
614 if (dev->isobuf[i].data) {
615 kfree(dev->isobuf[i].data);
616 dev->isobuf[i].data = NULL;
618 usb_free_urb(urb);
619 dev->isobuf[i].urb = NULL;
625 /**
626 * @param dev Device structure
627 * @param index Choice of the interface
629 * @returns 0 if all is OK
631 * @brief Send the message SET_FEATURE and choose the interface
633 * This function permits to send the message SET_FEATURE on the USB bus.
635 int usb_microdia_set_feature(struct usb_microdia *dev, int index)
637 int result;
638 struct usb_device *udev = dev->udev;
640 result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
641 USB_REQ_SET_FEATURE,
642 USB_TYPE_STANDARD | USB_DIR_OUT | USB_RECIP_DEVICE,
643 USB_DEVICE_REMOTE_WAKEUP,
644 index,
645 NULL,
647 500);
649 if (result < 0)
650 UDIA_ERROR("SET FEATURE fail !\n");
651 else
652 UDIA_DEBUG("SET FEATURE\n");
654 return result;
658 /**
659 * @param dev Device structure
661 * @returns 0 if all is OK
663 * @brief Send the message SET_CONFIGURATION
665 * This function permits to send the message SET_CONFIGURATION on the USB bus.
667 int usb_microdia_set_configuration(struct usb_microdia *dev)
669 int result;
670 struct usb_device *udev = dev->udev;
672 result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
673 USB_REQ_SET_CONFIGURATION,
674 USB_TYPE_STANDARD | USB_DIR_OUT | USB_RECIP_DEVICE,
676 udev->config[0].desc.bConfigurationValue,
677 NULL,
679 500);
681 if (result < 0)
682 UDIA_ERROR("SET CONFIGURATION fail !\n");
683 else
684 UDIA_DEBUG("SET CONFIGURATION %d\n", udev->config[0].desc.bConfigurationValue);
686 return result;
691 * @param dev Device structure
692 * @param value register to write to
693 * @param data
694 * @param length number of bytes
696 * @returns 0 if all is OK
698 * @brief Write a 16-bit value to a 16-bit register
700 * This function permits to write a 16-bit value to a 16-bit register on the USB bus.
702 int usb_microdia_control_write(struct usb_microdia *dev, __u16 value, __u8 *data, __u16 length)
704 int result;
705 struct usb_device *udev = dev->udev;
707 result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
708 0x08,
709 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
710 value,
711 0x00,
712 data,
713 length,
714 500);
716 if (result < 0)
717 UDIA_ERROR("Write register failed index = 0x%02X\n", value);
719 return result;
723 * @param dev
724 * @param commands
725 * @param data
726 * @param cmdlen
727 * @param datalen
729 * @returns 0 if all is OK
731 * @brief Write a series of 16-bit "commands" using the same buffer
733 int usb_microdia_control_write_multi(struct usb_microdia *dev, __u16 *commands, __u8 *data,
734 __u16 cmdlen, __u16 datalen)
736 int result, i;
738 for(i = 0; i < cmdlen; i++) {
739 result = usb_microdia_control_write(dev, commands[i], data, datalen);
741 if(result < 0)
742 return result;
745 return 0;
749 * @param dev Device structure
750 * @param index register to read from
751 * @param data
752 * @param length number of bytes
754 * @returns 0 if all is OK
756 * @brief Read a 16-bit value from a 16-bit register
758 * This function permits to read a 16-bit value from a 16-bit register on the USB bus.
760 int usb_microdia_control_read(struct usb_microdia *dev, __u16 index, __u8 *data, __u16 length)
762 int result;
764 struct usb_device *udev = dev->udev;
766 *data = 0;
768 result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
769 0x00,
770 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
771 index,
772 0x00,
773 data,
774 length,
775 500);
777 if (result < 0)
778 UDIA_ERROR("Read register failed 0x%02X\n", index);
780 return result;
784 /**
785 * @param dev
787 * @returns 0 if all is OK
789 * @brief Set the default value about the video settings.
791 * This function permits to set the video settings for each video camera model.
794 static int usb_microdia_default_settings(struct usb_microdia *dev)
796 struct v4l2_pix_format *def_fmt;
798 dev->vframes_overflow = 0;
799 dev->vframes_incomplete = 0;
800 dev->vframes_dropped = 0;
802 dev->queue.min_buffers = min_buffers;
803 dev->queue.max_buffers = max_buffers;
805 def_fmt = v4l2_enum_supported_formats(dev, 0);
807 switch (dev->webcam_model) {
808 default:
809 dev->vsettings.fps = fps;
810 dev->vsettings.vflip = vflip;
811 dev->vsettings.hflip = hflip;
812 dev->vsettings.brightness = brightness & 0xffff;
813 dev->vsettings.contrast = contrast & 0xffff;
814 dev->vsettings.whiteness = whiteness & 0xffff;
815 dev->vsettings.exposure = exposure & 0xffff;
816 dev->vsettings.sharpness = sharpness & 0x3f;
817 dev->vsettings.rgb_gain[0] = (rgb_gain >> 16) & 0x7f;
818 dev->vsettings.rgb_gain[1] = (rgb_gain >> 8) & 0x7f;
819 dev->vsettings.rgb_gain[2] = (rgb_gain >> 8) & 0x7f;
820 dev->vsettings.rgb_gain[3] = rgb_gain & 0x7f;
821 dev->vsettings.auto_exposure = auto_exposure & 1;
822 dev->vsettings.auto_whitebalance = auto_whitebalance & 1;
823 dev->vsettings.hue = 0xffff;
825 if (def_fmt) {
826 memcpy(&(dev->vsettings.format),
827 def_fmt,
828 sizeof(struct v4l2_pix_format));
831 v4l_microdia_select_video_mode(dev, MICRODIA_640x480);
832 break;
834 return 0;
837 /**
838 * @param interface
839 * @param id
841 * @returns 0 if all is OK
843 * @brief Load the driver
845 * This function detects the device and allocate the buffers for the device
846 * and the video interface.
848 static int usb_microdia_probe(struct usb_interface *interface, const struct usb_device_id *id)
850 int i;
851 int ret;
852 size_t buffer_size;
854 int vendor_id;
855 int product_id;
856 int bNumInterfaces;
858 struct usb_microdia *dev = NULL;
859 struct usb_device *udev = interface_to_usbdev(interface);
860 struct usb_host_interface *iface_desc;
861 struct usb_endpoint_descriptor *endpoint;
862 struct microdia_camera *camera = NULL;
864 // Get USB VendorID and ProductID
865 vendor_id = le16_to_cpu(udev->descriptor.idVendor);
866 product_id = le16_to_cpu(udev->descriptor.idProduct);
868 // Check if we can handle this device
869 UDIA_DEBUG("Probe function called with VendorID=%04X, ProductID=%04X and InterfaceNumber=%d\n",
870 vendor_id, product_id, interface->cur_altsetting->desc.bInterfaceNumber);
872 // The interface are probed one by one.
873 // We are interested in the video interface (always the interface '0')
874 // The interfaces '1' or '2' (if presents) are the audio control.
875 if (interface->cur_altsetting->desc.bInterfaceNumber > 0) {
876 ret = -ENODEV;
877 goto error;
880 // Detect device
881 camera = find_camera(CAMERA_MODEL(vendor_id, product_id));
882 if (camera == NULL) {
883 UDIA_INFO("Camera %04X:%04X not supported.\n",
884 vendor_id, product_id);
885 ret = -ENODEV;
886 goto error;
889 UDIA_INFO("Microdia USB2.0 Webcam - %04X:%04X found.\n",
890 vendor_id, product_id);
893 // Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device
894 dev = kzalloc(sizeof(struct usb_microdia), GFP_KERNEL);
896 if (dev == NULL) {
897 UDIA_ERROR("Out of memory !\n");
898 ret = -ENOMEM;
899 goto error;
902 // Init mutexes, spinlock, etc.
903 mutex_init(&dev->mutex);
904 kref_init(&dev->vopen);
906 // Save pointers
907 dev->webcam_model = camera->model;
908 dev->webcam_type = camera->type;
909 if (dev->webcam_model == CAMERA_MODEL(USB_0C45_VID, USB_6260_PID))
910 dev->frame_size_divisor = MICRODIA_FRAME_SIZE_DIVISOR_6260;
911 else
912 dev->frame_size_divisor = MICRODIA_FRAME_SIZE_DIVISOR_DEFAULT;
913 dev->initialize = camera->initialize;
914 dev->stop_stream = camera->stop_stream;
915 dev->start_stream = camera->start_stream;
916 dev->set_contrast = camera->set_contrast == NULL ?
917 sn9c20x_set_contrast : camera->set_contrast;
918 dev->set_brightness = camera->set_brightness == NULL ?
919 sn9c20x_set_brightness : camera->set_brightness;
920 dev->set_gamma = camera->set_gamma == NULL ?
921 sn9c20x_set_gamma : camera->set_gamma;
922 dev->set_sharpness = camera->set_sharpness == NULL ?
923 sn9c20x_set_sharpness : camera->set_sharpness;
924 dev->set_rgb_gain = camera->set_rgb_gain == NULL ?
925 sn9c20x_set_rgb_gain : camera->set_rgb_gain;
926 dev->set_exposure = camera->set_exposure;
927 if (flip_detect) {
928 UDIA_INFO("Rotate detection enabled\n");
929 dev->flip_detect = camera->flip_detect;
931 dev->set_hvflip = camera->set_hvflip;
932 dev->set_auto_exposure = camera->set_auto_exposure;
933 dev->set_auto_whitebalance = camera->set_auto_whitebalance;
934 dev->udev = udev;
935 dev->interface = interface;
937 dev->sensor_slave_address = camera->sensor_slave_address;
938 dev->sensor_flags = camera->sensor_flags;
939 dev->supported_fmts = camera->supported_fmts;
941 // Read the product release
942 dev->release = le16_to_cpu(udev->descriptor.bcdDevice);
943 UDIA_INFO("Release: %04x\n", dev->release);
945 // How many interfaces (1 or 3) ?
946 bNumInterfaces = udev->config->desc.bNumInterfaces;
947 UDIA_INFO("Number of interfaces : %d\n", bNumInterfaces);
950 // Switch on the camera (to detect size of buffers)
951 dev_microdia_camera_on(dev);
954 // Set up the endpoint information
955 // use only the first int-in and isoc-in endpoints
956 // for the current alternate setting
957 iface_desc = interface->cur_altsetting;
959 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
960 endpoint = &iface_desc->endpoint[i].desc;
962 if (!dev->int_in_endpointAddr
963 && ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
964 && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
965 // we found an interrupt in endpoint
966 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
968 dev->int_in_size = buffer_size;
969 dev->int_in_endpointAddr = (endpoint->bEndpointAddress & 0xf);
972 if (!dev->isoc_in_endpointAddr
973 && ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
974 && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)) {
975 // we found an isoc in endpoint
976 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
978 dev->isoc_in_size = buffer_size;
979 dev->isoc_in_endpointAddr = (endpoint->bEndpointAddress & 0xf);
983 if (!(dev->int_in_endpointAddr && dev->isoc_in_endpointAddr)) {
984 UDIA_ERROR("Could not find both int-in and isoc-in endpoints");
985 ret = -ENODEV;
986 goto free_dev;
989 usb_microdia_default_settings(dev);
991 dev_microdia_camera_off(dev);
993 // Initialize the video device
994 dev->vdev = video_device_alloc();
996 if (!dev->vdev) {
997 ret = -ENOMEM;
998 goto free_dev;
1001 // Initialize the camera
1002 dev_microdia_initialize_device(dev);
1004 // Register the video device
1005 ret = v4l_microdia_register_video_device(dev);
1007 if (ret) {
1008 goto free_dev;
1011 // Create the entries in the sys filesystem
1012 microdia_create_sysfs_files(dev->vdev);
1014 // Save our data pointer in this interface device
1015 usb_set_intfdata(interface, dev);
1017 return 0;
1019 free_dev:
1020 kref_put(&dev->vopen, usb_microdia_delete);
1021 error:
1022 return ret;
1025 void usb_microdia_delete(struct kref *kref)
1027 struct usb_microdia *dev;
1028 dev = container_of(kref, struct usb_microdia, vopen);
1030 if (dev->vdev != NULL) {
1031 microdia_remove_sysfs_files(dev->vdev);
1032 v4l_microdia_unregister_video_device(dev);
1034 kfree(dev);
1037 /**
1038 * @param interface
1040 * @brief This function is called when the device is disconnected
1041 * or when the kernel module is unloaded.
1043 static void usb_microdia_disconnect(struct usb_interface *interface)
1045 struct usb_microdia *dev = usb_get_intfdata(interface);
1047 UDIA_INFO("Microdia USB2.0 Camera disconnected\n");
1049 usb_set_intfdata(interface, NULL);
1051 mutex_lock(&open_lock);
1052 kref_put(&dev->vopen, usb_microdia_delete);
1053 mutex_unlock(&open_lock);
1058 * @var usb_microdia_driver
1060 * This variable contains some callback
1062 static struct usb_driver usb_microdia_driver = {
1063 .name = "usb_microdia_driver",
1064 .probe = usb_microdia_probe,
1065 .disconnect = usb_microdia_disconnect,
1066 .id_table = microdia_table,
1069 module_param(fps, int, 0444); /**< @brief Module parameter frames per second */
1070 module_param(hflip, int, 0444); /**< @brief Module parameter horizontal flip process */
1071 module_param(vflip, int, 0444); /**< @brief Module parameter vertical flip process */
1072 module_param(flip_detect, int, 0444); /**< @brief Module parameter flip detect */
1073 module_param(auto_exposure, int, 0444); /**< @brief Module parameter automatic exposure control */
1074 module_param(auto_whitebalance, int, 0444); /**< @brief Module parameter automatic whitebalance control */
1075 module_param(brightness, int, 0444); /**< @brief Module parameter brightness */
1076 module_param(whiteness, int, 0444); /**< @brief Module parameter whiteness */
1077 module_param(contrast, int, 0444); /**< @brief Module parameter contrast */
1078 module_param(exposure, int, 0444); /**< @brief Module parameter exposure */
1079 module_param(sharpness, int, 0444); /**< @brief Module parameter sharpness */
1080 module_param(rgb_gain, int, 0444); /**< @brief Module parameter red/green/blue gain */
1082 module_param(min_buffers, int, 0444);
1083 module_param(max_buffers, int, 0444);
1086 /**
1087 * @returns 0 if all is OK
1089 * @brief Initialize the driver.
1091 * This function is called at first.
1092 * This function permits to define the default values from the command line.
1094 static int __init usb_microdia_init(void)
1096 int result;
1098 UDIA_INFO("Microdia USB2.0 webcam driver startup\n");
1100 debug_dir = debugfs_create_dir(debug_dir_name, NULL);
1101 if(debug_dir)
1102 debug_file = debugfs_create_u8(debug_file_name, S_IRUGO | S_IWUGO,
1103 debug_dir, &debug_level);
1105 if(fps < 10 || fps > 30) {
1106 UDIA_WARNING("Framerate out of bounds [10-30]! Defaulting to 25\n");
1107 fps = 25;
1110 if(vflip != 0 && vflip != 1) {
1111 UDIA_WARNING("Vertical flip should be 0 or 1! Defaulting to 0\n");
1112 vflip = 0;
1115 if(hflip != 0 && hflip != 1) {
1116 UDIA_WARNING("Horizontal flip should be 0 or 1! Defaulting to 0\n");
1117 hflip = 0;
1120 if (sharpness < 0 || sharpness > 0x3f) {
1121 UDIA_WARNING("Sharpness should be 0 to 63 ! Defaulting to 31\n");
1122 sharpness = 0x1f;
1125 if ((rgb_gain >> 16) < 0 || (rgb_gain >> 16) > 0x7f) {
1126 UDIA_WARNING("Red Gain should be 0 to 127 ! Defaulting to 32\n");
1127 rgb_gain = (rgb_gain & 0x0000ffff) | 0x200000;
1130 if (((rgb_gain >> 8) & 0xFF) < 0 || ((rgb_gain >> 8) & 0xFF) > 0x7f) {
1131 UDIA_WARNING("Green Gain should be 0 to 127 ! Defaulting to 32\n");
1132 rgb_gain = (rgb_gain & 0x00ff00ff) | 0x002000;
1135 if ((rgb_gain & 0xFF) < 0 || (rgb_gain & 0xFF) > 0x7f) {
1136 UDIA_WARNING("Blue Gain should be 0 to 127 ! Defaulting to 32\n");
1137 rgb_gain = (rgb_gain & 0x00ffff00) | 0x20;
1140 if(auto_exposure != 0 && auto_exposure != 1) {
1141 UDIA_WARNING("Automatic exposure should be 0 or 1! "
1142 "Defaulting to 1\n");
1143 auto_exposure = 1;
1146 if(auto_whitebalance != 0 && auto_whitebalance != 1) {
1147 UDIA_WARNING("Automatic whitebalance should be 0 or 1! "
1148 "Defaulting to 1\n");
1149 auto_whitebalance = 1;
1152 if (min_buffers < 2) {
1153 UDIA_WARNING("Minimum buffers can't be less then 2! "
1154 "Defaulting to 2\n");
1155 min_buffers = 2;
1159 if (min_buffers > max_buffers) {
1160 UDIA_WARNING("Minimum buffers must be less then or equal to "
1161 "max buffers! Defaulting to 2, 10\n");
1162 min_buffers = 2;
1163 max_buffers = 5;
1166 // Register the driver with the USB subsystem
1167 result = usb_register(&usb_microdia_driver);
1169 if (result)
1170 UDIA_ERROR("usb_register failed ! Error number %d\n", result);
1172 UDIA_INFO(DRIVER_VERSION " : " DRIVER_DESC "\n");
1174 return result;
1178 /**
1179 * @brief Close the driver
1181 * This function is called at last when you unload the driver.
1183 static void __exit usb_microdia_exit(void)
1185 UDIA_INFO("usb_microdia_exit: Microdia USB2.0 webcam driver shutdown\n");
1187 if(debug_file)
1188 debugfs_remove(debug_file);
1189 if(debug_dir)
1190 debugfs_remove(debug_dir);
1192 // Deregister this driver with the USB subsystem
1193 usb_deregister(&usb_microdia_driver);
1197 module_init(usb_microdia_init); /**< @brief Module initialize */
1198 module_exit(usb_microdia_exit); /**< @brief Module exit */
1201 MODULE_PARM_DESC(fps, "Frames per second [10-30]"); /**< @brief Description of 'fps' parameter */
1202 MODULE_PARM_DESC(hflip, "Horizontal image flip"); /**< @brief Description of 'hflip' parameter */
1203 MODULE_PARM_DESC(vflip, "Vertical image flip"); /**< @brief Description of 'vflip' parameter */
1204 MODULE_PARM_DESC(flip_detect, "Image flip detection"); /**< @brief Description of 'vflip_detect' parameter */
1205 MODULE_PARM_DESC(auto_exposure, "Automatic exposure control"); /**< @brief Description of 'auto_exposure' parameter */
1206 MODULE_PARM_DESC(auto_whitebalance, "Automatic whitebalance"); /**< @brief Description of 'auto_whitebalance' parameter */
1207 MODULE_PARM_DESC(brightness, "Brightness setting"); /**< @brief Description of 'brightness' parameter */
1208 MODULE_PARM_DESC(whiteness, "Whiteness setting"); /**< @brief Description of 'whiteness' parameter */
1209 MODULE_PARM_DESC(exposure, "Exposure setting"); /**< @brief Description of 'exposure' parameter */
1210 MODULE_PARM_DESC(contrast, "Contrast setting"); /**< @brief Description of 'contrast' parameter */
1211 MODULE_PARM_DESC(sharpness, "Sharpness setting"); /**< @brief Description of 'sharpness' parameter */
1212 MODULE_PARM_DESC(rgb_gain, "Red/Green/Blue Gain setting"); /**< @brief Description of 'RGB Gain' parameter */
1214 MODULE_PARM_DESC(min_buffers, "Minimum number of image buffers");
1215 MODULE_PARM_DESC(max_buffers, "Maximum number of image buffers");
1217 MODULE_LICENSE("GPL"); /**< @brief Driver is under licence GPL */
1218 MODULE_AUTHOR(DRIVER_AUTHOR); /**< @brief Driver is written by Nicolas VIVIEN */
1219 MODULE_DESCRIPTION(DRIVER_DESC); /**< @brief Define the description of the driver */
1220 MODULE_SUPPORTED_DEVICE(DRIVER_SUPPORT); /**< @brief List of supported device */