Fix 62B3 to use correct format decoding routines
[microdia.git] / microdia-usb.c
blobd652828a9399bffaeafe145f44ea95701234292f
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 min_buffers
101 * Module parameter to set the minimum number of image buffers
103 static int min_buffers = 2;
106 * @var max_buffers
107 * Module parameter to set the maximum number of image buffers
109 static int max_buffers = 5;
112 * @var auto_exposure
113 * Module parameter to set the exposure
115 static int auto_exposure = 1;
118 * @var auto_whitebalance
119 * Module parameter to set the exposure
121 static int auto_whitebalance = 1;
124 * @var debug_dir_name
125 * Name of our directory in debugfs
127 static const char * debug_dir_name = "microdia";
130 * @var debug_file_name
131 * Name of our debug file in debugfs
133 static const char * debug_file_name = "debug_level";
136 * @var debug_dir
137 * Dentry for our debug dir (for cleanup)
139 static struct dentry * debug_dir;
142 * @var debug_file
143 * Dentry for our debug file (for cleanup)
145 static struct dentry * debug_file;
148 * @var debug_level
149 * Level at which we do debugging
151 static __u8 debug_level = 0;
155 * @var microdia_table
156 * Define all the hotplug supported devices by this driver
158 static struct usb_device_id microdia_table[] = {
159 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_6240) }, // SN9C201 + MI1300
160 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_6242) }, // SN9C201 + MI1310
161 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_6243) }, // SN9C201 + S5K4AAFX
162 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_6248) }, // SN9C201 + OV9655
163 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_624B) }, // SN9C201 + CX1332
164 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_624C) }, // SN9C201 + MI1320
165 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_624E) }, // SN9C201 + SOI968
166 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_624F) }, // SN9C201 + OV9650
167 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_6253) }, // SN9C201 + OV9650
168 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_6260) }, // SN9C201 + OV7670ISP
169 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_6262) }, // SN9C201 + OM6802
170 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_6270) }, // SN9C201 + MI0360/MT9V111
171 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_627A) }, // SN9C201 + S5K53BEB
172 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_627B) }, // SN9C201 + OV7660
173 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_627C) }, // SN9C201 + HV7131R
174 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_627F) }, // EEPROM
175 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_6280) }, // SN9C202 + MI1300
176 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_6282) }, // SN9C202 + MI1310
177 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_6283) }, // SN9C202 + S5K4AAFX
178 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_6288) }, // SN9C202 + OV9655
179 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_628A) }, // SN9C202 + ICM107
180 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_628B) }, // SN9C202 + CX1332
181 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_628C) }, // SN9C202 + MI1320
182 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_628E) }, // SN9C202 + SOI968
183 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_628F) }, // SN9C202 + OV9650
184 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_62A0) }, // SN9C202 + OV7670ISP
185 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_62A2) }, // SN9C202 + OM6802
186 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_62B0) }, // SN9C202 + MI0360/MT9V111
187 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_62B3) }, // SN9C202 + OV9655
188 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_62BA) }, // SN9C202 + S5K53BEB
189 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_62BB) }, // SN9C202 + OV7660
190 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_62BC) }, // SN9C202 + HV7131R
191 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_62BE) }, // SN9C202 + OV7663
192 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_6128) }, // SN9C325 + OM6802
193 { USB_DEVICE(USB_VENDOR_ID_MICRODIA, USB_UDIA_MICRODIA_PRODUCT_ID_612A) }, // SN9C325 + OV7648 + POx1030xC + SOI768 + PO2030N + OV7660 + OV7670 + HV7131R
194 { USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_UDIA_MICROSOFT_PRODUCT_ID_00F4) }, // => 628f (SN9C202 + OV9650)
195 { USB_DEVICE(USB_VENDOR_ID_TRUST, USB_UDIA_TRUST_PRODUCT_ID_013D) }, // => 627b (SN9C201 + OV7660)
196 { USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_UDIA_CHICONY_PRODUCT_ID_A128) }, // => 62be (SN9C202 + OV7663 + EEPROM)
201 MODULE_DEVICE_TABLE(usb, microdia_table); /**< Define the supported devices */
203 DEFINE_MUTEX(open_lock); /**< Define global mutex */
205 /**
206 * @param dev Device structure
208 * @returns 0 if all is OK
210 * @brief Initilize an isochronous pipe.
212 * This function permits to initialize an URB transfert (or isochronous pipe).
214 int usb_microdia_isoc_init(struct usb_microdia *dev)
216 int i, j;
217 int ret = 0;
218 __u16 iso_max_frame_size;
219 struct urb *urb;
220 struct usb_device *udev;
222 if (dev == NULL)
223 return -EFAULT;
225 udev = dev->udev;
227 UDIA_DEBUG("usb_microdia_isoc_init()\n");
229 iso_max_frame_size = max_packet_sz(le16_to_cpu(dev->isoc_in_size)) *
230 hb_multiplier(le16_to_cpu(dev->isoc_in_size));
232 for (i = 0; i < MAX_ISO_BUFS; i++) {
233 urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
235 if (urb == NULL) {
236 UDIA_ERROR("Failed to allocate URB %d\n", i);
237 usb_microdia_isoc_cleanup(dev);
238 return -ENOMEM;
241 urb->interval = 1;
242 urb->dev = udev;
243 urb->pipe = usb_rcvisocpipe(udev, dev->isoc_in_endpointAddr);
244 urb->transfer_flags = URB_ISO_ASAP;
245 urb->transfer_buffer_length = iso_max_frame_size * ISO_FRAMES_PER_DESC;
246 urb->complete = usb_microdia_isoc_handler;
247 urb->context = dev;
248 urb->start_frame = 0;
249 urb->number_of_packets = ISO_FRAMES_PER_DESC;
251 for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
252 urb->iso_frame_desc[j].offset = j * iso_max_frame_size;
253 urb->iso_frame_desc[j].length = iso_max_frame_size;
256 dev->isobuf[i].data = kzalloc(urb->transfer_buffer_length,
257 GFP_KERNEL);
258 if (dev->isobuf[i].data == NULL) {
259 usb_microdia_isoc_cleanup(dev);
260 return -ENOMEM;
263 urb->transfer_buffer = dev->isobuf[i].data;
264 dev->isobuf[i].urb = urb;
267 UDIA_DEBUG("dev->isoc_in_size = %X\n", dev->isoc_in_size);
268 UDIA_DEBUG("dev->isoc_in_endpointAddr = %X\n", dev->isoc_in_endpointAddr);
270 for (i = 0; i < MAX_ISO_BUFS; i++) {
271 ret = usb_submit_urb(dev->isobuf[i].urb, GFP_KERNEL);
273 if (ret) {
274 UDIA_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
278 return 0;
282 /**
283 * @param urb URB structure
285 * @brief ISOC handler
287 * This function is called as an URB transfert is complete (Isochronous pipe).
288 * So, the traitement is done in interrupt time, so it has be fast, not crash,
289 * ans not stall. Neat.
291 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
292 void usb_microdia_isoc_handler(struct urb *urb, struct pt_regs *regs)
293 #else
294 void usb_microdia_isoc_handler(struct urb *urb)
295 #endif
297 int i;
298 int ret;
300 int framestatus;
301 unsigned int framelen;
302 int flags;
304 unsigned char *iso_buf = NULL;
306 void *mem = NULL;
307 struct microdia_buffer *buf = NULL;
308 struct usb_microdia *dev = urb->context;
309 struct microdia_video_queue *queue = &dev->queue;
311 unsigned char frame_header[] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
313 UDIA_STREAM("Isoc handler\n");
315 switch (urb->status) {
316 case 0:
317 break;
319 default:
320 UDIA_WARNING("Non-zero status (%d) in video "
321 "completion handler.\n", urb->status);
323 case -ENOENT: /* usb_kill_urb() called. */
324 if (queue->frozen)
325 return;
327 case -ECONNRESET: /* usb_unlink_urb() called. */
328 case -ESHUTDOWN: /* The endpoint is being disabled. */
329 microdia_queue_cancel(queue);
330 return;
333 spin_lock_irqsave(&queue->irqlock, flags);
334 if (!list_empty(&queue->irqqueue))
335 buf = list_first_entry(&queue->irqqueue, struct microdia_buffer,
336 queue);
337 spin_unlock_irqrestore(&queue->irqlock, flags);
339 for (i=0; i<urb->number_of_packets; i++) {
340 framestatus = urb->iso_frame_desc[i].status;
341 if (framestatus != 0) {
342 UDIA_ERROR("Iso frame %d of USB has error %d\n",
343 i, framestatus);
344 continue;
346 framelen = urb->iso_frame_desc[i].actual_length;
347 iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
349 if (buf == NULL)
350 continue;
352 if (memcmp(iso_buf, frame_header, 6) == 0 && framelen == 64) {
353 UDIA_DEBUG("Frame Resolution: %dx%d\n",
354 iso_buf[0x3a] << 4, iso_buf[0x3b] << 3);
355 if (buf->buf.bytesused != 0)
356 buf->state = MICRODIA_BUF_STATE_DONE;
357 } else {
358 if (buf->state != MICRODIA_BUF_STATE_ACTIVE)
359 buf->state = MICRODIA_BUF_STATE_ACTIVE;
361 if (framelen + buf->buf.bytesused > queue->frame_size) {
362 UDIA_WARNING("Frame Buffer overflow!\n");
363 dev->vframes_overflow++;
364 buf->state = MICRODIA_BUF_STATE_DONE;
366 framelen = min(queue->frame_size - buf->buf.bytesused,
367 framelen);
368 mem = queue->mem + buf->buf.m.offset +
369 buf->buf.bytesused;
370 memcpy(mem, iso_buf, framelen);
371 buf->buf.bytesused += framelen;
373 if (buf->state == MICRODIA_BUF_STATE_DONE ||
374 buf->state == MICRODIA_BUF_STATE_ERROR) {
375 buf = microdia_queue_next_buffer(queue, buf);
376 if (buf == NULL)
377 dev->vframes_dropped++;
381 urb->dev = dev->udev;
383 ret = usb_submit_urb(urb, GFP_ATOMIC);
385 if (ret != 0) {
386 UDIA_ERROR("Error (%d) re-submitting urb in "
387 "microdia_isoc_handler.\n", ret);
392 /**
393 * @param dev Device structure
395 * @brief Clean-up all the ISOC buffers
397 * This function permits to clean-up all the ISOC buffers.
399 void usb_microdia_isoc_cleanup(struct usb_microdia *dev)
401 int i;
402 struct urb *urb;
404 UDIA_DEBUG("Isoc cleanup\n");
406 if (dev == NULL)
407 return;
409 for (i=0; i<MAX_ISO_BUFS; i++) {
410 urb = dev->isobuf[i].urb;
411 if (urb == NULL)
412 continue;
414 usb_kill_urb(urb);
415 if (dev->isobuf[i].data) {
416 kfree(dev->isobuf[i].data);
417 dev->isobuf[i].data = NULL;
419 usb_free_urb(urb);
420 dev->isobuf[i].urb = NULL;
426 /**
427 * @param dev Device structure
428 * @param index Choice of the interface
430 * @returns 0 if all is OK
432 * @brief Send the message SET_FEATURE and choose the interface
434 * This function permits to send the message SET_FEATURE on the USB bus.
436 int usb_microdia_set_feature(struct usb_microdia *dev, int index)
438 int result;
439 struct usb_device *udev = dev->udev;
441 result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
442 USB_REQ_SET_FEATURE,
443 USB_TYPE_STANDARD | USB_DIR_OUT | USB_RECIP_DEVICE,
444 USB_DEVICE_REMOTE_WAKEUP,
445 index,
446 NULL,
448 500);
450 if (result < 0)
451 UDIA_ERROR("SET FEATURE fail !\n");
452 else
453 UDIA_DEBUG("SET FEATURE\n");
455 return result;
459 /**
460 * @param dev Device structure
462 * @returns 0 if all is OK
464 * @brief Send the message SET_CONFIGURATION
466 * This function permits to send the message SET_CONFIGURATION on the USB bus.
468 int usb_microdia_set_configuration(struct usb_microdia *dev)
470 int result;
471 struct usb_device *udev = dev->udev;
473 result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
474 USB_REQ_SET_CONFIGURATION,
475 USB_TYPE_STANDARD | USB_DIR_OUT | USB_RECIP_DEVICE,
477 udev->config[0].desc.bConfigurationValue,
478 NULL,
480 500);
482 if (result < 0)
483 UDIA_ERROR("SET CONFIGURATION fail !\n");
484 else
485 UDIA_DEBUG("SET CONFIGURATION %d\n", udev->config[0].desc.bConfigurationValue);
487 return result;
492 * @param dev Device structure
493 * @param value register to write to
494 * @param data
495 * @param length number of bytes
497 * @returns 0 if all is OK
499 * @brief Write a 16-bit value to a 16-bit register
501 * This function permits to write a 16-bit value to a 16-bit register on the USB bus.
503 int usb_microdia_control_write(struct usb_microdia *dev, __u16 value, __u8 *data, __u16 length)
505 int result;
506 struct usb_device *udev = dev->udev;
508 result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
509 0x08,
510 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
511 value,
512 0x00,
513 data,
514 length,
515 500);
517 if (result < 0)
518 UDIA_ERROR("Write register failed index = 0x%02X\n", value);
520 return result;
524 * @param dev
525 * @param commands
526 * @param data
527 * @param cmdlen
528 * @param datalen
530 * @returns 0 if all is OK
532 * @brief Write a series of 16-bit "commands" using the same buffer
534 int usb_microdia_control_write_multi(struct usb_microdia *dev, __u16 *commands, __u8 *data,
535 __u16 cmdlen, __u16 datalen)
537 int result, i;
539 for(i = 0; i < cmdlen; i++) {
540 result = usb_microdia_control_write(dev, commands[i], data, datalen);
542 if(result < 0)
543 return result;
546 return 0;
550 * @param dev Device structure
551 * @param index register to read from
552 * @param data
553 * @param length number of bytes
555 * @returns 0 if all is OK
557 * @brief Read a 16-bit value from a 16-bit register
559 * This function permits to read a 16-bit value from a 16-bit register on the USB bus.
561 int usb_microdia_control_read(struct usb_microdia *dev, __u16 index, __u8 *data, __u16 length)
563 int result;
565 struct usb_device *udev = dev->udev;
567 *data = 0;
569 result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
570 0x00,
571 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
572 index,
573 0x00,
574 data,
575 length,
576 500);
578 if (result < 0)
579 UDIA_ERROR("Read register failed 0x%02X\n", index);
581 return result;
585 /**
586 * @param dev
588 * @returns 0 if all is OK
590 * @brief Set the default value about the video settings.
592 * This function permits to set the video settings for each video camera model.
595 static int usb_microdia_default_settings(struct usb_microdia *dev)
597 struct v4l2_pix_format *def_fmt;
599 dev->vframes_overflow = 0;
600 dev->vframes_incomplete = 0;
601 dev->vframes_dropped = 0;
603 dev->queue.min_buffers = min_buffers;
604 dev->queue.max_buffers = max_buffers;
606 def_fmt = v4l2_enum_supported_formats(dev, 0);
608 switch (dev->webcam_model) {
609 default:
610 dev->vsettings.fps = fps;
611 dev->vsettings.vflip = vflip;
612 dev->vsettings.hflip = hflip;
613 dev->vsettings.brightness = brightness & 0xffff;
614 dev->vsettings.contrast = contrast & 0xffff;
615 dev->vsettings.whiteness = whiteness & 0xffff;
616 dev->vsettings.exposure = exposure & 0xffff;
617 dev->vsettings.sharpness = sharpness & 0x3f;
618 dev->vsettings.auto_exposure = auto_exposure & 1;
619 dev->vsettings.auto_whitebalance = auto_whitebalance & 1;
620 dev->vsettings.hue = 0xffff;
622 if (def_fmt) {
623 memcpy(&(dev->vsettings.format),
624 def_fmt,
625 sizeof(struct v4l2_pix_format));
628 v4l_microdia_select_video_mode(dev, MICRODIA_640x480);
629 break;
631 return 0;
634 extern int microdia_6240_initialize(struct usb_microdia *dev);
635 extern int microdia_6240_start_stream(struct usb_microdia *dev);
636 extern int microdia_6240_stop_stream(struct usb_microdia *dev);
637 extern int microdia_6242_start_stream(struct usb_microdia *dev);
638 extern int microdia_6242_stop_stream(struct usb_microdia *dev);
639 extern int microdia_624e_initialize(struct usb_microdia *dev);
640 extern int microdia_624e_start_stream(struct usb_microdia *dev);
641 extern int microdia_624e_stop_stream(struct usb_microdia *dev);
642 extern int microdia_624f_initialize(struct usb_microdia *dev);
643 extern int microdia_624f_stop_stream(struct usb_microdia *dev);
644 extern int microdia_624f_start_stream(struct usb_microdia *dev);
645 extern int microdia_624f_set_exposure(struct usb_microdia *dev);
646 extern int microdia_624f_flip_detect(struct usb_microdia *dev);
647 extern int microdia_6260_initialize(struct usb_microdia *dev);
648 extern int microdia_6260_start_stream(struct usb_microdia *dev);
649 extern int microdia_6260_stop_stream(struct usb_microdia *dev);
650 extern int microdia_6260_flip_detect(struct usb_microdia *dev);
651 extern int microdia_6270_initialize(struct usb_microdia *dev);
652 extern int microdia_6270_start_stream(struct usb_microdia *dev);
653 extern int microdia_6270_stop_stream(struct usb_microdia *dev);
654 extern int microdia_627b_initialize(struct usb_microdia *dev);
655 extern int microdia_627b_start_stream(struct usb_microdia *dev);
656 extern int microdia_627b_stop_stream(struct usb_microdia *dev);
657 extern int microdia_627f_initialize(struct usb_microdia *dev);
658 extern int microdia_6288_initialize(struct usb_microdia *dev);
659 extern int microdia_6288_start_stream(struct usb_microdia *dev);
660 extern int microdia_6288_stop_stream(struct usb_microdia *dev);
661 extern int microdia_6128_initialize(struct usb_microdia *dev);
662 extern int microdia_6128_start_stream(struct usb_microdia *dev);
663 extern int microdia_6128_stop_stream(struct usb_microdia *dev);
666 /**
667 * @param interface
668 * @param id
670 * @returns 0 if all is OK
672 * @brief Load the driver
674 * This function detects the device and allocate the buffers for the device
675 * and the video interface.
677 static int usb_microdia_probe(struct usb_interface *interface, const struct usb_device_id *id)
679 int i;
680 int ret;
681 size_t buffer_size;
683 int vendor_id;
684 int product_id;
685 int bNumInterfaces;
686 int webcam_model;
687 int webcam_type;
688 __u8 sensor_slave_address = 0;
689 __u8 supported_fmts = 0;
690 __u8 sensor_flags = 0x80; // 2-WIRE,100KHz
691 int (*initialize)(struct usb_microdia *) = NULL;
692 int (*stop_stream)(struct usb_microdia *) = NULL;
693 int (*start_stream)(struct usb_microdia *) = NULL;
694 int (*set_contrast)(struct usb_microdia *) = NULL;
695 int (*set_brightness)(struct usb_microdia *) = NULL;
696 int (*set_gamma)(struct usb_microdia *) = NULL;
697 int (*set_exposure)(struct usb_microdia *) = NULL;
698 int (*flip_detect_f)(struct usb_microdia *) = NULL;
699 int (*set_hvflip)(struct usb_microdia *) = NULL;
700 int (*set_sharpness)(struct usb_microdia *) = NULL;
701 int (*set_auto_exposure)(struct usb_microdia *) = NULL;
702 int (*set_auto_whitebalance)(struct usb_microdia *) = NULL;
704 struct usb_microdia *dev = NULL;
705 struct usb_device *udev = interface_to_usbdev(interface);
706 struct usb_host_interface *iface_desc;
707 struct usb_endpoint_descriptor *endpoint;
709 // Set default device parameters:
710 webcam_type = MICRODIA_VGA;
711 sensor_flags = SN9C20X_I2C_2WIRE;
712 set_contrast = sn9c20x_set_contrast;
713 set_brightness = sn9c20x_set_brightness;
714 set_gamma = sn9c20x_set_gamma;
715 set_sharpness = sn9c20x_set_sharpness;
717 // Get USB VendorID and ProductID
718 vendor_id = le16_to_cpu(udev->descriptor.idVendor);
719 product_id = le16_to_cpu(udev->descriptor.idProduct);
721 // Check if we can handle this device
722 UDIA_DEBUG("Probe function called with VendorID=%04X, ProductID=%04X and InterfaceNumber=%d\n",
723 vendor_id, product_id, interface->cur_altsetting->desc.bInterfaceNumber);
725 // The interface are probed one by one.
726 // We are interested in the video interface (always the interface '0')
727 // The interfaces '1' or '2' (if presents) are the audio control.
728 if (interface->cur_altsetting->desc.bInterfaceNumber > 0) {
729 ret = -ENODEV;
730 goto error;
733 // Detect device
734 if (vendor_id == USB_VENDOR_ID_MICRODIA) {
735 switch (product_id) {
736 case USB_UDIA_MICRODIA_PRODUCT_ID_6240:
737 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6240.\n");
738 UDIA_INFO("This device is under development. Please contact microdia@googlegroups for further info\n");
739 webcam_model = MICRODIA_6240;
740 supported_fmts = 0x03;
741 initialize = microdia_6240_initialize;
742 start_stream = microdia_6240_start_stream;
743 stop_stream = microdia_6240_stop_stream;
744 break;
746 case USB_UDIA_MICRODIA_PRODUCT_ID_6242:
747 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6242.\n");
748 webcam_model = MICRODIA_6242;
749 sensor_slave_address = 0x5d;
750 supported_fmts = 0x03;
751 initialize = microdia_624e_initialize;
752 start_stream = microdia_6242_start_stream;
753 stop_stream = microdia_6242_stop_stream;
754 break;
756 case USB_UDIA_MICRODIA_PRODUCT_ID_6243:
757 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6243.\n");
758 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
759 webcam_model = MICRODIA_6243;
760 ret = -ENODEV;
761 goto error;
763 case USB_UDIA_MICRODIA_PRODUCT_ID_6248:
764 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6248.\n");
765 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
766 webcam_model = MICRODIA_6248;
767 ret = -ENODEV;
768 goto error;
770 case USB_UDIA_MICRODIA_PRODUCT_ID_624B:
771 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 624B.\n");
772 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
773 webcam_model = MICRODIA_624B;
774 ret = -ENODEV;
775 goto error;
777 case USB_UDIA_MICRODIA_PRODUCT_ID_624C:
778 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 624C.\n");
779 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
780 webcam_model = MICRODIA_624C;
781 ret = -ENODEV;
782 goto error;
784 case USB_UDIA_MICRODIA_PRODUCT_ID_624E:
785 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 624E.\n");
786 webcam_model = MICRODIA_624E;
787 webcam_type = MICRODIA_SXGA;
788 sensor_slave_address = 0x30;
789 supported_fmts = 0x03;
790 initialize = microdia_624e_initialize;
791 start_stream = microdia_624e_start_stream;
792 stop_stream = microdia_624e_stop_stream;
793 break;
795 case USB_UDIA_MICRODIA_PRODUCT_ID_624F:
796 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 624F.\n");
797 webcam_model = MICRODIA_624F;
798 webcam_type = MICRODIA_SXGA;
799 sensor_slave_address = 0x30;
800 supported_fmts = 0x03;
801 initialize = microdia_624f_initialize;
802 start_stream = microdia_624f_start_stream;
803 stop_stream = microdia_624f_stop_stream;
804 set_exposure = microdia_624f_set_exposure;
805 flip_detect_f = microdia_624f_flip_detect;
806 break;
808 case USB_UDIA_MICRODIA_PRODUCT_ID_6253:
809 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6253.\n");
810 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
811 webcam_model = MICRODIA_6253;
812 ret = -ENODEV;
813 goto error;
815 case USB_UDIA_MICRODIA_PRODUCT_ID_6260:
816 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6260.\n");
817 webcam_model = MICRODIA_6260;
818 sensor_slave_address = 0x21;
819 supported_fmts = 0x08;
820 initialize = microdia_6260_initialize;
821 start_stream = microdia_6260_start_stream;
822 stop_stream = microdia_6260_stop_stream;
823 flip_detect_f = microdia_6260_flip_detect;
824 break;
826 case USB_UDIA_MICRODIA_PRODUCT_ID_6262:
827 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6262.\n");
828 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
829 webcam_model = MICRODIA_6262;
830 ret = -ENODEV;
831 goto error;
833 case USB_UDIA_MICRODIA_PRODUCT_ID_6270:
834 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6270.\n");
835 webcam_model = MICRODIA_6270;
836 sensor_slave_address = 0; // will be probed during initialisation
837 supported_fmts = 0x07;
838 initialize = microdia_6270_initialize;
839 start_stream = microdia_6270_start_stream;
840 stop_stream = microdia_6270_stop_stream;
841 set_exposure = mt9vx11_set_exposure;
842 set_hvflip = mt9vx11_set_hvflip;
843 set_auto_exposure = mt9v111_set_autoexposure;
844 set_auto_whitebalance = mt9v111_set_autowhitebalance;
845 break;
847 case USB_UDIA_MICRODIA_PRODUCT_ID_627A:
848 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 627A.\n");
849 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
850 webcam_model = MICRODIA_627A;
851 ret = -ENODEV;
852 goto error;
854 case USB_UDIA_MICRODIA_PRODUCT_ID_627B:
855 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 627B.\n");
856 webcam_model = MICRODIA_627B;
857 sensor_slave_address = 0x21;
858 supported_fmts = 0x07;
859 initialize = microdia_627b_initialize;
860 start_stream = microdia_627b_start_stream;
861 stop_stream = microdia_627b_stop_stream;
862 break;
864 case USB_UDIA_MICRODIA_PRODUCT_ID_627C:
865 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 627C.\n");
866 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
867 webcam_model = MICRODIA_627C;
868 ret = -ENODEV;
869 goto error;
871 case USB_UDIA_MICRODIA_PRODUCT_ID_627F:
872 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 627F.\n");
873 webcam_model = MICRODIA_627F;
874 webcam_type = MICRODIA_SXGA;
875 sensor_slave_address = 0x30;
876 supported_fmts = 0x03;
877 initialize = microdia_627f_initialize;
878 start_stream = microdia_624f_start_stream;
879 stop_stream = microdia_624f_stop_stream;
880 set_exposure = microdia_624f_set_exposure;
881 //flip_detect_f = microdia_624f_flip_detect;
882 break;
884 case USB_UDIA_MICRODIA_PRODUCT_ID_6280:
885 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6280.\n");
886 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
887 webcam_model = MICRODIA_6280;
888 ret = -ENODEV;
889 goto error;
891 case USB_UDIA_MICRODIA_PRODUCT_ID_6282:
892 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6282.\n");
893 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
894 webcam_model = MICRODIA_6282;
895 ret = -ENODEV;
896 goto error;
898 case USB_UDIA_MICRODIA_PRODUCT_ID_6283:
899 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6283.\n");
900 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
901 webcam_model = MICRODIA_6283;
902 ret = -ENODEV;
903 goto error;
905 case USB_UDIA_MICRODIA_PRODUCT_ID_6288:
906 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6288.\n");
907 webcam_model = MICRODIA_6288;
908 sensor_slave_address = 0x30;
909 supported_fmts = 0x03;
910 initialize = microdia_6288_initialize;
911 start_stream = microdia_6288_start_stream;
912 stop_stream = microdia_6288_stop_stream;
913 break;
915 case USB_UDIA_MICRODIA_PRODUCT_ID_628A:
916 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 628A.\n");
917 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
918 webcam_model = MICRODIA_628A;
919 ret = -ENODEV;
920 goto error;
922 case USB_UDIA_MICRODIA_PRODUCT_ID_628B:
923 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 628B.\n");
924 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
925 webcam_model = MICRODIA_628B;
926 ret = -ENODEV;
927 goto error;
929 case USB_UDIA_MICRODIA_PRODUCT_ID_628C:
930 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 628C.\n");
931 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
932 webcam_model = MICRODIA_628C;
933 ret = -ENODEV;
934 goto error;
936 case USB_UDIA_MICRODIA_PRODUCT_ID_628E:
937 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 628E.\n");
938 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
939 webcam_model = MICRODIA_628E;
940 ret = -ENODEV;
941 goto error;
943 case USB_UDIA_MICRODIA_PRODUCT_ID_628F:
944 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 628F.\n");
945 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
946 webcam_model = MICRODIA_628F;
947 ret = -ENODEV;
948 goto error;
950 case USB_UDIA_MICRODIA_PRODUCT_ID_62A0:
951 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 62A0.\n");
952 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
953 webcam_model = MICRODIA_62A0;
954 ret = -ENODEV;
955 goto error;
957 case USB_UDIA_MICRODIA_PRODUCT_ID_62A2:
958 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 62A2.\n");
959 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
960 webcam_model = MICRODIA_62A2;
961 ret = -ENODEV;
962 goto error;
964 case USB_UDIA_MICRODIA_PRODUCT_ID_62B0:
965 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 62B0.\n");
966 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
967 webcam_model = MICRODIA_62B0;
968 ret = -ENODEV;
969 goto error;
971 case USB_UDIA_MICRODIA_PRODUCT_ID_62B3:
972 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 62B3.\n");
973 webcam_model = MICRODIA_62B3;
974 sensor_slave_address = 0x30;
975 supported_fmts = 0x03;
976 initialize = microdia_6288_initialize;
977 start_stream = microdia_6288_start_stream;
978 stop_stream = microdia_6288_stop_stream;
979 break;
981 case USB_UDIA_MICRODIA_PRODUCT_ID_62BA:
982 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 62BA.\n");
983 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
984 webcam_model = MICRODIA_62BA;
985 ret = -ENODEV;
986 goto error;
988 case USB_UDIA_MICRODIA_PRODUCT_ID_62BB:
989 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 62BB.\n");
990 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
991 webcam_model = MICRODIA_62BB;
992 ret = -ENODEV;
993 goto error;
995 case USB_UDIA_MICRODIA_PRODUCT_ID_62BC:
996 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 62BC.\n");
997 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
998 webcam_model = MICRODIA_62BC;
999 ret = -ENODEV;
1000 goto error;
1002 case USB_UDIA_MICRODIA_PRODUCT_ID_62BE:
1003 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 62BE.\n");
1004 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
1005 webcam_model = MICRODIA_62BE;
1006 ret = -ENODEV;
1007 goto error;
1009 case USB_UDIA_MICRODIA_PRODUCT_ID_6128:
1010 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6128.\n");
1011 webcam_model = MICRODIA_6128;
1012 webcam_type = MICRODIA_SXGA;
1013 sensor_slave_address = 0x34;
1014 initialize = microdia_6128_initialize;
1015 start_stream = microdia_6128_start_stream;
1016 stop_stream = microdia_6128_stop_stream;
1017 set_contrast = NULL; // sn9c325_set_contrast
1018 set_brightness = NULL; // sn9c325_set_brightness
1019 set_gamma = NULL; // sn9c325_set_gamma
1020 set_sharpness = NULL; // sn9c325_set_sharpness
1021 break;
1023 case USB_UDIA_MICRODIA_PRODUCT_ID_612A:
1024 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 612A.\n");
1025 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
1026 webcam_model = MICRODIA_612A;
1027 set_contrast = NULL; // sn9c325_set_contrast
1028 set_brightness = NULL; // sn9c325_set_brightness
1029 set_gamma = NULL; // sn9c325_set_gamma
1030 set_sharpness = NULL; // sn9c325_set_sharpness
1031 ret = -ENODEV;
1032 goto error;
1034 default:
1035 ret = -ENODEV;
1036 goto error;
1039 // "Clone"-devices:
1040 else if (vendor_id == USB_VENDOR_ID_MICROSOFT) {
1041 switch (product_id) {
1042 case USB_UDIA_MICROSOFT_PRODUCT_ID_00F4:
1043 UDIA_INFO("Microdia PID 628F Compatible USB2.0 Webcam:\n Microsoft LifeCam VX-6000 (045e:00f4)\n");
1044 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
1045 webcam_model = MICRODIA_628F;
1046 webcam_type = MICRODIA_SXGA;
1047 sensor_slave_address = 0x30;
1048 ret = -ENODEV;
1049 goto error;
1050 default:
1051 ret = -ENODEV;
1052 goto error;
1055 else if (vendor_id == USB_VENDOR_ID_CHICONY) {
1056 switch (product_id) {
1057 case USB_UDIA_CHICONY_PRODUCT_ID_A128:
1058 UDIA_INFO("Microdia PID 62BE Compatible USB2.0 Webcam:\n Chicony Panda 7 (04f2:a128)\n");
1059 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
1060 webcam_model = MICRODIA_62BE;
1061 ret = -ENODEV;
1062 goto error;
1063 default:
1064 ret = -ENODEV;
1065 goto error;
1068 else if (vendor_id == USB_VENDOR_ID_TRUST) {
1069 switch (product_id) {
1070 case USB_UDIA_TRUST_PRODUCT_ID_013D:
1071 UDIA_INFO("Microdia PID 627B Compatible USB2.0 Webcam:\n Trust WB-3600R (145f:013d)\n");
1072 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
1073 webcam_model = MICRODIA_627B;
1074 sensor_slave_address = 0x21;
1075 ret = -ENODEV;
1076 goto error;
1077 default:
1078 ret = -ENODEV;
1079 goto error;
1081 } else {
1082 ret = -ENODEV;
1083 goto error;
1086 // Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device
1087 dev = kzalloc(sizeof(struct usb_microdia), GFP_KERNEL);
1089 if (dev == NULL) {
1090 UDIA_ERROR("Out of memory !\n");
1091 ret = -ENOMEM;
1092 goto error;
1095 // Init mutexes, spinlock, etc.
1096 mutex_init(&dev->mutex);
1097 kref_init(&dev->vopen);
1099 // Save pointers
1100 dev->webcam_model = webcam_model;
1101 dev->webcam_type = webcam_type;
1102 if (webcam_model == MICRODIA_6260)
1103 dev->frame_size_divisor = MICRODIA_FRAME_SIZE_DIVISOR_6260;
1104 else
1105 dev->frame_size_divisor = MICRODIA_FRAME_SIZE_DIVISOR_DEFAULT;
1106 dev->initialize = initialize;
1107 dev->stop_stream = stop_stream;
1108 dev->start_stream = start_stream;
1109 dev->set_contrast = set_contrast;
1110 dev->set_brightness = set_brightness;
1111 dev->set_gamma = set_gamma;
1112 dev->set_exposure = set_exposure;
1113 if (flip_detect) {
1114 UDIA_INFO("Rotate detection enabled\n");
1115 dev->flip_detect = flip_detect_f;
1117 dev->set_hvflip = set_hvflip;
1118 dev->set_sharpness = set_sharpness;
1119 dev->set_auto_exposure = set_auto_exposure;
1120 dev->set_auto_whitebalance = set_auto_whitebalance;
1121 dev->udev = udev;
1122 dev->interface = interface;
1123 dev->sensor_slave_address = sensor_slave_address;
1124 dev->sensor_flags = sensor_flags;
1125 dev->supported_fmts = supported_fmts;
1127 // Read the product release
1128 dev->release = le16_to_cpu(udev->descriptor.bcdDevice);
1129 UDIA_INFO("Release: %04x\n", dev->release);
1131 // How many interfaces (1 or 3) ?
1132 bNumInterfaces = udev->config->desc.bNumInterfaces;
1133 UDIA_INFO("Number of interfaces : %d\n", bNumInterfaces);
1136 // Switch on the camera (to detect size of buffers)
1137 dev_microdia_camera_on(dev);
1140 // Set up the endpoint information
1141 // use only the first int-in and isoc-in endpoints
1142 // for the current alternate setting
1143 iface_desc = interface->cur_altsetting;
1145 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1146 endpoint = &iface_desc->endpoint[i].desc;
1148 if (!dev->int_in_endpointAddr
1149 && ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
1150 && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
1151 // we found an interrupt in endpoint
1152 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1154 dev->int_in_size = buffer_size;
1155 dev->int_in_endpointAddr = (endpoint->bEndpointAddress & 0xf);
1158 if (!dev->isoc_in_endpointAddr
1159 && ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
1160 && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)) {
1161 // we found an isoc in endpoint
1162 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1164 dev->isoc_in_size = buffer_size;
1165 dev->isoc_in_endpointAddr = (endpoint->bEndpointAddress & 0xf);
1169 if (!(dev->int_in_endpointAddr && dev->isoc_in_endpointAddr)) {
1170 UDIA_ERROR("Could not find both int-in and isoc-in endpoints");
1171 ret = -ENODEV;
1172 goto free_dev;
1175 usb_microdia_default_settings(dev);
1177 dev_microdia_camera_off(dev);
1179 // Initialize the video device
1180 dev->vdev = video_device_alloc();
1182 if (!dev->vdev) {
1183 ret = -ENOMEM;
1184 goto free_dev;
1187 // Initialize the camera
1188 dev_microdia_initialize_device(dev);
1190 // Register the video device
1191 ret = v4l_microdia_register_video_device(dev);
1193 if (ret) {
1194 goto free_dev;
1197 // Create the entries in the sys filesystem
1198 microdia_create_sysfs_files(dev->vdev);
1200 // Save our data pointer in this interface device
1201 usb_set_intfdata(interface, dev);
1203 return 0;
1205 free_dev:
1206 kref_put(&dev->vopen, usb_microdia_delete);
1207 error:
1208 return ret;
1211 void usb_microdia_delete(struct kref *kref)
1213 struct usb_microdia *dev;
1214 dev = container_of(kref, struct usb_microdia, vopen);
1216 if (dev->vdev != NULL) {
1217 microdia_remove_sysfs_files(dev->vdev);
1218 v4l_microdia_unregister_video_device(dev);
1220 kfree(dev);
1223 /**
1224 * @param interface
1226 * @brief This function is called when the device is disconnected
1227 * or when the kernel module is unloaded.
1229 static void usb_microdia_disconnect(struct usb_interface *interface)
1231 struct usb_microdia *dev = usb_get_intfdata(interface);
1233 UDIA_INFO("Microdia USB2.0 Camera disconnected\n");
1235 usb_set_intfdata(interface, NULL);
1237 mutex_lock(&open_lock);
1238 kref_put(&dev->vopen, usb_microdia_delete);
1239 mutex_unlock(&open_lock);
1244 * @var usb_microdia_driver
1246 * This variable contains some callback
1248 static struct usb_driver usb_microdia_driver = {
1249 .name = "usb_microdia_driver",
1250 .probe = usb_microdia_probe,
1251 .disconnect = usb_microdia_disconnect,
1252 .id_table = microdia_table,
1255 module_param(fps, int, 0444); /**< @brief Module parameter frames per second */
1256 module_param(hflip, int, 0444); /**< @brief Module parameter horizontal flip process */
1257 module_param(vflip, int, 0444); /**< @brief Module parameter vertical flip process */
1258 module_param(flip_detect, int, 0444); /**< @brief Module parameter flip detect */
1259 module_param(auto_exposure, int, 0444); /**< @brief Module parameter automatic exposure control */
1260 module_param(auto_whitebalance, int, 0444); /**< @brief Module parameter automatic whitebalance control */
1261 module_param(brightness, int, 0444); /**< @brief Module parameter brightness */
1262 module_param(whiteness, int, 0444); /**< @brief Module parameter whiteness */
1263 module_param(contrast, int, 0444); /**< @brief Module parameter contrast */
1264 module_param(exposure, int, 0444); /**< @brief Module parameter exposure */
1265 module_param(sharpness, int, 0444); /**< @brief Module parameter sharpness */
1267 module_param(min_buffers, int, 0444);
1268 module_param(max_buffers, int, 0444);
1271 /**
1272 * @returns 0 if all is OK
1274 * @brief Initialize the driver.
1276 * This function is called at first.
1277 * This function permits to define the default values from the command line.
1279 static int __init usb_microdia_init(void)
1281 int result;
1283 UDIA_INFO("Microdia USB2.0 webcam driver startup\n");
1285 debug_dir = debugfs_create_dir(debug_dir_name, NULL);
1286 if(debug_dir)
1287 debug_file = debugfs_create_u8(debug_file_name, S_IRUGO | S_IWUGO,
1288 debug_dir, &debug_level);
1290 if(fps < 10 || fps > 30) {
1291 UDIA_WARNING("Framerate out of bounds [10-30]! Defaulting to 25\n");
1292 fps = 25;
1295 if(vflip != 0 && vflip != 1) {
1296 UDIA_WARNING("Vertical flip should be 0 or 1! Defaulting to 0\n");
1297 vflip = 0;
1300 if(hflip != 0 && hflip != 1) {
1301 UDIA_WARNING("Horizontal flip should be 0 or 1! Defaulting to 0\n");
1302 hflip = 0;
1305 if (sharpness < 0 || sharpness > 0x3f) {
1306 UDIA_WARNING("Sharpness should be 0 to 63 ! Defaulting to 31\n");
1307 sharpness = 0x1f;
1310 if(auto_exposure != 0 && auto_exposure != 1) {
1311 UDIA_WARNING("Automatic exposure should be 0 or 1! "
1312 "Defaulting to 1\n");
1313 auto_exposure = 1;
1316 if(auto_whitebalance != 0 && auto_whitebalance != 1) {
1317 UDIA_WARNING("Automatic whitebalance should be 0 or 1! "
1318 "Defaulting to 1\n");
1319 auto_whitebalance = 1;
1322 if (min_buffers < 2) {
1323 UDIA_WARNING("Minimum buffers can't be less then 2! "
1324 "Defaulting to 2\n");
1325 min_buffers = 2;
1329 if (min_buffers > max_buffers) {
1330 UDIA_WARNING("Minimum buffers must be less then or equal to "
1331 "max buffers! Defaulting to 2, 10\n");
1332 min_buffers = 2;
1333 max_buffers = 5;
1336 // Register the driver with the USB subsystem
1337 result = usb_register(&usb_microdia_driver);
1339 if (result)
1340 UDIA_ERROR("usb_register failed ! Error number %d\n", result);
1342 UDIA_INFO(DRIVER_VERSION " : " DRIVER_DESC "\n");
1344 return result;
1348 /**
1349 * @brief Close the driver
1351 * This function is called at last when you unload the driver.
1353 static void __exit usb_microdia_exit(void)
1355 UDIA_INFO("usb_microdia_exit: Microdia USB2.0 webcam driver shutdown\n");
1357 if(debug_file)
1358 debugfs_remove(debug_file);
1359 if(debug_dir)
1360 debugfs_remove(debug_dir);
1362 // Deregister this driver with the USB subsystem
1363 usb_deregister(&usb_microdia_driver);
1367 module_init(usb_microdia_init); /**< @brief Module initialize */
1368 module_exit(usb_microdia_exit); /**< @brief Module exit */
1371 MODULE_PARM_DESC(fps, "Frames per second [10-30]"); /**< @brief Description of 'fps' parameter */
1372 MODULE_PARM_DESC(hflip, "Horizontal image flip"); /**< @brief Description of 'hflip' parameter */
1373 MODULE_PARM_DESC(vflip, "Vertical image flip"); /**< @brief Description of 'vflip' parameter */
1374 MODULE_PARM_DESC(flip_detect, "Image flip detection"); /**< @brief Description of 'vflip_detect' parameter */
1375 MODULE_PARM_DESC(auto_exposure, "Automatic exposure control"); /**< @brief Description of 'auto_exposure' parameter */
1376 MODULE_PARM_DESC(auto_whitebalance, "Automatic whitebalance"); /**< @brief Description of 'auto_whitebalance' parameter */
1377 MODULE_PARM_DESC(brightness, "Brightness setting"); /**< @brief Description of 'brightness' parameter */
1378 MODULE_PARM_DESC(whiteness, "Whiteness setting"); /**< @brief Description of 'whiteness' parameter */
1379 MODULE_PARM_DESC(exposure, "Exposure setting"); /**< @brief Description of 'exposure' parameter */
1380 MODULE_PARM_DESC(contrast, "Contrast setting"); /**< @brief Description of 'contrast' parameter */
1381 MODULE_PARM_DESC(sharpness, "Sharpness setting"); /**< @brief Description of 'sharpness' parameter */
1383 MODULE_PARM_DESC(min_buffers, "Minimum number of image buffers");
1384 MODULE_PARM_DESC(max_buffers, "Maximum number of image buffers");
1386 MODULE_LICENSE("GPL"); /**< @brief Driver is under licence GPL */
1387 MODULE_AUTHOR(DRIVER_AUTHOR); /**< @brief Driver is written by Nicolas VIVIEN */
1388 MODULE_DESCRIPTION(DRIVER_DESC); /**< @brief Define the description of the driver */
1389 MODULE_SUPPORTED_DEVICE(DRIVER_SUPPORT); /**< @brief List of supported device */