1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65#include <linux/module.h>
66#include <linux/delay.h>
67#include <linux/errno.h>
68#include <linux/fs.h>
69#include <linux/init.h>
70#include <linux/kernel.h>
71#include <linux/slab.h>
72#include <linux/mm.h>
73#include <linux/parport.h>
74#include <linux/sched.h>
75#include <linux/videodev.h>
76#include <media/v4l2-common.h>
77#include <linux/mutex.h>
78#include <asm/uaccess.h>
79
80#include "bw-qcam.h"
81
82static unsigned int maxpoll=250;
83static unsigned int yieldlines=4;
84static int video_nr = -1;
85
86module_param(maxpoll, int, 0);
87module_param(yieldlines, int, 0);
88module_param(video_nr, int, 0);
89
90static inline int read_lpstatus(struct qcam_device *q)
91{
92 return parport_read_status(q->pport);
93}
94
95static inline int read_lpdata(struct qcam_device *q)
96{
97 return parport_read_data(q->pport);
98}
99
100static inline void write_lpdata(struct qcam_device *q, int d)
101{
102 parport_write_data(q->pport, d);
103}
104
105static inline void write_lpcontrol(struct qcam_device *q, int d)
106{
107 if (d & 0x20) {
108
109 parport_data_reverse(q->pport);
110 } else {
111
112 parport_data_forward(q->pport);
113 }
114
115
116
117 d &= ~0x20;
118 parport_write_control(q->pport, d);
119}
120
121static int qc_waithand(struct qcam_device *q, int val);
122static int qc_command(struct qcam_device *q, int command);
123static int qc_readparam(struct qcam_device *q);
124static int qc_setscanmode(struct qcam_device *q);
125static int qc_readbytes(struct qcam_device *q, char buffer[]);
126
127static struct video_device qcam_template;
128
129static int qc_calibrate(struct qcam_device *q)
130{
131
132
133
134
135
136
137 int value;
138 int count = 0;
139
140 qc_command(q, 27);
141 qc_command(q, 0);
142
143
144
145
146
147 do {
148 qc_command(q, 33);
149 value = qc_readparam(q);
150 mdelay(1);
151 schedule();
152 count++;
153 } while (value == 0xff && count<2048);
154
155 q->whitebal = value;
156 return value;
157}
158
159
160
161
162static struct qcam_device *qcam_init(struct parport *port)
163{
164 struct qcam_device *q;
165
166 q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
167 if(q==NULL)
168 return NULL;
169
170 q->pport = port;
171 q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
172 NULL, 0, NULL);
173 if (q->pdev == NULL)
174 {
175 printk(KERN_ERR "bw-qcam: couldn't register for %s.\n",
176 port->name);
177 kfree(q);
178 return NULL;
179 }
180
181 memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
182
183 mutex_init(&q->lock);
184
185 q->port_mode = (QC_ANY | QC_NOTSET);
186 q->width = 320;
187 q->height = 240;
188 q->bpp = 4;
189 q->transfer_scale = 2;
190 q->contrast = 192;
191 q->brightness = 180;
192 q->whitebal = 105;
193 q->top = 1;
194 q->left = 14;
195 q->mode = -1;
196 q->status = QC_PARAM_CHANGE;
197 return q;
198}
199
200
201
202
203
204
205
206static int qc_command(struct qcam_device *q, int command)
207{
208 int n1, n2;
209 int cmd;
210
211 write_lpdata(q, command);
212 write_lpcontrol(q, 6);
213
214 n1 = qc_waithand(q, 1);
215
216 write_lpcontrol(q, 0xe);
217 n2 = qc_waithand(q, 0);
218
219 cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
220 return cmd;
221}
222
223static int qc_readparam(struct qcam_device *q)
224{
225 int n1, n2;
226 int cmd;
227
228 write_lpcontrol(q, 6);
229 n1 = qc_waithand(q, 1);
230
231 write_lpcontrol(q, 0xe);
232 n2 = qc_waithand(q, 0);
233
234 cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
235 return cmd;
236}
237
238
239
240
241static int qc_waithand(struct qcam_device *q, int val)
242{
243 int status;
244 int runs=0;
245
246 if (val)
247 {
248 while (!((status = read_lpstatus(q)) & 8))
249 {
250
251
252
253
254
255
256
257 if(runs++>maxpoll)
258 {
259 msleep_interruptible(5);
260 }
261 if(runs>(maxpoll+1000))
262 return -1;
263 }
264 }
265 else
266 {
267 while (((status = read_lpstatus(q)) & 8))
268 {
269
270
271
272
273
274
275
276 if(runs++>maxpoll)
277 {
278 msleep_interruptible(5);
279 }
280 if(runs++>(maxpoll+1000))
281 return -1;
282 }
283 }
284
285 return status;
286}
287
288
289
290
291
292
293static unsigned int qc_waithand2(struct qcam_device *q, int val)
294{
295 unsigned int status;
296 int runs=0;
297
298 do
299 {
300 status = read_lpdata(q);
301
302
303
304
305
306
307
308 if(runs++>maxpoll)
309 {
310 msleep_interruptible(5);
311 }
312 if(runs++>(maxpoll+1000))
313 return 0;
314 }
315 while ((status & 1) != val);
316
317 return status;
318}
319
320
321
322
323
324
325
326
327
328static int qc_detect(struct qcam_device *q)
329{
330 int reg, lastreg;
331 int count = 0;
332 int i;
333
334 lastreg = reg = read_lpstatus(q) & 0xf0;
335
336 for (i = 0; i < 500; i++)
337 {
338 reg = read_lpstatus(q) & 0xf0;
339 if (reg != lastreg)
340 count++;
341 lastreg = reg;
342 mdelay(2);
343 }
344
345
346#if 0
347
348
349
350
351 printk("Debugging: QCam detection counter <30-200 counts as detected>: %d\n", count);
352 return 1;
353#endif
354
355
356
357
358 if (count > 20 && count < 400) {
359 return 1;
360 } else {
361 printk(KERN_ERR "No Quickcam found on port %s\n",
362 q->pport->name);
363 return 0;
364 }
365}
366
367
368
369
370
371
372
373static void qc_reset(struct qcam_device *q)
374{
375 switch (q->port_mode & QC_FORCE_MASK)
376 {
377 case QC_FORCE_UNIDIR:
378 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
379 break;
380
381 case QC_FORCE_BIDIR:
382 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
383 break;
384
385 case QC_ANY:
386 write_lpcontrol(q, 0x20);
387 write_lpdata(q, 0x75);
388
389 if (read_lpdata(q) != 0x75) {
390 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
391 } else {
392 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
393 }
394 break;
395 }
396
397 write_lpcontrol(q, 0xb);
398 udelay(250);
399 write_lpcontrol(q, 0xe);
400 qc_setscanmode(q);
401}
402
403
404
405
406
407
408
409
410
411
412
413static int qc_setscanmode(struct qcam_device *q)
414{
415 int old_mode = q->mode;
416
417 switch (q->transfer_scale)
418 {
419 case 1:
420 q->mode = 0;
421 break;
422 case 2:
423 q->mode = 4;
424 break;
425 case 4:
426 q->mode = 8;
427 break;
428 }
429
430 switch (q->bpp)
431 {
432 case 4:
433 break;
434 case 6:
435 q->mode += 2;
436 break;
437 }
438
439 switch (q->port_mode & QC_MODE_MASK)
440 {
441 case QC_BIDIR:
442 q->mode += 1;
443 break;
444 case QC_NOTSET:
445 case QC_UNIDIR:
446 break;
447 }
448
449 if (q->mode != old_mode)
450 q->status |= QC_PARAM_CHANGE;
451
452 return 0;
453}
454
455
456
457
458
459static void qc_set(struct qcam_device *q)
460{
461 int val;
462 int val2;
463
464 qc_reset(q);
465
466
467
468
469
470 qc_command(q, 0xb);
471 qc_command(q, q->brightness);
472
473 val = q->height / q->transfer_scale;
474 qc_command(q, 0x11);
475 qc_command(q, val);
476 if ((q->port_mode & QC_MODE_MASK) == QC_UNIDIR && q->bpp == 6) {
477
478
479
480
481
482 val = q->width;
483 val2 = q->transfer_scale * 4;
484 } else {
485 val = q->width * q->bpp;
486 val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
487 q->transfer_scale;
488 }
489 val = (val + val2 - 1) / val2;
490 qc_command(q, 0x13);
491 qc_command(q, val);
492
493
494 qc_command(q, 0xd);
495 qc_command(q, q->top);
496 qc_command(q, 0xf);
497 qc_command(q, q->left / 2);
498
499 qc_command(q, 0x19);
500 qc_command(q, q->contrast);
501 qc_command(q, 0x1f);
502 qc_command(q, q->whitebal);
503
504
505
506 q->status &= (~QC_PARAM_CHANGE);
507}
508
509
510
511
512
513static inline int qc_readbytes(struct qcam_device *q, char buffer[])
514{
515 int ret=1;
516 unsigned int hi, lo;
517 unsigned int hi2, lo2;
518 static int state = 0;
519
520 if (buffer == NULL)
521 {
522 state = 0;
523 return 0;
524 }
525
526 switch (q->port_mode & QC_MODE_MASK)
527 {
528 case QC_BIDIR:
529 write_lpcontrol(q, 0x26);
530 lo = (qc_waithand2(q, 1) >> 1);
531 hi = (read_lpstatus(q) >> 3) & 0x1f;
532 write_lpcontrol(q, 0x2e);
533 lo2 = (qc_waithand2(q, 0) >> 1);
534 hi2 = (read_lpstatus(q) >> 3) & 0x1f;
535 switch (q->bpp)
536 {
537 case 4:
538 buffer[0] = lo & 0xf;
539 buffer[1] = ((lo & 0x70) >> 4) | ((hi & 1) << 3);
540 buffer[2] = (hi & 0x1e) >> 1;
541 buffer[3] = lo2 & 0xf;
542 buffer[4] = ((lo2 & 0x70) >> 4) | ((hi2 & 1) << 3);
543 buffer[5] = (hi2 & 0x1e) >> 1;
544 ret = 6;
545 break;
546 case 6:
547 buffer[0] = lo & 0x3f;
548 buffer[1] = ((lo & 0x40) >> 6) | (hi << 1);
549 buffer[2] = lo2 & 0x3f;
550 buffer[3] = ((lo2 & 0x40) >> 6) | (hi2 << 1);
551 ret = 4;
552 break;
553 }
554 break;
555
556 case QC_UNIDIR:
557 write_lpcontrol(q, 6);
558 lo = (qc_waithand(q, 1) & 0xf0) >> 4;
559 write_lpcontrol(q, 0xe);
560 hi = (qc_waithand(q, 0) & 0xf0) >> 4;
561
562 switch (q->bpp)
563 {
564 case 4:
565 buffer[0] = lo;
566 buffer[1] = hi;
567 ret = 2;
568 break;
569 case 6:
570 switch (state)
571 {
572 case 0:
573 buffer[0] = (lo << 2) | ((hi & 0xc) >> 2);
574 q->saved_bits = (hi & 3) << 4;
575 state = 1;
576 ret = 1;
577 break;
578 case 1:
579 buffer[0] = lo | q->saved_bits;
580 q->saved_bits = hi << 2;
581 state = 2;
582 ret = 1;
583 break;
584 case 2:
585 buffer[0] = ((lo & 0xc) >> 2) | q->saved_bits;
586 buffer[1] = ((lo & 3) << 4) | hi;
587 state = 0;
588 ret = 2;
589 break;
590 }
591 break;
592 }
593 break;
594 }
595 return ret;
596}
597
598
599
600
601
602
603
604
605
606
607
608
609static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long len)
610{
611 int i, j, k, yield;
612 int bytes;
613 int linestotrans, transperline;
614 int divisor;
615 int pixels_per_line;
616 int pixels_read = 0;
617 int got=0;
618 char buffer[6];
619 int shift=8-q->bpp;
620 char invert;
621
622 if (q->mode == -1)
623 return -ENXIO;
624
625 qc_command(q, 0x7);
626 qc_command(q, q->mode);
627
628 if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR)
629 {
630 write_lpcontrol(q, 0x2e);
631 write_lpcontrol(q, 0x26);
632 (void) qc_waithand(q, 1);
633 write_lpcontrol(q, 0x2e);
634 (void) qc_waithand(q, 0);
635 }
636
637
638 invert = (q->bpp == 4) ? 16 : 63;
639
640 linestotrans = q->height / q->transfer_scale;
641 pixels_per_line = q->width / q->transfer_scale;
642 transperline = q->width * q->bpp;
643 divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
644 q->transfer_scale;
645 transperline = (transperline + divisor - 1) / divisor;
646
647 for (i = 0, yield = yieldlines; i < linestotrans; i++)
648 {
649 for (pixels_read = j = 0; j < transperline; j++)
650 {
651 bytes = qc_readbytes(q, buffer);
652 for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++)
653 {
654 int o;
655 if (buffer[k] == 0 && invert == 16)
656 {
657
658
659 buffer[k] = 16;
660 }
661 o=i*pixels_per_line + pixels_read + k;
662 if(o<len)
663 {
664 got++;
665 put_user((invert - buffer[k])<<shift, buf+o);
666 }
667 }
668 pixels_read += bytes;
669 }
670 (void) qc_readbytes(q, NULL);
671
672
673
674
675
676
677
678 if (i >= yield) {
679 msleep_interruptible(5);
680 yield = i + yieldlines;
681 }
682 }
683
684 if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR)
685 {
686 write_lpcontrol(q, 2);
687 write_lpcontrol(q, 6);
688 udelay(3);
689 write_lpcontrol(q, 0xe);
690 }
691 if(got<len)
692 return got;
693 return len;
694}
695
696
697
698
699
700static int qcam_do_ioctl(struct inode *inode, struct file *file,
701 unsigned int cmd, void *arg)
702{
703 struct video_device *dev = video_devdata(file);
704 struct qcam_device *qcam=(struct qcam_device *)dev;
705
706 switch(cmd)
707 {
708 case VIDIOCGCAP:
709 {
710 struct video_capability *b = arg;
711 strcpy(b->name, "Quickcam");
712 b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES|VID_TYPE_MONOCHROME;
713 b->channels = 1;
714 b->audios = 0;
715 b->maxwidth = 320;
716 b->maxheight = 240;
717 b->minwidth = 80;
718 b->minheight = 60;
719 return 0;
720 }
721 case VIDIOCGCHAN:
722 {
723 struct video_channel *v = arg;
724 if(v->channel!=0)
725 return -EINVAL;
726 v->flags=0;
727 v->tuners=0;
728
729 v->type = VIDEO_TYPE_CAMERA;
730 strcpy(v->name, "Camera");
731 return 0;
732 }
733 case VIDIOCSCHAN:
734 {
735 struct video_channel *v = arg;
736 if(v->channel!=0)
737 return -EINVAL;
738 return 0;
739 }
740 case VIDIOCGTUNER:
741 {
742 struct video_tuner *v = arg;
743 if(v->tuner)
744 return -EINVAL;
745 strcpy(v->name, "Format");
746 v->rangelow=0;
747 v->rangehigh=0;
748 v->flags= 0;
749 v->mode = VIDEO_MODE_AUTO;
750 return 0;
751 }
752 case VIDIOCSTUNER:
753 {
754 struct video_tuner *v = arg;
755 if(v->tuner)
756 return -EINVAL;
757 if(v->mode!=VIDEO_MODE_AUTO)
758 return -EINVAL;
759 return 0;
760 }
761 case VIDIOCGPICT:
762 {
763 struct video_picture *p = arg;
764 p->colour=0x8000;
765 p->hue=0x8000;
766 p->brightness=qcam->brightness<<8;
767 p->contrast=qcam->contrast<<8;
768 p->whiteness=qcam->whitebal<<8;
769 p->depth=qcam->bpp;
770 p->palette=VIDEO_PALETTE_GREY;
771 return 0;
772 }
773 case VIDIOCSPICT:
774 {
775 struct video_picture *p = arg;
776 if(p->palette!=VIDEO_PALETTE_GREY)
777 return -EINVAL;
778 if(p->depth!=4 && p->depth!=6)
779 return -EINVAL;
780
781
782
783
784
785 qcam->brightness = p->brightness>>8;
786 qcam->contrast = p->contrast>>8;
787 qcam->whitebal = p->whiteness>>8;
788 qcam->bpp = p->depth;
789
790 mutex_lock(&qcam->lock);
791 qc_setscanmode(qcam);
792 mutex_unlock(&qcam->lock);
793 qcam->status |= QC_PARAM_CHANGE;
794
795 return 0;
796 }
797 case VIDIOCSWIN:
798 {
799 struct video_window *vw = arg;
800 if(vw->flags)
801 return -EINVAL;
802 if(vw->clipcount)
803 return -EINVAL;
804 if(vw->height<60||vw->height>240)
805 return -EINVAL;
806 if(vw->width<80||vw->width>320)
807 return -EINVAL;
808
809 qcam->width = 320;
810 qcam->height = 240;
811 qcam->transfer_scale = 4;
812
813 if(vw->width>=160 && vw->height>=120)
814 {
815 qcam->transfer_scale = 2;
816 }
817 if(vw->width>=320 && vw->height>=240)
818 {
819 qcam->width = 320;
820 qcam->height = 240;
821 qcam->transfer_scale = 1;
822 }
823 mutex_lock(&qcam->lock);
824 qc_setscanmode(qcam);
825 mutex_unlock(&qcam->lock);
826
827
828
829 qcam->status |= QC_PARAM_CHANGE;
830
831
832 return 0;
833 }
834 case VIDIOCGWIN:
835 {
836 struct video_window *vw = arg;
837 memset(vw, 0, sizeof(*vw));
838 vw->width=qcam->width/qcam->transfer_scale;
839 vw->height=qcam->height/qcam->transfer_scale;
840 return 0;
841 }
842 case VIDIOCKEY:
843 return 0;
844 case VIDIOCCAPTURE:
845 case VIDIOCGFBUF:
846 case VIDIOCSFBUF:
847 case VIDIOCGFREQ:
848 case VIDIOCSFREQ:
849 case VIDIOCGAUDIO:
850 case VIDIOCSAUDIO:
851 return -EINVAL;
852 default:
853 return -ENOIOCTLCMD;
854 }
855 return 0;
856}
857
858static int qcam_ioctl(struct inode *inode, struct file *file,
859 unsigned int cmd, unsigned long arg)
860{
861 return video_usercopy(inode, file, cmd, arg, qcam_do_ioctl);
862}
863
864static ssize_t qcam_read(struct file *file, char __user *buf,
865 size_t count, loff_t *ppos)
866{
867 struct video_device *v = video_devdata(file);
868 struct qcam_device *qcam=(struct qcam_device *)v;
869 int len;
870 parport_claim_or_block(qcam->pdev);
871
872 mutex_lock(&qcam->lock);
873
874 qc_reset(qcam);
875
876
877 if (qcam->status & QC_PARAM_CHANGE)
878 qc_set(qcam);
879
880 len=qc_capture(qcam, buf,count);
881
882 mutex_unlock(&qcam->lock);
883
884 parport_release(qcam->pdev);
885 return len;
886}
887
888static const struct file_operations qcam_fops = {
889 .owner = THIS_MODULE,
890 .open = video_exclusive_open,
891 .release = video_exclusive_release,
892 .ioctl = qcam_ioctl,
893 .compat_ioctl = v4l_compat_ioctl32,
894 .read = qcam_read,
895 .llseek = no_llseek,
896};
897static struct video_device qcam_template=
898{
899 .owner = THIS_MODULE,
900 .name = "Connectix Quickcam",
901 .type = VID_TYPE_CAPTURE,
902 .fops = &qcam_fops,
903};
904
905#define MAX_CAMS 4
906static struct qcam_device *qcams[MAX_CAMS];
907static unsigned int num_cams = 0;
908
909static int init_bwqcam(struct parport *port)
910{
911 struct qcam_device *qcam;
912
913 if (num_cams == MAX_CAMS)
914 {
915 printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS);
916 return -ENOSPC;
917 }
918
919 qcam=qcam_init(port);
920 if(qcam==NULL)
921 return -ENODEV;
922
923 parport_claim_or_block(qcam->pdev);
924
925 qc_reset(qcam);
926
927 if(qc_detect(qcam)==0)
928 {
929 parport_release(qcam->pdev);
930 parport_unregister_device(qcam->pdev);
931 kfree(qcam);
932 return -ENODEV;
933 }
934 qc_calibrate(qcam);
935
936 parport_release(qcam->pdev);
937
938 printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name);
939
940 if(video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
941 {
942 parport_unregister_device(qcam->pdev);
943 kfree(qcam);
944 return -ENODEV;
945 }
946
947 qcams[num_cams++] = qcam;
948
949 return 0;
950}
951
952static void close_bwqcam(struct qcam_device *qcam)
953{
954 video_unregister_device(&qcam->vdev);
955 parport_unregister_device(qcam->pdev);
956 kfree(qcam);
957}
958
959
960
961
962#ifdef MODULE
963static char *parport[MAX_CAMS] = { NULL, };
964module_param_array(parport, charp, NULL, 0);
965#endif
966
967static int accept_bwqcam(struct parport *port)
968{
969#ifdef MODULE
970 int n;
971
972 if (parport[0] && strncmp(parport[0], "auto", 4) != 0) {
973
974 for(n=0; parport[n] && n<MAX_CAMS; n++){
975 char *ep;
976 unsigned long r;
977 r = simple_strtoul(parport[n], &ep, 0);
978 if (ep == parport[n]) {
979 printk(KERN_ERR
980 "bw-qcam: bad port specifier \"%s\"\n",
981 parport[n]);
982 continue;
983 }
984 if (r == port->number)
985 return 1;
986 }
987 return 0;
988 }
989#endif
990 return 1;
991}
992
993static void bwqcam_attach(struct parport *port)
994{
995 if (accept_bwqcam(port))
996 init_bwqcam(port);
997}
998
999static void bwqcam_detach(struct parport *port)
1000{
1001 int i;
1002 for (i = 0; i < num_cams; i++) {
1003 struct qcam_device *qcam = qcams[i];
1004 if (qcam && qcam->pdev->port == port) {
1005 qcams[i] = NULL;
1006 close_bwqcam(qcam);
1007 }
1008 }
1009}
1010
1011static struct parport_driver bwqcam_driver = {
1012 .name = "bw-qcam",
1013 .attach = bwqcam_attach,
1014 .detach = bwqcam_detach,
1015};
1016
1017static void __exit exit_bw_qcams(void)
1018{
1019 parport_unregister_driver(&bwqcam_driver);
1020}
1021
1022static int __init init_bw_qcams(void)
1023{
1024#ifdef MODULE
1025
1026 if (maxpoll > 5000) {
1027 printk("Connectix Quickcam max-poll was above 5000. Using 5000.\n");
1028 maxpoll = 5000;
1029 }
1030
1031 if (yieldlines < 1) {
1032 printk("Connectix Quickcam yieldlines was less than 1. Using 1.\n");
1033 yieldlines = 1;
1034 }
1035#endif
1036 return parport_register_driver(&bwqcam_driver);
1037}
1038
1039module_init(init_bw_qcams);
1040module_exit(exit_bw_qcams);
1041
1042MODULE_LICENSE("GPL");
1043