Move debugfs code to its own source file
[microdia.git] / microdia-usb.c
blobacaaf930618481279f11098c694bf5bc282c765b
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/stat.h>
37 #include <linux/usb.h>
38 #include <media/v4l2-common.h>
40 #include "microdia.h"
41 #include "sn9c20x.h"
42 #include "mt9vx11.h"
44 /**
45 * @var fps
46 * Module parameter to set frame per second
48 static int fps = 25;
50 /**
51 * @var hflip
52 * Module parameter to enable/disable the horizontal flip process
54 static int hflip = 0;
56 /**
57 * @var flip_detect
58 * Module parameter to enable/disable vflip detection
60 static int flip_detect = 0;
62 /**
63 * @var vflip
64 * Module parameter to enable/disable the vertical flip process
66 static int vflip = 0;
68 /**
69 * @var brightness
70 * Module parameter to set the brightness
72 static int brightness = MICRODIA_PERCENT(50, 0xFFFF);
74 /**
75 * @var whiteness
76 * Module parameter to set the whiteness
78 static int whiteness = MICRODIA_PERCENT(20, 0xFFFF);
80 /**
81 * @var contrast
82 * Module parameter to set the contrast
84 static int contrast = MICRODIA_PERCENT(50, 0xFFFF);
86 /**
87 * @var exposure
88 * Module parameter to set the exposure
90 static int exposure = MICRODIA_PERCENT(20, 0xFFFF);
92 /**
93 * @var sharpness
94 * Module parameter to set the sharpness
96 static int sharpness = MICRODIA_PERCENT(50, 0x3F);
98 /**
99 * @var rgb_gain
100 * Module parameter to set the red/green/blue gain
102 static int rgb_gain = MICRODIA_PERCENT(25, 0x7F) |
103 (MICRODIA_PERCENT(25, 0x7F) << 8) |
104 (MICRODIA_PERCENT(25, 0x7F) << 16);
107 * @var min_buffers
108 * Module parameter to set the minimum number of image buffers
110 static int min_buffers = 2;
113 * @var max_buffers
114 * Module parameter to set the maximum number of image buffers
116 static int max_buffers = 5;
119 * @var auto_exposure
120 * Module parameter to set the exposure
122 static int auto_exposure = 1;
125 * @var auto_whitebalance
126 * Module parameter to set the exposure
128 static int auto_whitebalance = 1;
131 * @var microdia_table
132 * Define all the hotplug supported devices by this driver
134 static struct usb_device_id microdia_table[] = {
135 /* SN9C201 + MI1300 */
136 { USB_DEVICE(USB_0C45_VID, USB_6240_PID) },
137 /* SN9C201 + MI1310 */
138 { USB_DEVICE(USB_0C45_VID, USB_6242_PID) },
139 /* SN9C201 + S5K4AAFX */
140 { USB_DEVICE(USB_0C45_VID, USB_6243_PID) },
141 /* SN9C201 + OV9655 */
142 { USB_DEVICE(USB_0C45_VID, USB_6248_PID) },
143 /* SN9C201 + CX1332 */
144 { USB_DEVICE(USB_0C45_VID, USB_624B_PID) },
145 /* SN9C201 + MI1320 */
146 { USB_DEVICE(USB_0C45_VID, USB_624C_PID) },
147 /* SN9C201 + SOI968 */
148 { USB_DEVICE(USB_0C45_VID, USB_624E_PID) },
149 /* SN9C201 + OV9650 */
150 { USB_DEVICE(USB_0C45_VID, USB_624F_PID) },
151 /* SN9C201 + OV9650 */
152 { USB_DEVICE(USB_0C45_VID, USB_6253_PID) },
153 /* SN9C201 + OV7670ISP */
154 { USB_DEVICE(USB_0C45_VID, USB_6260_PID) },
155 /* SN9C201 + OM6802 */
156 { USB_DEVICE(USB_0C45_VID, USB_6262_PID) },
157 /* SN9C201 + MI0360/MT9V111 */
158 { USB_DEVICE(USB_0C45_VID, USB_6270_PID) },
159 /* SN9C201 + S5K53BEB */
160 { USB_DEVICE(USB_0C45_VID, USB_627A_PID) },
161 /* SN9C201 + OV7660 */
162 { USB_DEVICE(USB_0C45_VID, USB_627B_PID) },
163 /* SN9C201 + HV7131R */
164 { USB_DEVICE(USB_0C45_VID, USB_627C_PID) },
165 /* EEPROM */
166 { USB_DEVICE(USB_0C45_VID, USB_627F_PID) },
167 /* SN9C202 + MI1300 */
168 { USB_DEVICE(USB_0C45_VID, USB_6280_PID) },
169 /* SN9C202 + MI1310 */
170 { USB_DEVICE(USB_0C45_VID, USB_6282_PID) },
171 /* SN9C202 + S5K4AAFX */
172 { USB_DEVICE(USB_0C45_VID, USB_6283_PID) },
173 /* SN9C202 + OV9655 */
174 { USB_DEVICE(USB_0C45_VID, USB_6288_PID) },
175 /* SN9C202 + ICM107 */
176 { USB_DEVICE(USB_0C45_VID, USB_628A_PID) },
177 /* SN9C202 + CX1332 */
178 { USB_DEVICE(USB_0C45_VID, USB_628B_PID) },
179 /* SN9C202 + MI1320 */
180 { USB_DEVICE(USB_0C45_VID, USB_628C_PID) },
181 /* SN9C202 + SOI968 */
182 { USB_DEVICE(USB_0C45_VID, USB_628E_PID) },
183 /* SN9C202 + OV9650 */
184 { USB_DEVICE(USB_0C45_VID, USB_628F_PID) },
185 /* SN9C202 + OV7670ISP */
186 { USB_DEVICE(USB_0C45_VID, USB_62A0_PID) },
187 /* SN9C202 + OM6802 */
188 { USB_DEVICE(USB_0C45_VID, USB_62A2_PID) },
189 /* SN9C202 + MI0360/MT9V111 */
190 { USB_DEVICE(USB_0C45_VID, USB_62B0_PID) },
191 /* SN9C202 + OV9655 */
192 { USB_DEVICE(USB_0C45_VID, USB_62B3_PID) },
193 /* SN9C202 + S5K53BEB */
194 { USB_DEVICE(USB_0C45_VID, USB_62BA_PID) },
195 /* SN9C202 + OV7660 */
196 { USB_DEVICE(USB_0C45_VID, USB_62BB_PID) },
197 /* SN9C202 + HV7131R */
198 { USB_DEVICE(USB_0C45_VID, USB_62BC_PID) },
199 /* SN9C202 + OV7663 */
200 { USB_DEVICE(USB_0C45_VID, USB_62BE_PID) },
201 /* => 628f (SN9C202 + OV9650) */
202 { USB_DEVICE(USB_045E_VID, USB_00F4_PID) },
203 /* => 627b (SN9C201 + OV7660) */
204 { USB_DEVICE(USB_145F_VID, USB_013D_PID) },
205 /* => 62be (SN9C202 + OV7663 + EEPROM) */
206 { USB_DEVICE(USB_04F2_VID, USB_A128_PID) },
211 MODULE_DEVICE_TABLE(usb, microdia_table); /**< Define the supported devices */
213 DEFINE_MUTEX(open_lock); /**< Define global mutex */
215 extern int microdia_6240_initialize(struct usb_microdia *dev);
216 extern int microdia_6240_start_stream(struct usb_microdia *dev);
217 extern int microdia_6240_stop_stream(struct usb_microdia *dev);
218 extern int microdia_6242_start_stream(struct usb_microdia *dev);
219 extern int microdia_6242_stop_stream(struct usb_microdia *dev);
220 extern int microdia_624e_initialize(struct usb_microdia *dev);
221 extern int microdia_624e_start_stream(struct usb_microdia *dev);
222 extern int microdia_624e_stop_stream(struct usb_microdia *dev);
223 extern int microdia_624f_initialize(struct usb_microdia *dev);
224 extern int microdia_624f_stop_stream(struct usb_microdia *dev);
225 extern int microdia_624f_start_stream(struct usb_microdia *dev);
226 extern int microdia_624f_set_exposure(struct usb_microdia *dev);
227 extern int microdia_624f_flip_detect(struct usb_microdia *dev);
228 extern int microdia_6260_initialize(struct usb_microdia *dev);
229 extern int microdia_6260_start_stream(struct usb_microdia *dev);
230 extern int microdia_6260_stop_stream(struct usb_microdia *dev);
231 extern int microdia_6260_flip_detect(struct usb_microdia *dev);
232 extern int microdia_6270_initialize(struct usb_microdia *dev);
233 extern int microdia_6270_start_stream(struct usb_microdia *dev);
234 extern int microdia_6270_stop_stream(struct usb_microdia *dev);
235 extern int microdia_627b_initialize(struct usb_microdia *dev);
236 extern int microdia_627b_start_stream(struct usb_microdia *dev);
237 extern int microdia_627b_stop_stream(struct usb_microdia *dev);
238 extern int microdia_627f_initialize(struct usb_microdia *dev);
239 extern int microdia_6288_initialize(struct usb_microdia *dev);
240 extern int microdia_6288_start_stream(struct usb_microdia *dev);
241 extern int microdia_6288_stop_stream(struct usb_microdia *dev);
243 struct microdia_camera cameras[] = {
245 .model = CAMERA_MODEL(USB_0C45_VID, USB_6240_PID),
246 .type = MICRODIA_VGA,
247 .sensor_slave_address = 0x5d,
248 .sensor_flags = SN9C20X_I2C_2WIRE,
249 .supported_fmts = 0x03,
250 .initialize = microdia_6240_initialize,
251 .start_stream = microdia_6240_start_stream,
252 .stop_stream = microdia_6240_stop_stream,
255 .model = CAMERA_MODEL(USB_0C45_VID, USB_6242_PID),
256 .type = MICRODIA_VGA,
257 .sensor_slave_address = 0x5d,
258 .sensor_flags = SN9C20X_I2C_2WIRE,
259 .supported_fmts = 0x03,
260 .initialize = microdia_624e_initialize,
261 .start_stream = microdia_6242_start_stream,
262 .stop_stream = microdia_6242_stop_stream,
265 .model = CAMERA_MODEL(USB_0C45_VID, USB_624E_PID),
266 .type = MICRODIA_VGA,
267 .sensor_slave_address = 0x30,
268 .sensor_flags = SN9C20X_I2C_2WIRE,
269 .supported_fmts = 0x03,
270 .initialize = microdia_624e_initialize,
271 .start_stream = microdia_624e_start_stream,
272 .stop_stream = microdia_624e_stop_stream,
275 .model = CAMERA_MODEL(USB_0C45_VID, USB_624F_PID),
276 .type = MICRODIA_VGA,
277 .sensor_slave_address = 0x30,
278 .sensor_flags = SN9C20X_I2C_2WIRE,
279 .supported_fmts = 0x03,
280 .initialize = microdia_624f_initialize,
281 .start_stream = microdia_624f_start_stream,
282 .stop_stream = microdia_624f_stop_stream,
283 .flip_detect = microdia_624f_flip_detect,
284 .set_exposure = microdia_624f_set_exposure,
287 .model = CAMERA_MODEL(USB_0C45_VID, USB_6260_PID),
288 .type = MICRODIA_VGA,
289 .sensor_slave_address = 0x21,
290 .sensor_flags = SN9C20X_I2C_2WIRE,
291 .supported_fmts = 0x08,
292 .initialize = microdia_6260_initialize,
293 .start_stream = microdia_6260_start_stream,
294 .stop_stream = microdia_6260_stop_stream,
295 .flip_detect = microdia_6260_flip_detect,
298 .model = CAMERA_MODEL(USB_0C45_VID, USB_6270_PID),
299 .type = MICRODIA_VGA,
300 .sensor_slave_address = 0,
301 .sensor_flags = SN9C20X_I2C_2WIRE,
302 .supported_fmts = 0x07,
303 .initialize = microdia_6270_initialize,
304 .start_stream = microdia_6270_start_stream,
305 .stop_stream = microdia_6270_stop_stream,
306 .set_exposure = mt9vx11_set_exposure,
307 .set_hvflip = mt9vx11_set_hvflip,
308 .set_auto_exposure = mt9v111_set_autoexposure,
309 .set_auto_whitebalance = mt9v111_set_autowhitebalance,
312 .model = CAMERA_MODEL(USB_0C45_VID, USB_627B_PID),
313 .type = MICRODIA_VGA,
314 .sensor_slave_address = 0x21,
315 .sensor_flags = SN9C20X_I2C_2WIRE,
316 .supported_fmts = 0x07,
317 .initialize = microdia_627b_initialize,
318 .start_stream = microdia_627b_start_stream,
319 .stop_stream = microdia_627b_stop_stream,
322 .model = CAMERA_MODEL(USB_0C45_VID, USB_6288_PID),
323 .type = MICRODIA_VGA,
324 .sensor_slave_address = 0x30,
325 .sensor_flags = SN9C20X_I2C_2WIRE,
326 .supported_fmts = 0x03,
327 .initialize = microdia_6288_initialize,
328 .start_stream = microdia_6288_start_stream,
329 .stop_stream = microdia_6288_stop_stream,
332 .model = CAMERA_MODEL(USB_0C45_VID, USB_62B3_PID),
333 .type = MICRODIA_VGA,
334 .sensor_slave_address = 0x30,
335 .sensor_flags = SN9C20X_I2C_2WIRE,
336 .supported_fmts = 0x03,
337 .initialize = microdia_6288_initialize,
338 .start_stream = microdia_6288_start_stream,
339 .stop_stream = microdia_6288_stop_stream,
342 .model = CAMERA_MODEL(USB_145F_VID, USB_013D_PID),
343 .type = MICRODIA_VGA,
344 .sensor_slave_address = 0x21,
345 .sensor_flags = SN9C20X_I2C_2WIRE,
346 .supported_fmts = 0x07,
347 .initialize = microdia_627b_initialize,
348 .start_stream = microdia_627b_start_stream,
349 .stop_stream = microdia_627b_stop_stream,
354 static inline struct microdia_camera *find_camera(__u32 model)
356 int i;
357 for (i = 0; i < ARRAY_SIZE(cameras); i++) {
358 if (cameras[i].model == model)
359 return &cameras[i];
361 return NULL;
365 * @param dev Device structure
367 * @returns 0 if all is OK
369 * @brief Initilize an isochronous pipe.
371 * This function permits to initialize an URB transfert (or isochronous pipe).
373 int usb_microdia_isoc_init(struct usb_microdia *dev)
375 int i, j;
376 int ret = 0;
377 __u16 iso_max_frame_size;
378 struct urb *urb;
379 struct usb_device *udev;
381 if (dev == NULL)
382 return -EFAULT;
384 udev = dev->udev;
386 UDIA_DEBUG("usb_microdia_isoc_init()\n");
388 iso_max_frame_size = max_packet_sz(le16_to_cpu(dev->isoc_in_size)) *
389 hb_multiplier(le16_to_cpu(dev->isoc_in_size));
391 for (i = 0; i < MAX_ISO_BUFS; i++) {
392 urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
394 if (urb == NULL) {
395 UDIA_ERROR("Failed to allocate URB %d\n", i);
396 usb_microdia_isoc_cleanup(dev);
397 return -ENOMEM;
400 urb->interval = 1;
401 urb->dev = udev;
402 urb->pipe = usb_rcvisocpipe(udev, dev->isoc_in_endpointAddr);
403 urb->transfer_flags = URB_ISO_ASAP;
404 urb->transfer_buffer_length = iso_max_frame_size * ISO_FRAMES_PER_DESC;
405 urb->complete = usb_microdia_isoc_handler;
406 urb->context = dev;
407 urb->start_frame = 0;
408 urb->number_of_packets = ISO_FRAMES_PER_DESC;
410 for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
411 urb->iso_frame_desc[j].offset = j * iso_max_frame_size;
412 urb->iso_frame_desc[j].length = iso_max_frame_size;
415 dev->isobuf[i].data = kzalloc(urb->transfer_buffer_length,
416 GFP_KERNEL);
417 if (dev->isobuf[i].data == NULL) {
418 usb_microdia_isoc_cleanup(dev);
419 return -ENOMEM;
422 urb->transfer_buffer = dev->isobuf[i].data;
423 dev->isobuf[i].urb = urb;
426 UDIA_DEBUG("dev->isoc_in_size = %X\n", (unsigned int)dev->isoc_in_size);
427 UDIA_DEBUG("dev->isoc_in_endpointAddr = %X\n", dev->isoc_in_endpointAddr);
429 for (i = 0; i < MAX_ISO_BUFS; i++) {
430 ret = usb_submit_urb(dev->isobuf[i].urb, GFP_KERNEL);
432 if (ret)
433 UDIA_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
436 return 0;
441 * @param urb URB structure
443 * @brief ISOC handler
445 * This function is called as an URB transfert is complete (Isochronous pipe).
446 * So, the traitement is done in interrupt time, so it has be fast, not crash,
447 * and not stall. Neat.
449 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
450 void usb_microdia_isoc_handler(struct urb *urb, struct pt_regs *regs)
451 #else
452 void usb_microdia_isoc_handler(struct urb *urb)
453 #endif
455 int i;
456 int ret;
458 int framestatus;
459 unsigned int framelen;
460 int flags;
462 unsigned char *iso_buf = NULL;
464 void *mem = NULL;
465 struct microdia_buffer *buf = NULL;
466 struct usb_microdia *dev = urb->context;
467 struct microdia_video_queue *queue = &dev->queue;
469 unsigned char frame_header[] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
471 UDIA_STREAM("Isoc handler\n");
473 switch (urb->status) {
474 case 0:
475 break;
477 default:
478 UDIA_WARNING("Non-zero status (%d) in video "
479 "completion handler.\n", urb->status);
481 case -ENOENT: /* usb_kill_urb() called. */
482 if (queue->frozen)
483 return;
485 case -ECONNRESET: /* usb_unlink_urb() called. */
486 case -ESHUTDOWN: /* The endpoint is being disabled. */
487 microdia_queue_cancel(queue);
488 return;
491 spin_lock_irqsave(&queue->irqlock, flags);
492 if (!list_empty(&queue->irqqueue))
493 buf = list_first_entry(&queue->irqqueue, struct microdia_buffer,
494 queue);
495 spin_unlock_irqrestore(&queue->irqlock, flags);
497 for (i = 0; i < urb->number_of_packets; i++) {
498 framestatus = urb->iso_frame_desc[i].status;
499 if (framestatus != 0) {
500 UDIA_ERROR("Iso frame %d of USB has error %d\n",
501 i, framestatus);
502 continue;
504 framelen = urb->iso_frame_desc[i].actual_length;
505 iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
507 if (buf == NULL)
508 continue;
510 if (memcmp(iso_buf, frame_header, 6) == 0 && framelen == 64) {
511 UDIA_DEBUG("Frame Resolution: %dx%d\n",
512 iso_buf[0x3a] << 4, iso_buf[0x3b] << 3);
513 if (buf->buf.bytesused != 0)
514 buf->state = MICRODIA_BUF_STATE_DONE;
515 } else {
516 if (buf->state != MICRODIA_BUF_STATE_ACTIVE)
517 buf->state = MICRODIA_BUF_STATE_ACTIVE;
519 if (framelen + buf->buf.bytesused > queue->frame_size) {
520 UDIA_WARNING("Frame Buffer overflow!\n");
521 dev->vframes_overflow++;
522 buf->state = MICRODIA_BUF_STATE_DONE;
524 framelen = min(queue->frame_size - buf->buf.bytesused,
525 framelen);
526 mem = queue->mem + buf->buf.m.offset +
527 buf->buf.bytesused;
528 memcpy(mem, iso_buf, framelen);
529 buf->buf.bytesused += framelen;
531 if (buf->state == MICRODIA_BUF_STATE_DONE ||
532 buf->state == MICRODIA_BUF_STATE_ERROR) {
533 buf = microdia_queue_next_buffer(queue, buf);
534 if (buf == NULL)
535 dev->vframes_dropped++;
539 urb->dev = dev->udev;
541 ret = usb_submit_urb(urb, GFP_ATOMIC);
543 if (ret != 0) {
544 UDIA_ERROR("Error (%d) re-submitting urb in "
545 "microdia_isoc_handler.\n", ret);
551 * @param dev Device structure
553 * @brief Clean-up all the ISOC buffers
555 * This function permits to clean-up all the ISOC buffers.
557 void usb_microdia_isoc_cleanup(struct usb_microdia *dev)
559 int i;
560 struct urb *urb;
562 UDIA_DEBUG("Isoc cleanup\n");
564 if (dev == NULL)
565 return;
567 for (i = 0; i < MAX_ISO_BUFS; i++) {
568 urb = dev->isobuf[i].urb;
569 if (urb == NULL)
570 continue;
572 usb_kill_urb(urb);
573 if (dev->isobuf[i].data) {
574 kfree(dev->isobuf[i].data);
575 dev->isobuf[i].data = NULL;
577 usb_free_urb(urb);
578 dev->isobuf[i].urb = NULL;
585 * @param dev Device structure
586 * @param index Choice of the interface
588 * @returns 0 if all is OK
590 * @brief Send the message SET_FEATURE and choose the interface
592 * This function permits to send the message SET_FEATURE on the USB bus.
594 int usb_microdia_set_feature(struct usb_microdia *dev, int index)
596 int result;
597 struct usb_device *udev = dev->udev;
599 result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
600 USB_REQ_SET_FEATURE,
601 USB_TYPE_STANDARD | USB_DIR_OUT | USB_RECIP_DEVICE,
602 USB_DEVICE_REMOTE_WAKEUP,
603 index,
604 NULL,
606 500);
608 if (result < 0)
609 UDIA_ERROR("SET FEATURE fail !\n");
610 else
611 UDIA_DEBUG("SET FEATURE\n");
613 return result;
618 * @param dev Device structure
620 * @returns 0 if all is OK
622 * @brief Send the message SET_CONFIGURATION
624 * This function permits to send the message SET_CONFIGURATION on the USB bus.
626 int usb_microdia_set_configuration(struct usb_microdia *dev)
628 int result;
629 struct usb_device *udev = dev->udev;
631 result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
632 USB_REQ_SET_CONFIGURATION,
633 USB_TYPE_STANDARD | USB_DIR_OUT | USB_RECIP_DEVICE,
635 udev->config[0].desc.bConfigurationValue,
636 NULL,
638 500);
640 if (result < 0)
641 UDIA_ERROR("SET CONFIGURATION fail !\n");
642 else
643 UDIA_DEBUG("SET CONFIGURATION %d\n", udev->config[0].desc.bConfigurationValue);
645 return result;
650 * @param dev Device structure
651 * @param value register to write to
652 * @param data
653 * @param length number of bytes
655 * @returns 0 if all is OK
657 * @brief Write a 16-bit value to a 16-bit register
659 * This function permits to write a 16-bit value to a 16-bit register on the USB bus.
661 int usb_microdia_control_write(struct usb_microdia *dev, __u16 value, __u8 *data, __u16 length)
663 int result;
664 struct usb_device *udev = dev->udev;
666 result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
667 0x08,
668 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
669 value,
670 0x00,
671 data,
672 length,
673 500);
675 if (result < 0)
676 UDIA_ERROR("Write register failed index = 0x%02X\n", value);
678 return result;
682 * @param dev
683 * @param commands
684 * @param data
685 * @param cmdlen
686 * @param datalen
688 * @returns 0 if all is OK
690 * @brief Write a series of 16-bit "commands" using the same buffer
692 int usb_microdia_control_write_multi(struct usb_microdia *dev, __u16 *commands, __u8 *data,
693 __u16 cmdlen, __u16 datalen)
695 int result, i;
697 for (i = 0; i < cmdlen; i++) {
698 result = usb_microdia_control_write(dev, commands[i], data, datalen);
700 if (result < 0)
701 return result;
704 return 0;
708 * @param dev Device structure
709 * @param index register to read from
710 * @param data
711 * @param length number of bytes
713 * @returns 0 if all is OK
715 * @brief Read a 16-bit value from a 16-bit register
717 * This function permits to read a 16-bit value from a 16-bit register on the USB bus.
719 int usb_microdia_control_read(struct usb_microdia *dev, __u16 index, __u8 *data, __u16 length)
721 int result;
723 struct usb_device *udev = dev->udev;
725 *data = 0;
727 result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
728 0x00,
729 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
730 index,
731 0x00,
732 data,
733 length,
734 500);
736 if (result < 0)
737 UDIA_ERROR("Read register failed 0x%02X\n", index);
739 return result;
744 * @param dev
746 * @returns 0 if all is OK
748 * @brief Set the default value about the video settings.
750 * This function permits to set the video settings for each video camera model.
753 static int usb_microdia_default_settings(struct usb_microdia *dev)
755 struct v4l2_pix_format *def_fmt;
757 dev->vframes_overflow = 0;
758 dev->vframes_incomplete = 0;
759 dev->vframes_dropped = 0;
761 dev->queue.min_buffers = min_buffers;
762 dev->queue.max_buffers = max_buffers;
764 def_fmt = v4l2_enum_supported_formats(dev, 0);
766 switch (dev->webcam_model) {
767 default:
768 dev->vsettings.fps = fps;
769 dev->vsettings.vflip = vflip;
770 dev->vsettings.hflip = hflip;
771 dev->vsettings.brightness = brightness & 0xffff;
772 dev->vsettings.contrast = contrast & 0xffff;
773 dev->vsettings.whiteness = whiteness & 0xffff;
774 dev->vsettings.exposure = exposure & 0xffff;
775 dev->vsettings.sharpness = sharpness & 0x3f;
776 dev->vsettings.rgb_gain[0] = (rgb_gain >> 16) & 0x7f;
777 dev->vsettings.rgb_gain[1] = (rgb_gain >> 8) & 0x7f;
778 dev->vsettings.rgb_gain[2] = (rgb_gain >> 8) & 0x7f;
779 dev->vsettings.rgb_gain[3] = rgb_gain & 0x7f;
780 dev->vsettings.auto_exposure = auto_exposure & 1;
781 dev->vsettings.auto_whitebalance = auto_whitebalance & 1;
782 dev->vsettings.hue = 0xffff;
784 if (def_fmt) {
785 memcpy(&(dev->vsettings.format),
786 def_fmt,
787 sizeof(struct v4l2_pix_format));
790 v4l_microdia_select_video_mode(dev, MICRODIA_640x480);
791 break;
793 return 0;
797 * @param interface
798 * @param id
800 * @returns 0 if all is OK
802 * @brief Load the driver
804 * This function detects the device and allocate the buffers for the device
805 * and the video interface.
807 static int usb_microdia_probe(struct usb_interface *interface, const struct usb_device_id *id)
809 int i;
810 int ret;
811 size_t buffer_size;
813 int vendor_id;
814 int product_id;
815 int bNumInterfaces;
817 struct usb_microdia *dev = NULL;
818 struct usb_device *udev = interface_to_usbdev(interface);
819 struct usb_host_interface *iface_desc;
820 struct usb_endpoint_descriptor *endpoint;
821 struct microdia_camera *camera = NULL;
823 /* Get USB VendorID and ProductID */
824 vendor_id = le16_to_cpu(udev->descriptor.idVendor);
825 product_id = le16_to_cpu(udev->descriptor.idProduct);
827 /* Check if we can handle this device */
828 UDIA_DEBUG("Probe function called with VendorID=%04X, ProductID=%04X and InterfaceNumber=%d\n",
829 vendor_id, product_id, interface->cur_altsetting->desc.bInterfaceNumber);
832 //The interface are probed one by one.
833 // We are interested in the video interface (always the interface '0')
834 // The interfaces '1' or '2' (if presents) are the audio control.
836 if (interface->cur_altsetting->desc.bInterfaceNumber > 0) {
837 ret = -ENODEV;
838 goto error;
841 /* Detect device */
842 camera = find_camera(CAMERA_MODEL(vendor_id, product_id));
843 if (camera == NULL) {
844 UDIA_INFO("Camera %04X:%04X not supported.\n",
845 vendor_id, product_id);
846 ret = -ENODEV;
847 goto error;
850 UDIA_INFO("Microdia USB2.0 Webcam - %04X:%04X found.\n",
851 vendor_id, product_id);
855 // Allocate structure, initialize pointers, mutexes, etc.
856 // and link it to the usb_device
858 dev = kzalloc(sizeof(struct usb_microdia), GFP_KERNEL);
860 if (dev == NULL) {
861 UDIA_ERROR("Out of memory !\n");
862 ret = -ENOMEM;
863 goto error;
866 /* Init mutexes, spinlock, etc. */
867 mutex_init(&dev->mutex);
868 kref_init(&dev->vopen);
870 /* Save pointers */
871 dev->webcam_model = camera->model;
872 dev->webcam_type = camera->type;
873 if (dev->webcam_model == CAMERA_MODEL(USB_0C45_VID, USB_6260_PID))
874 dev->frame_size_divisor = MICRODIA_FRAME_SIZE_DIVISOR_6260;
875 else
876 dev->frame_size_divisor = MICRODIA_FRAME_SIZE_DIVISOR_DEFAULT;
877 dev->initialize = camera->initialize;
878 dev->stop_stream = camera->stop_stream;
879 dev->start_stream = camera->start_stream;
880 dev->set_contrast = camera->set_contrast == NULL ?
881 sn9c20x_set_contrast : camera->set_contrast;
882 dev->set_brightness = camera->set_brightness == NULL ?
883 sn9c20x_set_brightness : camera->set_brightness;
884 dev->set_gamma = camera->set_gamma == NULL ?
885 sn9c20x_set_gamma : camera->set_gamma;
886 dev->set_sharpness = camera->set_sharpness == NULL ?
887 sn9c20x_set_sharpness : camera->set_sharpness;
888 dev->set_rgb_gain = camera->set_rgb_gain == NULL ?
889 sn9c20x_set_rgb_gain : camera->set_rgb_gain;
890 dev->set_exposure = camera->set_exposure;
891 if (flip_detect) {
892 UDIA_INFO("Rotate detection enabled\n");
893 dev->flip_detect = camera->flip_detect;
895 dev->set_hvflip = camera->set_hvflip;
896 dev->set_auto_exposure = camera->set_auto_exposure;
897 dev->set_auto_whitebalance = camera->set_auto_whitebalance;
898 dev->udev = udev;
899 dev->interface = interface;
901 dev->sensor_slave_address = camera->sensor_slave_address;
902 dev->sensor_flags = camera->sensor_flags;
903 dev->supported_fmts = camera->supported_fmts;
905 /* Read the product release */
906 dev->release = le16_to_cpu(udev->descriptor.bcdDevice);
907 UDIA_INFO("Release: %04x\n", dev->release);
909 /* How many interfaces (1 or 3) ? */
910 bNumInterfaces = udev->config->desc.bNumInterfaces;
911 UDIA_INFO("Number of interfaces : %d\n", bNumInterfaces);
914 /* Switch on the camera (to detect size of buffers) */
915 dev_microdia_camera_on(dev);
918 // Set up the endpoint information
919 // use only the first int-in and isoc-in endpoints
920 // for the current alternate setting
922 iface_desc = interface->cur_altsetting;
924 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
925 endpoint = &iface_desc->endpoint[i].desc;
927 if (!dev->int_in_endpointAddr
928 && ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
929 && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
930 /* we found an interrupt in endpoint */
931 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
933 dev->int_in_size = buffer_size;
934 dev->int_in_endpointAddr = (endpoint->bEndpointAddress & 0xf);
937 if (!dev->isoc_in_endpointAddr
938 && ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
939 && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)) {
940 /* we found an isoc in endpoint */
941 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
943 dev->isoc_in_size = buffer_size;
944 dev->isoc_in_endpointAddr = (endpoint->bEndpointAddress & 0xf);
948 if (!(dev->int_in_endpointAddr && dev->isoc_in_endpointAddr)) {
949 UDIA_ERROR("Could not find both int-in and isoc-in endpoints");
950 ret = -ENODEV;
951 goto free_dev;
954 usb_microdia_default_settings(dev);
956 dev_microdia_camera_off(dev);
958 /* Initialize the video device */
959 dev->vdev = video_device_alloc();
961 if (!dev->vdev) {
962 ret = -ENOMEM;
963 goto free_dev;
966 /* Initialize the camera */
967 dev_microdia_initialize_device(dev);
969 /* Register the video device */
970 ret = v4l_microdia_register_video_device(dev);
972 if (ret)
973 goto free_dev;
975 /* Create the entries in the sys filesystem */
976 microdia_create_sysfs_files(dev->vdev);
978 microdia_create_debugfs_files(dev);
980 /* Save our data pointer in this interface device */
981 usb_set_intfdata(interface, dev);
983 return 0;
985 free_dev:
986 kref_put(&dev->vopen, usb_microdia_delete);
987 error:
988 return ret;
991 void usb_microdia_delete(struct kref *kref)
993 struct usb_microdia *dev;
994 dev = container_of(kref, struct usb_microdia, vopen);
996 if (dev->vdev != NULL) {
997 microdia_remove_sysfs_files(dev->vdev);
998 microdia_remove_debugfs_files(dev);
999 v4l_microdia_unregister_video_device(dev);
1001 kfree(dev);
1005 * @param interface
1007 * @brief This function is called when the device is disconnected
1008 * or when the kernel module is unloaded.
1010 static void usb_microdia_disconnect(struct usb_interface *interface)
1012 struct usb_microdia *dev = usb_get_intfdata(interface);
1014 UDIA_INFO("Microdia USB2.0 Camera disconnected\n");
1016 usb_set_intfdata(interface, NULL);
1018 mutex_lock(&open_lock);
1019 kref_put(&dev->vopen, usb_microdia_delete);
1020 mutex_unlock(&open_lock);
1025 * @var usb_microdia_driver
1027 * This variable contains some callback
1029 static struct usb_driver usb_microdia_driver = {
1030 .name = "usb_microdia_driver",
1031 .probe = usb_microdia_probe,
1032 .disconnect = usb_microdia_disconnect,
1033 .id_table = microdia_table,
1036 module_param(fps, int, 0444); /**< @brief Module parameter frames per second */
1037 module_param(hflip, int, 0444); /**< @brief Module parameter horizontal flip process */
1038 module_param(vflip, int, 0444); /**< @brief Module parameter vertical flip process */
1039 module_param(flip_detect, int, 0444); /**< @brief Module parameter flip detect */
1040 module_param(auto_exposure, int, 0444); /**< @brief Module parameter automatic exposure control */
1041 module_param(auto_whitebalance, int, 0444); /**< @brief Module parameter automatic whitebalance control */
1042 module_param(brightness, int, 0444); /**< @brief Module parameter brightness */
1043 module_param(whiteness, int, 0444); /**< @brief Module parameter whiteness */
1044 module_param(contrast, int, 0444); /**< @brief Module parameter contrast */
1045 module_param(exposure, int, 0444); /**< @brief Module parameter exposure */
1046 module_param(sharpness, int, 0444); /**< @brief Module parameter sharpness */
1047 module_param(rgb_gain, int, 0444); /**< @brief Module parameter red/green/blue gain */
1049 module_param(min_buffers, int, 0444);
1050 module_param(max_buffers, int, 0444);
1054 * @returns 0 if all is OK
1056 * @brief Initialize the driver.
1058 * This function is called at first.
1059 * This function permits to define the default values from the command line.
1061 static int __init usb_microdia_init(void)
1063 int result;
1065 UDIA_INFO("Microdia USB2.0 webcam driver startup\n");
1067 microdia_init_debugfs();
1069 if (fps < 10 || fps > 30) {
1070 UDIA_WARNING("Framerate out of bounds [10-30]! Defaulting to 25\n");
1071 fps = 25;
1074 if (vflip != 0 && vflip != 1) {
1075 UDIA_WARNING("Vertical flip should be 0 or 1! Defaulting to 0\n");
1076 vflip = 0;
1079 if (hflip != 0 && hflip != 1) {
1080 UDIA_WARNING("Horizontal flip should be 0 or 1! Defaulting to 0\n");
1081 hflip = 0;
1084 if (sharpness < 0 || sharpness > 0x3f) {
1085 UDIA_WARNING("Sharpness should be 0 to 63 ! Defaulting to 31\n");
1086 sharpness = 0x1f;
1089 if ((rgb_gain >> 16) < 0 || (rgb_gain >> 16) > 0x7f) {
1090 UDIA_WARNING("Red Gain should be 0 to 127 ! Defaulting to 32\n");
1091 rgb_gain = (rgb_gain & 0x0000ffff) | 0x200000;
1094 if (((rgb_gain >> 8) & 0xFF) < 0 || ((rgb_gain >> 8) & 0xFF) > 0x7f) {
1095 UDIA_WARNING("Green Gain should be 0 to 127 ! Defaulting to 32\n");
1096 rgb_gain = (rgb_gain & 0x00ff00ff) | 0x002000;
1099 if ((rgb_gain & 0xFF) < 0 || (rgb_gain & 0xFF) > 0x7f) {
1100 UDIA_WARNING("Blue Gain should be 0 to 127 ! Defaulting to 32\n");
1101 rgb_gain = (rgb_gain & 0x00ffff00) | 0x20;
1104 if (auto_exposure != 0 && auto_exposure != 1) {
1105 UDIA_WARNING("Automatic exposure should be 0 or 1! "
1106 "Defaulting to 1\n");
1107 auto_exposure = 1;
1110 if (auto_whitebalance != 0 && auto_whitebalance != 1) {
1111 UDIA_WARNING("Automatic whitebalance should be 0 or 1! "
1112 "Defaulting to 1\n");
1113 auto_whitebalance = 1;
1116 if (min_buffers < 2) {
1117 UDIA_WARNING("Minimum buffers can't be less then 2! "
1118 "Defaulting to 2\n");
1119 min_buffers = 2;
1123 if (min_buffers > max_buffers) {
1124 UDIA_WARNING("Minimum buffers must be less then or equal to "
1125 "max buffers! Defaulting to 2, 10\n");
1126 min_buffers = 2;
1127 max_buffers = 5;
1130 /* Register the driver with the USB subsystem */
1131 result = usb_register(&usb_microdia_driver);
1133 if (result)
1134 UDIA_ERROR("usb_register failed ! Error number %d\n", result);
1136 UDIA_INFO(DRIVER_VERSION " : " DRIVER_DESC "\n");
1138 return result;
1143 * @brief Close the driver
1145 * This function is called at last when you unload the driver.
1147 static void __exit usb_microdia_exit(void)
1149 UDIA_INFO("usb_microdia_exit: Microdia USB2.0 webcam driver shutdown\n");
1151 microdia_uninit_debugfs();
1153 /* Deregister this driver with the USB subsystem */
1154 usb_deregister(&usb_microdia_driver);
1158 module_init(usb_microdia_init); /**< @brief Module initialize */
1159 module_exit(usb_microdia_exit); /**< @brief Module exit */
1162 MODULE_PARM_DESC(fps, "Frames per second [10-30]"); /**< @brief Description of 'fps' parameter */
1163 MODULE_PARM_DESC(hflip, "Horizontal image flip"); /**< @brief Description of 'hflip' parameter */
1164 MODULE_PARM_DESC(vflip, "Vertical image flip"); /**< @brief Description of 'vflip' parameter */
1165 MODULE_PARM_DESC(flip_detect, "Image flip detection"); /**< @brief Description of 'vflip_detect' parameter */
1166 MODULE_PARM_DESC(auto_exposure, "Automatic exposure control"); /**< @brief Description of 'auto_exposure' parameter */
1167 MODULE_PARM_DESC(auto_whitebalance, "Automatic whitebalance"); /**< @brief Description of 'auto_whitebalance' parameter */
1168 MODULE_PARM_DESC(brightness, "Brightness setting"); /**< @brief Description of 'brightness' parameter */
1169 MODULE_PARM_DESC(whiteness, "Whiteness setting"); /**< @brief Description of 'whiteness' parameter */
1170 MODULE_PARM_DESC(exposure, "Exposure setting"); /**< @brief Description of 'exposure' parameter */
1171 MODULE_PARM_DESC(contrast, "Contrast setting"); /**< @brief Description of 'contrast' parameter */
1172 MODULE_PARM_DESC(sharpness, "Sharpness setting"); /**< @brief Description of 'sharpness' parameter */
1173 MODULE_PARM_DESC(rgb_gain, "Red/Green/Blue Gain setting"); /**< @brief Description of 'RGB Gain' parameter */
1175 MODULE_PARM_DESC(min_buffers, "Minimum number of image buffers");
1176 MODULE_PARM_DESC(max_buffers, "Maximum number of image buffers");
1178 MODULE_LICENSE("GPL"); /**< @brief Driver is under licence GPL */
1179 MODULE_AUTHOR(DRIVER_AUTHOR); /**< @brief Driver is written by Nicolas VIVIEN */
1180 MODULE_DESCRIPTION(DRIVER_DESC); /**< @brief Define the description of the driver */
1181 MODULE_SUPPORTED_DEVICE(DRIVER_SUPPORT); /**< @brief List of supported device */