Fix possible NULL reference bug
[microdia.git] / microdia-usb.c
blob30417144be9a60658fcaae216946c7685ae2a2c3
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);
275 usb_microdia_isoc_cleanup(dev);
276 return ret;
280 return 0;
284 /**
285 * @param urb URB structure
287 * @brief ISOC handler
289 * This function is called as an URB transfert is complete (Isochronous pipe).
290 * So, the traitement is done in interrupt time, so it has be fast, not crash,
291 * ans not stall. Neat.
293 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
294 void usb_microdia_isoc_handler(struct urb *urb, struct pt_regs *regs)
295 #else
296 void usb_microdia_isoc_handler(struct urb *urb)
297 #endif
299 int i;
300 int ret;
302 int framestatus;
303 unsigned int framelen;
304 int flags;
306 unsigned char *iso_buf = NULL;
308 void *mem = NULL;
309 struct microdia_buffer *buf = NULL;
310 struct usb_microdia *dev = urb->context;
311 struct microdia_video_queue *queue = &dev->queue;
313 unsigned char frame_header[] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
315 UDIA_STREAM("Isoc handler\n");
317 switch (urb->status) {
318 case 0:
319 break;
321 default:
322 UDIA_WARNING("Non-zero status (%d) in video "
323 "completion handler.\n", urb->status);
325 case -ENOENT: /* usb_kill_urb() called. */
326 if (queue->frozen)
327 return;
329 case -ECONNRESET: /* usb_unlink_urb() called. */
330 case -ESHUTDOWN: /* The endpoint is being disabled. */
331 microdia_queue_cancel(queue);
332 return;
335 spin_lock_irqsave(&queue->irqlock, flags);
336 if (!list_empty(&queue->irqqueue))
337 buf = list_first_entry(&queue->irqqueue, struct microdia_buffer,
338 queue);
339 spin_unlock_irqrestore(&queue->irqlock, flags);
341 for (i=0; i<urb->number_of_packets; i++) {
342 framestatus = urb->iso_frame_desc[i].status;
343 if (framestatus != 0) {
344 UDIA_ERROR("Iso frame %d of USB has error %d\n",
345 i, framestatus);
346 continue;
348 framelen = urb->iso_frame_desc[i].actual_length;
349 iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
351 if (buf == NULL)
352 continue;
354 if (memcmp(iso_buf, frame_header, 6) == 0 && framelen == 64) {
355 UDIA_DEBUG("Frame Resolution: %dx%d\n",
356 iso_buf[0x3a] << 4, iso_buf[0x3b] << 3);
357 if (buf->buf.bytesused != 0)
358 buf->state = MICRODIA_BUF_STATE_DONE;
359 } else {
360 if (buf->state != MICRODIA_BUF_STATE_ACTIVE)
361 buf->state = MICRODIA_BUF_STATE_ACTIVE;
363 if (framelen + buf->buf.bytesused > queue->frame_size) {
364 UDIA_WARNING("Frame Buffer overflow!\n");
365 dev->vframes_overflow++;
366 buf->state = MICRODIA_BUF_STATE_DONE;
368 framelen = min(queue->frame_size - buf->buf.bytesused,
369 framelen);
370 mem = queue->mem + buf->buf.m.offset +
371 buf->buf.bytesused;
372 memcpy(mem, iso_buf, framelen);
373 buf->buf.bytesused += framelen;
375 if (buf->state == MICRODIA_BUF_STATE_DONE ||
376 buf->state == MICRODIA_BUF_STATE_ERROR) {
377 buf = microdia_queue_next_buffer(queue, buf);
378 if (buf == NULL)
379 dev->vframes_dropped++;
383 urb->dev = dev->udev;
385 ret = usb_submit_urb(urb, GFP_ATOMIC);
387 if (ret != 0) {
388 UDIA_ERROR("Error (%d) re-submitting urb in "
389 "microdia_isoc_handler.\n", ret);
394 /**
395 * @param dev Device structure
397 * @brief Clean-up all the ISOC buffers
399 * This function permits to clean-up all the ISOC buffers.
401 void usb_microdia_isoc_cleanup(struct usb_microdia *dev)
403 int i;
404 struct urb *urb;
406 UDIA_DEBUG("Isoc cleanup\n");
408 if (dev == NULL)
409 return;
411 for (i=0; i<MAX_ISO_BUFS; i++) {
412 urb = dev->isobuf[i].urb;
413 if (urb == NULL)
414 continue;
416 usb_kill_urb(urb);
417 if (dev->isobuf[i].data) {
418 kfree(dev->isobuf[i].data);
419 dev->isobuf[i].data = NULL;
421 usb_free_urb(urb);
422 dev->isobuf[i].urb = NULL;
428 /**
429 * @param dev Device structure
430 * @param index Choice of the interface
432 * @returns 0 if all is OK
434 * @brief Send the message SET_FEATURE and choose the interface
436 * This function permits to send the message SET_FEATURE on the USB bus.
438 int usb_microdia_set_feature(struct usb_microdia *dev, int index)
440 int result;
441 struct usb_device *udev = dev->udev;
443 result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
444 USB_REQ_SET_FEATURE,
445 USB_TYPE_STANDARD | USB_DIR_OUT | USB_RECIP_DEVICE,
446 USB_DEVICE_REMOTE_WAKEUP,
447 index,
448 NULL,
450 500);
452 if (result < 0)
453 UDIA_ERROR("SET FEATURE fail !\n");
454 else
455 UDIA_DEBUG("SET FEATURE\n");
457 return result;
461 /**
462 * @param dev Device structure
464 * @returns 0 if all is OK
466 * @brief Send the message SET_CONFIGURATION
468 * This function permits to send the message SET_CONFIGURATION on the USB bus.
470 int usb_microdia_set_configuration(struct usb_microdia *dev)
472 int result;
473 struct usb_device *udev = dev->udev;
475 result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
476 USB_REQ_SET_CONFIGURATION,
477 USB_TYPE_STANDARD | USB_DIR_OUT | USB_RECIP_DEVICE,
479 udev->config[0].desc.bConfigurationValue,
480 NULL,
482 500);
484 if (result < 0)
485 UDIA_ERROR("SET CONFIGURATION fail !\n");
486 else
487 UDIA_DEBUG("SET CONFIGURATION %d\n", udev->config[0].desc.bConfigurationValue);
489 return result;
494 * @param dev Device structure
495 * @param value register to write to
496 * @param data
497 * @param length number of bytes
499 * @returns 0 if all is OK
501 * @brief Write a 16-bit value to a 16-bit register
503 * This function permits to write a 16-bit value to a 16-bit register on the USB bus.
505 int usb_microdia_control_write(struct usb_microdia *dev, __u16 value, __u8 *data, __u16 length)
507 int result;
508 struct usb_device *udev = dev->udev;
510 result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
511 0x08,
512 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
513 value,
514 0x00,
515 data,
516 length,
517 500);
519 if (result < 0)
520 UDIA_ERROR("Write register failed index = 0x%02X\n", value);
522 return result;
526 * @param dev
527 * @param commands
528 * @param data
529 * @param cmdlen
530 * @param datalen
532 * @returns 0 if all is OK
534 * @brief Write a series of 16-bit "commands" using the same buffer
536 int usb_microdia_control_write_multi(struct usb_microdia *dev, __u16 *commands, __u8 *data,
537 __u16 cmdlen, __u16 datalen)
539 int result, i;
541 for(i = 0; i < cmdlen; i++) {
542 result = usb_microdia_control_write(dev, commands[i], data, datalen);
544 if(result < 0)
545 return result;
548 return 0;
552 * @param dev Device structure
553 * @param index register to read from
554 * @param data
555 * @param length number of bytes
557 * @returns 0 if all is OK
559 * @brief Read a 16-bit value from a 16-bit register
561 * This function permits to read a 16-bit value from a 16-bit register on the USB bus.
563 int usb_microdia_control_read(struct usb_microdia *dev, __u16 index, __u8 *data, __u16 length)
565 int result;
567 struct usb_device *udev = dev->udev;
569 *data = 0;
571 result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
572 0x00,
573 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
574 index,
575 0x00,
576 data,
577 length,
578 500);
580 if (result < 0)
581 UDIA_ERROR("Read register failed 0x%02X\n", index);
583 return result;
587 /**
588 * @param dev
590 * @returns 0 if all is OK
592 * @brief Set the default value about the video settings.
594 * This function permits to set the video settings for each video camera model.
597 static int usb_microdia_default_settings(struct usb_microdia *dev)
599 struct v4l2_pix_format *def_fmt;
601 dev->vframes_overflow = 0;
602 dev->vframes_incomplete = 0;
603 dev->vframes_dropped = 0;
605 dev->queue.min_buffers = min_buffers;
606 dev->queue.max_buffers = max_buffers;
608 def_fmt = v4l2_enum_supported_formats(dev, 0);
610 switch (dev->webcam_model) {
611 default:
612 dev->vsettings.fps = fps;
613 dev->vsettings.vflip = vflip;
614 dev->vsettings.hflip = hflip;
615 dev->vsettings.brightness = brightness & 0xffff;
616 dev->vsettings.contrast = contrast & 0xffff;
617 dev->vsettings.whiteness = whiteness & 0xffff;
618 dev->vsettings.exposure = exposure & 0xffff;
619 dev->vsettings.sharpness = sharpness & 0x3f;
620 dev->vsettings.auto_exposure = auto_exposure & 1;
621 dev->vsettings.auto_whitebalance = auto_whitebalance & 1;
622 dev->vsettings.hue = 0xffff;
624 if (def_fmt) {
625 memcpy(&(dev->vsettings.format),
626 def_fmt,
627 sizeof(struct v4l2_pix_format));
630 v4l_microdia_select_video_mode(dev, MICRODIA_640x480);
631 break;
633 return 0;
636 extern int microdia_6240_initialize(struct usb_microdia *dev);
637 extern int microdia_6240_start_stream(struct usb_microdia *dev);
638 extern int microdia_6240_stop_stream(struct usb_microdia *dev);
639 extern int microdia_6242_start_stream(struct usb_microdia *dev);
640 extern int microdia_6242_stop_stream(struct usb_microdia *dev);
641 extern int microdia_624e_initialize(struct usb_microdia *dev);
642 extern int microdia_624e_start_stream(struct usb_microdia *dev);
643 extern int microdia_624e_stop_stream(struct usb_microdia *dev);
644 extern int microdia_624f_initialize(struct usb_microdia *dev);
645 extern int microdia_624f_stop_stream(struct usb_microdia *dev);
646 extern int microdia_624f_start_stream(struct usb_microdia *dev);
647 extern int microdia_624f_set_exposure(struct usb_microdia *dev);
648 extern int microdia_624f_flip_detect(struct usb_microdia *dev);
649 extern int microdia_6260_initialize(struct usb_microdia *dev);
650 extern int microdia_6260_start_stream(struct usb_microdia *dev);
651 extern int microdia_6260_stop_stream(struct usb_microdia *dev);
652 extern int microdia_6260_flip_detect(struct usb_microdia *dev);
653 extern int microdia_6270_initialize(struct usb_microdia *dev);
654 extern int microdia_6270_start_stream(struct usb_microdia *dev);
655 extern int microdia_6270_stop_stream(struct usb_microdia *dev);
656 extern int microdia_627b_initialize(struct usb_microdia *dev);
657 extern int microdia_627b_start_stream(struct usb_microdia *dev);
658 extern int microdia_627b_stop_stream(struct usb_microdia *dev);
659 extern int microdia_627f_initialize(struct usb_microdia *dev);
660 extern int microdia_6288_initialize(struct usb_microdia *dev);
661 extern int microdia_6288_start_stream(struct usb_microdia *dev);
662 extern int microdia_6288_stop_stream(struct usb_microdia *dev);
663 extern int microdia_6128_initialize(struct usb_microdia *dev);
664 extern int microdia_6128_start_stream(struct usb_microdia *dev);
665 extern int microdia_6128_stop_stream(struct usb_microdia *dev);
668 /**
669 * @param interface
670 * @param id
672 * @returns 0 if all is OK
674 * @brief Load the driver
676 * This function detects the device and allocate the buffers for the device
677 * and the video interface.
679 static int usb_microdia_probe(struct usb_interface *interface, const struct usb_device_id *id)
681 int i;
682 int ret;
683 size_t buffer_size;
685 int vendor_id;
686 int product_id;
687 int bNumInterfaces;
688 int webcam_model;
689 int webcam_type;
690 __u8 sensor_slave_address = 0;
691 __u8 supported_fmts = 0;
692 __u8 sensor_flags = 0x80; // 2-WIRE,100KHz
693 int (*initialize)(struct usb_microdia *) = NULL;
694 int (*stop_stream)(struct usb_microdia *) = NULL;
695 int (*start_stream)(struct usb_microdia *) = NULL;
696 int (*set_contrast)(struct usb_microdia *) = NULL;
697 int (*set_brightness)(struct usb_microdia *) = NULL;
698 int (*set_gamma)(struct usb_microdia *) = NULL;
699 int (*set_exposure)(struct usb_microdia *) = NULL;
700 int (*flip_detect_f)(struct usb_microdia *) = NULL;
701 int (*set_hvflip)(struct usb_microdia *) = NULL;
702 int (*set_sharpness)(struct usb_microdia *) = NULL;
703 int (*set_auto_exposure)(struct usb_microdia *) = NULL;
704 int (*set_auto_whitebalance)(struct usb_microdia *) = NULL;
706 struct usb_microdia *dev = NULL;
707 struct usb_device *udev = interface_to_usbdev(interface);
708 struct usb_host_interface *iface_desc;
709 struct usb_endpoint_descriptor *endpoint;
711 // Set default device parameters:
712 webcam_type = MICRODIA_VGA;
713 sensor_flags = SN9C20X_I2C_2WIRE;
714 set_contrast = sn9c20x_set_contrast;
715 set_brightness = sn9c20x_set_brightness;
716 set_gamma = sn9c20x_set_gamma;
717 set_sharpness = sn9c20x_set_sharpness;
719 // Get USB VendorID and ProductID
720 vendor_id = le16_to_cpu(udev->descriptor.idVendor);
721 product_id = le16_to_cpu(udev->descriptor.idProduct);
723 // Check if we can handle this device
724 UDIA_DEBUG("Probe function called with VendorID=%04X, ProductID=%04X and InterfaceNumber=%d\n",
725 vendor_id, product_id, interface->cur_altsetting->desc.bInterfaceNumber);
727 // The interface are probed one by one.
728 // We are interested in the video interface (always the interface '0')
729 // The interfaces '1' or '2' (if presents) are the audio control.
730 if (interface->cur_altsetting->desc.bInterfaceNumber > 0) {
731 ret = -ENODEV;
732 goto error;
735 // Detect device
736 if (vendor_id == USB_VENDOR_ID_MICRODIA) {
737 switch (product_id) {
738 case USB_UDIA_MICRODIA_PRODUCT_ID_6240:
739 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6240.\n");
740 UDIA_INFO("This device is under development. Please contact microdia@googlegroups for further info\n");
741 webcam_model = MICRODIA_6240;
742 initialize = microdia_6240_initialize;
743 start_stream = microdia_6240_start_stream;
744 stop_stream = microdia_6240_stop_stream;
745 break;
747 case USB_UDIA_MICRODIA_PRODUCT_ID_6242:
748 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6242.\n");
749 webcam_model = MICRODIA_6242;
750 sensor_slave_address = 0x5d;
751 supported_fmts = 0x03;
752 initialize = microdia_624e_initialize;
753 start_stream = microdia_6242_start_stream;
754 stop_stream = microdia_6242_stop_stream;
755 break;
757 case USB_UDIA_MICRODIA_PRODUCT_ID_6243:
758 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6243.\n");
759 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
760 webcam_model = MICRODIA_6243;
761 ret = -ENODEV;
762 goto error;
764 case USB_UDIA_MICRODIA_PRODUCT_ID_6248:
765 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6248.\n");
766 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
767 webcam_model = MICRODIA_6248;
768 ret = -ENODEV;
769 goto error;
771 case USB_UDIA_MICRODIA_PRODUCT_ID_624B:
772 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 624B.\n");
773 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
774 webcam_model = MICRODIA_624B;
775 ret = -ENODEV;
776 goto error;
778 case USB_UDIA_MICRODIA_PRODUCT_ID_624C:
779 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 624C.\n");
780 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
781 webcam_model = MICRODIA_624C;
782 ret = -ENODEV;
783 goto error;
785 case USB_UDIA_MICRODIA_PRODUCT_ID_624E:
786 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 624E.\n");
787 webcam_model = MICRODIA_624E;
788 webcam_type = MICRODIA_SXGA;
789 sensor_slave_address = 0x30;
790 supported_fmts = 0x03;
791 initialize = microdia_624e_initialize;
792 start_stream = microdia_624e_start_stream;
793 stop_stream = microdia_624e_stop_stream;
794 break;
796 case USB_UDIA_MICRODIA_PRODUCT_ID_624F:
797 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 624F.\n");
798 webcam_model = MICRODIA_624F;
799 webcam_type = MICRODIA_SXGA;
800 sensor_slave_address = 0x30;
801 supported_fmts = 0x03;
802 initialize = microdia_624f_initialize;
803 start_stream = microdia_624f_start_stream;
804 stop_stream = microdia_624f_stop_stream;
805 set_exposure = microdia_624f_set_exposure;
806 flip_detect_f = microdia_624f_flip_detect;
807 break;
809 case USB_UDIA_MICRODIA_PRODUCT_ID_6253:
810 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6253.\n");
811 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
812 webcam_model = MICRODIA_6253;
813 ret = -ENODEV;
814 goto error;
816 case USB_UDIA_MICRODIA_PRODUCT_ID_6260:
817 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6260.\n");
818 webcam_model = MICRODIA_6260;
819 sensor_slave_address = 0x21;
820 supported_fmts = 0x08;
821 initialize = microdia_6260_initialize;
822 start_stream = microdia_6260_start_stream;
823 stop_stream = microdia_6260_stop_stream;
824 flip_detect_f = microdia_6260_flip_detect;
825 break;
827 case USB_UDIA_MICRODIA_PRODUCT_ID_6262:
828 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6262.\n");
829 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
830 webcam_model = MICRODIA_6262;
831 ret = -ENODEV;
832 goto error;
834 case USB_UDIA_MICRODIA_PRODUCT_ID_6270:
835 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6270.\n");
836 webcam_model = MICRODIA_6270;
837 sensor_slave_address = 0; // will be probed during initialisation
838 supported_fmts = 0x07;
839 initialize = microdia_6270_initialize;
840 start_stream = microdia_6270_start_stream;
841 stop_stream = microdia_6270_stop_stream;
842 set_exposure = mt9vx11_set_exposure;
843 set_hvflip = mt9vx11_set_hvflip;
844 set_auto_exposure = mt9v111_set_autoexposure;
845 set_auto_whitebalance = mt9v111_set_autowhitebalance;
846 break;
848 case USB_UDIA_MICRODIA_PRODUCT_ID_627A:
849 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 627A.\n");
850 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
851 webcam_model = MICRODIA_627A;
852 ret = -ENODEV;
853 goto error;
855 case USB_UDIA_MICRODIA_PRODUCT_ID_627B:
856 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 627B.\n");
857 webcam_model = MICRODIA_627B;
858 sensor_slave_address = 0x21;
859 supported_fmts = 0x07;
860 initialize = microdia_627b_initialize;
861 start_stream = microdia_627b_start_stream;
862 stop_stream = microdia_627b_stop_stream;
863 break;
865 case USB_UDIA_MICRODIA_PRODUCT_ID_627C:
866 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 627C.\n");
867 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
868 webcam_model = MICRODIA_627C;
869 ret = -ENODEV;
870 goto error;
872 case USB_UDIA_MICRODIA_PRODUCT_ID_627F:
873 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 627F.\n");
874 webcam_model = MICRODIA_627F;
875 webcam_type = MICRODIA_SXGA;
876 sensor_slave_address = 0x30;
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 initialize = microdia_6288_initialize;
976 start_stream = microdia_6288_start_stream;
977 stop_stream = microdia_6288_stop_stream;
978 break;
980 case USB_UDIA_MICRODIA_PRODUCT_ID_62BA:
981 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 62BA.\n");
982 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
983 webcam_model = MICRODIA_62BA;
984 ret = -ENODEV;
985 goto error;
987 case USB_UDIA_MICRODIA_PRODUCT_ID_62BB:
988 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 62BB.\n");
989 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
990 webcam_model = MICRODIA_62BB;
991 ret = -ENODEV;
992 goto error;
994 case USB_UDIA_MICRODIA_PRODUCT_ID_62BC:
995 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 62BC.\n");
996 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
997 webcam_model = MICRODIA_62BC;
998 ret = -ENODEV;
999 goto error;
1001 case USB_UDIA_MICRODIA_PRODUCT_ID_62BE:
1002 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 62BE.\n");
1003 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
1004 webcam_model = MICRODIA_62BE;
1005 ret = -ENODEV;
1006 goto error;
1008 case USB_UDIA_MICRODIA_PRODUCT_ID_6128:
1009 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 6128.\n");
1010 webcam_model = MICRODIA_6128;
1011 webcam_type = MICRODIA_SXGA;
1012 sensor_slave_address = 0x34;
1013 initialize = microdia_6128_initialize;
1014 start_stream = microdia_6128_start_stream;
1015 stop_stream = microdia_6128_stop_stream;
1016 set_contrast = NULL; // sn9c325_set_contrast
1017 set_brightness = NULL; // sn9c325_set_brightness
1018 set_gamma = NULL; // sn9c325_set_gamma
1019 set_sharpness = NULL; // sn9c325_set_sharpness
1020 break;
1022 case USB_UDIA_MICRODIA_PRODUCT_ID_612A:
1023 UDIA_INFO("Microdia USB2.0 Webcam - Product ID 612A.\n");
1024 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
1025 webcam_model = MICRODIA_612A;
1026 set_contrast = NULL; // sn9c325_set_contrast
1027 set_brightness = NULL; // sn9c325_set_brightness
1028 set_gamma = NULL; // sn9c325_set_gamma
1029 set_sharpness = NULL; // sn9c325_set_sharpness
1030 ret = -ENODEV;
1031 goto error;
1033 default:
1034 ret = -ENODEV;
1035 goto error;
1038 // "Clone"-devices:
1039 else if (vendor_id == USB_VENDOR_ID_MICROSOFT) {
1040 switch (product_id) {
1041 case USB_UDIA_MICROSOFT_PRODUCT_ID_00F4:
1042 UDIA_INFO("Microdia PID 628F Compatible USB2.0 Webcam:\n Microsoft LifeCam VX-6000 (045e:00f4)\n");
1043 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
1044 webcam_model = MICRODIA_628F;
1045 webcam_type = MICRODIA_SXGA;
1046 sensor_slave_address = 0x30;
1047 ret = -ENODEV;
1048 goto error;
1049 default:
1050 ret = -ENODEV;
1051 goto error;
1054 else if (vendor_id == USB_VENDOR_ID_CHICONY) {
1055 switch (product_id) {
1056 case USB_UDIA_CHICONY_PRODUCT_ID_A128:
1057 UDIA_INFO("Microdia PID 62BE Compatible USB2.0 Webcam:\n Chicony Panda 7 (04f2:a128)\n");
1058 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
1059 webcam_model = MICRODIA_62BE;
1060 ret = -ENODEV;
1061 goto error;
1062 default:
1063 ret = -ENODEV;
1064 goto error;
1067 else if (vendor_id == USB_VENDOR_ID_TRUST) {
1068 switch (product_id) {
1069 case USB_UDIA_TRUST_PRODUCT_ID_013D:
1070 UDIA_INFO("Microdia PID 627B Compatible USB2.0 Webcam:\n Trust WB-3600R (145f:013d)\n");
1071 UDIA_INFO("This device is not supported yet. Please contact microdia@googlegroups.com if you want to add support for this device\n");
1072 webcam_model = MICRODIA_627B;
1073 sensor_slave_address = 0x21;
1074 ret = -ENODEV;
1075 goto error;
1076 default:
1077 ret = -ENODEV;
1078 goto error;
1080 } else {
1081 ret = -ENODEV;
1082 goto error;
1085 // Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device
1086 dev = kzalloc(sizeof(struct usb_microdia), GFP_KERNEL);
1088 if (dev == NULL) {
1089 UDIA_ERROR("Out of memory !\n");
1090 ret = -ENOMEM;
1091 goto error;
1094 // Init mutexes, spinlock, etc.
1095 mutex_init(&dev->mutex);
1096 kref_init(&dev->vopen);
1098 // Save pointers
1099 dev->webcam_model = webcam_model;
1100 dev->webcam_type = webcam_type;
1101 if (webcam_model == MICRODIA_6260)
1102 dev->frame_size_divisor = MICRODIA_FRAME_SIZE_DIVISOR_6260;
1103 else
1104 dev->frame_size_divisor = MICRODIA_FRAME_SIZE_DIVISOR_DEFAULT;
1105 dev->initialize = initialize;
1106 dev->stop_stream = stop_stream;
1107 dev->start_stream = start_stream;
1108 dev->set_contrast = set_contrast;
1109 dev->set_brightness = set_brightness;
1110 dev->set_gamma = set_gamma;
1111 dev->set_exposure = set_exposure;
1112 if (flip_detect) {
1113 UDIA_INFO("Rotate detection enabled\n");
1114 dev->flip_detect = flip_detect_f;
1116 dev->set_hvflip = set_hvflip;
1117 dev->set_sharpness = set_sharpness;
1118 dev->set_auto_exposure = set_auto_exposure;
1119 dev->set_auto_whitebalance = set_auto_whitebalance;
1120 dev->udev = udev;
1121 dev->interface = interface;
1122 dev->sensor_slave_address = sensor_slave_address;
1123 dev->sensor_flags = sensor_flags;
1124 dev->supported_fmts = supported_fmts;
1126 // Read the product release
1127 dev->release = le16_to_cpu(udev->descriptor.bcdDevice);
1128 UDIA_INFO("Release: %04x\n", dev->release);
1130 // How many interfaces (1 or 3) ?
1131 bNumInterfaces = udev->config->desc.bNumInterfaces;
1132 UDIA_INFO("Number of interfaces : %d\n", bNumInterfaces);
1135 // Switch on the camera (to detect size of buffers)
1136 dev_microdia_camera_on(dev);
1139 // Set up the endpoint information
1140 // use only the first int-in and isoc-in endpoints
1141 // for the current alternate setting
1142 iface_desc = interface->cur_altsetting;
1144 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1145 endpoint = &iface_desc->endpoint[i].desc;
1147 if (!dev->int_in_endpointAddr
1148 && ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
1149 && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
1150 // we found an interrupt in endpoint
1151 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1153 dev->int_in_size = buffer_size;
1154 dev->int_in_endpointAddr = (endpoint->bEndpointAddress & 0xf);
1157 if (!dev->isoc_in_endpointAddr
1158 && ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
1159 && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)) {
1160 // we found an isoc in endpoint
1161 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1163 dev->isoc_in_size = buffer_size;
1164 dev->isoc_in_endpointAddr = (endpoint->bEndpointAddress & 0xf);
1168 if (!(dev->int_in_endpointAddr && dev->isoc_in_endpointAddr)) {
1169 UDIA_ERROR("Could not find both int-in and isoc-in endpoints");
1170 ret = -ENODEV;
1171 goto free_dev;
1174 usb_microdia_default_settings(dev);
1176 dev_microdia_camera_off(dev);
1178 // Initialize the video device
1179 dev->vdev = video_device_alloc();
1181 if (!dev->vdev) {
1182 ret = -ENOMEM;
1183 goto free_dev;
1186 // Initialize the camera
1187 dev_microdia_initialize_device(dev);
1189 // Register the video device
1190 ret = v4l_microdia_register_video_device(dev);
1192 if (ret) {
1193 goto free_dev;
1196 // Create the entries in the sys filesystem
1197 microdia_create_sysfs_files(dev->vdev);
1199 // Save our data pointer in this interface device
1200 usb_set_intfdata(interface, dev);
1202 return 0;
1204 free_dev:
1205 kref_put(&dev->vopen, usb_microdia_delete);
1206 error:
1207 return ret;
1210 void usb_microdia_delete(struct kref *kref)
1212 struct usb_microdia *dev;
1213 dev = container_of(kref, struct usb_microdia, vopen);
1215 if (dev->vdev != NULL) {
1216 microdia_remove_sysfs_files(dev->vdev);
1217 v4l_microdia_unregister_video_device(dev);
1219 kfree(dev);
1222 /**
1223 * @param interface
1225 * @brief This function is called when the device is disconnected
1226 * or when the kernel module is unloaded.
1228 static void usb_microdia_disconnect(struct usb_interface *interface)
1230 struct usb_microdia *dev = usb_get_intfdata(interface);
1232 UDIA_INFO("Microdia USB2.0 Camera disconnected\n");
1234 usb_set_intfdata(interface, NULL);
1236 mutex_lock(&open_lock);
1237 kref_put(&dev->vopen, usb_microdia_delete);
1238 mutex_unlock(&open_lock);
1243 * @var usb_microdia_driver
1245 * This variable contains some callback
1247 static struct usb_driver usb_microdia_driver = {
1248 .name = "usb_microdia_driver",
1249 .probe = usb_microdia_probe,
1250 .disconnect = usb_microdia_disconnect,
1251 .id_table = microdia_table,
1254 module_param(fps, int, 0444); /**< @brief Module parameter frames per second */
1255 module_param(hflip, int, 0444); /**< @brief Module parameter horizontal flip process */
1256 module_param(vflip, int, 0444); /**< @brief Module parameter vertical flip process */
1257 module_param(flip_detect, int, 0444); /**< @brief Module parameter flip detect */
1258 module_param(auto_exposure, int, 0444); /**< @brief Module parameter automatic exposure control */
1259 module_param(auto_whitebalance, int, 0444); /**< @brief Module parameter automatic whitebalance control */
1260 module_param(brightness, int, 0444); /**< @brief Module parameter brightness */
1261 module_param(whiteness, int, 0444); /**< @brief Module parameter whiteness */
1262 module_param(contrast, int, 0444); /**< @brief Module parameter contrast */
1263 module_param(exposure, int, 0444); /**< @brief Module parameter exposure */
1264 module_param(sharpness, int, 0444); /**< @brief Module parameter sharpness */
1266 module_param(min_buffers, int, 0444);
1267 module_param(max_buffers, int, 0444);
1270 /**
1271 * @returns 0 if all is OK
1273 * @brief Initialize the driver.
1275 * This function is called at first.
1276 * This function permits to define the default values from the command line.
1278 static int __init usb_microdia_init(void)
1280 int result;
1282 UDIA_INFO("Microdia USB2.0 webcam driver startup\n");
1284 debug_dir = debugfs_create_dir(debug_dir_name, NULL);
1285 if(debug_dir)
1286 debug_file = debugfs_create_u8(debug_file_name, S_IRUGO | S_IWUGO,
1287 debug_dir, &debug_level);
1289 if(fps < 10 || fps > 30) {
1290 UDIA_WARNING("Framerate out of bounds [10-30]! Defaulting to 25\n");
1291 fps = 25;
1294 if(vflip != 0 && vflip != 1) {
1295 UDIA_WARNING("Vertical flip should be 0 or 1! Defaulting to 0\n");
1296 vflip = 0;
1299 if(hflip != 0 && hflip != 1) {
1300 UDIA_WARNING("Horizontal flip should be 0 or 1! Defaulting to 0\n");
1301 hflip = 0;
1304 if (sharpness < 0 || sharpness > 0x3f) {
1305 UDIA_WARNING("Sharpness should be 0 to 63 ! Defaulting to 31\n");
1306 sharpness = 0x1f;
1309 if(auto_exposure != 0 && auto_exposure != 1) {
1310 UDIA_WARNING("Automatic exposure should be 0 or 1! "
1311 "Defaulting to 1\n");
1312 auto_exposure = 1;
1315 if(auto_whitebalance != 0 && auto_whitebalance != 1) {
1316 UDIA_WARNING("Automatic whitebalance should be 0 or 1! "
1317 "Defaulting to 1\n");
1318 auto_whitebalance = 1;
1321 if (min_buffers < 2) {
1322 UDIA_WARNING("Minimum buffers can't be less then 2! "
1323 "Defaulting to 2\n");
1324 min_buffers = 2;
1328 if (min_buffers > max_buffers) {
1329 UDIA_WARNING("Minimum buffers must be less then or equal to "
1330 "max buffers! Defaulting to 2, 10\n");
1331 min_buffers = 2;
1332 max_buffers = 5;
1335 // Register the driver with the USB subsystem
1336 result = usb_register(&usb_microdia_driver);
1338 if (result)
1339 UDIA_ERROR("usb_register failed ! Error number %d\n", result);
1341 UDIA_INFO(DRIVER_VERSION " : " DRIVER_DESC "\n");
1343 return result;
1347 /**
1348 * @brief Close the driver
1350 * This function is called at last when you unload the driver.
1352 static void __exit usb_microdia_exit(void)
1354 UDIA_INFO("usb_microdia_exit: Microdia USB2.0 webcam driver shutdown\n");
1356 if(debug_file)
1357 debugfs_remove(debug_file);
1358 if(debug_dir)
1359 debugfs_remove(debug_dir);
1361 // Deregister this driver with the USB subsystem
1362 usb_deregister(&usb_microdia_driver);
1366 module_init(usb_microdia_init); /**< @brief Module initialize */
1367 module_exit(usb_microdia_exit); /**< @brief Module exit */
1370 MODULE_PARM_DESC(fps, "Frames per second [10-30]"); /**< @brief Description of 'fps' parameter */
1371 MODULE_PARM_DESC(hflip, "Horizontal image flip"); /**< @brief Description of 'hflip' parameter */
1372 MODULE_PARM_DESC(vflip, "Vertical image flip"); /**< @brief Description of 'vflip' parameter */
1373 MODULE_PARM_DESC(flip_detect, "Image flip detection"); /**< @brief Description of 'vflip_detect' parameter */
1374 MODULE_PARM_DESC(auto_exposure, "Automatic exposure control"); /**< @brief Description of 'auto_exposure' parameter */
1375 MODULE_PARM_DESC(auto_whitebalance, "Automatic whitebalance"); /**< @brief Description of 'auto_whitebalance' parameter */
1376 MODULE_PARM_DESC(brightness, "Brightness setting"); /**< @brief Description of 'brightness' parameter */
1377 MODULE_PARM_DESC(whiteness, "Whiteness setting"); /**< @brief Description of 'whiteness' parameter */
1378 MODULE_PARM_DESC(exposure, "Exposure setting"); /**< @brief Description of 'exposure' parameter */
1379 MODULE_PARM_DESC(contrast, "Contrast setting"); /**< @brief Description of 'contrast' parameter */
1380 MODULE_PARM_DESC(sharpness, "Sharpness setting"); /**< @brief Description of 'sharpness' parameter */
1382 MODULE_PARM_DESC(min_buffers, "Minimum number of image buffers");
1383 MODULE_PARM_DESC(max_buffers, "Maximum number of image buffers");
1385 MODULE_LICENSE("GPL"); /**< @brief Driver is under licence GPL */
1386 MODULE_AUTHOR(DRIVER_AUTHOR); /**< @brief Driver is written by Nicolas VIVIEN */
1387 MODULE_DESCRIPTION(DRIVER_DESC); /**< @brief Define the description of the driver */
1388 MODULE_SUPPORTED_DEVICE(DRIVER_SUPPORT); /**< @brief List of supported device */