OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [usb/] [se401.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Endpoints (formerly known as AOX) se401 USB Camera Driver
3
 *
4
 * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
5
 *
6
 * Still somewhat based on the Linux ov511 driver.
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms of the GNU General Public License as published by the
10
 * Free Software Foundation; either version 2 of the License, or (at your
11
 * option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16
 * for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software Foundation,
20
 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
 *
22
 *
23
 * Thanks to Endpoints Inc. (www.endpoints.com) for making documentation on
24
 * their chipset available and supporting me while writing this driver.
25
 *      - Jeroen Vreeken
26
 */
27
 
28
static const char version[] = "0.23";
29
 
30
#include <linux/config.h>
31
#include <linux/module.h>
32
#include <linux/version.h>
33
#include <linux/init.h>
34
#include <linux/fs.h>
35
#include <linux/vmalloc.h>
36
#include <linux/slab.h>
37
#include <linux/proc_fs.h>
38
#include <linux/pagemap.h>
39
#include <linux/usb.h>
40
#include <asm/io.h>
41
#include <asm/semaphore.h>
42
#include <linux/wrapper.h>
43
 
44
#include "se401.h"
45
 
46
static int flickerless=0;
47
static int video_nr = -1;
48
 
49
static struct usb_device_id device_table [] = {
50
        { USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */
51
        { USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */
52
        { USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */
53
        { USB_DEVICE(0x047d, 0x5002) },/* Kensington 6701(5/7) */
54
        { USB_DEVICE(0x047d, 0x5003) },/* Kensington 67016 */
55
        { }
56
};
57
 
58
MODULE_DEVICE_TABLE(usb, device_table);
59
 
60
MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
61
MODULE_DESCRIPTION("SE401 USB Camera Driver");
62
MODULE_LICENSE("GPL");
63
MODULE_PARM(flickerless, "i");
64
MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)");
65
MODULE_PARM(video_nr, "i");
66
EXPORT_NO_SYMBOLS;
67
 
68
 
69
static struct usb_driver se401_driver;
70
 
71
 
72
/**********************************************************************
73
 *
74
 * Memory management
75
 *
76
 **********************************************************************/
77
 
78
/* Here we want the physical address of the memory.
79
 * This is used when initializing the contents of the area.
80
 */
81
static inline unsigned long kvirt_to_pa(unsigned long adr)
82
{
83
        unsigned long kva, ret;
84
 
85
        kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
86
        kva |= adr & (PAGE_SIZE-1); /* restore the offset */
87
        ret = __pa(kva);
88
        return ret;
89
}
90
 
91
static void *rvmalloc(unsigned long size)
92
{
93
        void *mem;
94
        unsigned long adr;
95
 
96
        size = PAGE_ALIGN(size);
97
        mem = vmalloc_32(size);
98
        if (!mem)
99
                return NULL;
100
 
101
        memset(mem, 0, size); /* Clear the ram out, no junk to the user */
102
        adr = (unsigned long) mem;
103
        while (size > 0) {
104
                mem_map_reserve(vmalloc_to_page((void *)adr));
105
                adr += PAGE_SIZE;
106
                size -= PAGE_SIZE;
107
        }
108
 
109
        return mem;
110
}
111
 
112
static void rvfree(void *mem, unsigned long size)
113
{
114
        unsigned long adr;
115
 
116
        if (!mem)
117
                return;
118
 
119
        adr = (unsigned long) mem;
120
        while ((long) size > 0) {
121
                mem_map_unreserve(vmalloc_to_page((void *)adr));
122
                adr += PAGE_SIZE;
123
                size -= PAGE_SIZE;
124
        }
125
        vfree(mem);
126
}
127
 
128
 
129
 
130
/****************************************************************************
131
 *
132
 * /proc interface
133
 *
134
 ***************************************************************************/
135
 
136
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
137
 
138
static struct proc_dir_entry *se401_proc_entry = NULL;
139
extern struct proc_dir_entry *video_proc_entry;
140
 
141
#define YES_NO(x) ((x) ? "yes" : "no")
142
 
143
static int se401_read_proc(char *page, char **start, off_t off, int count,
144
                           int *eof, void *data)
145
{
146
        char *out = page;
147
        int i, len;
148
        struct usb_se401 *se401 = data;
149
 
150
        /* Stay under PAGE_SIZE or else bla bla bla.... */
151
 
152
        out+=sprintf(out, "driver_version  : %s\n", version);
153
        out+=sprintf(out, "model           : %s\n", se401->camera_name);
154
        out+=sprintf(out, "in use          : %s\n", YES_NO (se401->user));
155
        out+=sprintf(out, "streaming       : %s\n", YES_NO (se401->streaming));
156
        out+=sprintf(out, "button state    : %s\n", YES_NO (se401->button));
157
        out+=sprintf(out, "button pressed  : %s\n", YES_NO (se401->buttonpressed));
158
        out+=sprintf(out, "num_frames      : %d\n", SE401_NUMFRAMES);
159
 
160
        out+=sprintf(out, "Sizes           :");
161
        for (i=0; i<se401->sizes; i++) {
162
                out+=sprintf(out, " %dx%d", se401->width[i],
163
                    se401->height[i]);
164
        }
165
        out+=sprintf(out, "\n");
166
 
167
        out+=sprintf(out, "Frames total    : %d\n", se401->readcount);
168
        out+=sprintf(out, "Frames read     : %d\n", se401->framecount);
169
        out+=sprintf(out, "Packets dropped : %d\n", se401->dropped);
170
        out+=sprintf(out, "Decoding Errors : %d\n", se401->error);
171
 
172
        len = out - page;
173
        len -= off;
174
        if (len < count) {
175
                *eof = 1;
176
                        if (len <= 0) return 0;
177
        } else
178
                len = count;
179
 
180
        *start = page + off;
181
 
182
        return len;
183
}
184
 
185
static int se401_write_proc(struct file *file, const char *buffer,
186
                            unsigned long count, void *data)
187
{
188
        return -EINVAL;
189
}
190
 
191
static void create_proc_se401_cam (struct usb_se401 *se401)
192
{
193
        char name[7];
194
        struct proc_dir_entry *ent;
195
 
196
        if (!se401_proc_entry || !se401)
197
                return;
198
 
199
        sprintf (name, "video%d", se401->vdev.minor);
200
 
201
        ent = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
202
                                se401_proc_entry);
203
 
204
        if (!ent)
205
                return;
206
 
207
        ent->data = se401;
208
        ent->read_proc = se401_read_proc;
209
        ent->write_proc = se401_write_proc;
210
        se401->proc_entry = ent;
211
}
212
 
213
static void destroy_proc_se401_cam (struct usb_se401 *se401)
214
{
215
        /* One to much, just to be sure :) */
216
        char name[9];
217
 
218
        if (!se401 || !se401->proc_entry)
219
                return;
220
 
221
        sprintf(name, "video%d", se401->vdev.minor);
222
        remove_proc_entry(name, se401_proc_entry);
223
        se401->proc_entry = NULL;
224
}
225
 
226
static void proc_se401_create (void)
227
{
228
        if (video_proc_entry == NULL) {
229
                err("/proc/video/ doesn't exist");
230
                return;
231
        }
232
 
233
        se401_proc_entry=create_proc_entry("se401", S_IFDIR, video_proc_entry);
234
 
235
        if (se401_proc_entry)
236
                se401_proc_entry->owner = THIS_MODULE;
237
        else
238
                err("Unable to initialize /proc/video/se401");
239
}
240
 
241
static void proc_se401_destroy(void)
242
{
243
        if (se401_proc_entry == NULL)
244
                return;
245
 
246
        remove_proc_entry("se401", video_proc_entry);
247
}
248
#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
249
 
250
 
251
/****************************************************************************
252
 *
253
 * se401 register read/write functions
254
 *
255
 ***************************************************************************/
256
 
257
static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req,
258
                         unsigned short value, unsigned char *cp, int size)
259
{
260
        return usb_control_msg (
261
                se401->dev,
262
                set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0),
263
                req,
264
                (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
265
                value,
266
                0,
267
                cp,
268
                size,
269
                HZ
270
        );
271
}
272
 
273
static int se401_set_feature(struct usb_se401 *se401, unsigned short selector,
274
                             unsigned short param)
275
{
276
        /* specs say that the selector (address) should go in the value field
277
           and the param in index, but in the logs of the windows driver they do
278
           this the other way around...
279
         */
280
        return usb_control_msg (
281
                se401->dev,
282
                usb_sndctrlpipe(se401->dev, 0),
283
                SE401_REQ_SET_EXT_FEATURE,
284
                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
285
                param,
286
                selector,
287
                NULL,
288
                0,
289
                HZ
290
        );
291
}
292
 
293
static unsigned short se401_get_feature(struct usb_se401 *se401,
294
                                        unsigned short selector)
295
{
296
        /* For 'set' the selecetor should be in index, not sure if the spec is
297
           wrong here to....
298
         */
299
        unsigned char cp[2];
300
        usb_control_msg (
301
                se401->dev,
302
                usb_rcvctrlpipe(se401->dev, 0),
303
                SE401_REQ_GET_EXT_FEATURE,
304
                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
305
                0,
306
                selector,
307
                cp,
308
                2,
309
                HZ
310
        );
311
        return cp[0]+cp[1]*256;
312
}
313
 
314
/****************************************************************************
315
 *
316
 * Camera control
317
 *
318
 ***************************************************************************/
319
 
320
 
321
static int se401_send_pict(struct usb_se401 *se401)
322
{
323
        se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);/* integration time low */
324
        se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);/* integration time mid */
325
        se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);/* integration time mid */
326
        se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);/* reset level value */
327
        se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);/* red color gain */
328
        se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);/* green color gain */
329
        se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);/* blue color gain */
330
 
331
        return 0;
332
}
333
 
334
static void se401_set_exposure(struct usb_se401 *se401, int brightness)
335
{
336
        int integration=brightness<<5;
337
 
338
        if (flickerless==50) {
339
                integration=integration-integration%106667;
340
        }
341
        if (flickerless==60) {
342
                integration=integration-integration%88889;
343
        }
344
        se401->brightness=integration>>5;
345
        se401->expose_h=(integration>>16)&0xff;
346
        se401->expose_m=(integration>>8)&0xff;
347
        se401->expose_l=integration&0xff;
348
}
349
 
350
static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p)
351
{
352
        p->brightness=se401->brightness;
353
        if (se401->enhance) {
354
                p->whiteness=32768;
355
        } else {
356
                p->whiteness=0;
357
        }
358
        p->colour=65535;
359
        p->contrast=65535;
360
        p->hue=se401->rgain<<10;
361
        p->palette=se401->palette;
362
        p->depth=3; /* rgb24 */
363
        return 0;
364
}
365
 
366
 
367
static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p)
368
{
369
        if (p->palette != VIDEO_PALETTE_RGB24)
370
                return 1;
371
        se401->palette=p->palette;
372
        if (p->hue!=se401->hue) {
373
                se401->rgain= p->hue>>10;
374
                se401->bgain= 0x40-(p->hue>>10);
375
                se401->hue=p->hue;
376
        }
377
        if (p->brightness!=se401->brightness) {
378
                se401_set_exposure(se401, p->brightness);
379
        }
380
        if (p->whiteness>=32768) {
381
                se401->enhance=1;
382
        } else {
383
                se401->enhance=0;
384
        }
385
        se401_send_pict(se401);
386
        se401_send_pict(se401);
387
        return 0;
388
}
389
 
390
/*
391
        Hyundai have some really nice docs about this and other sensor related
392
        stuff on their homepage: www.hei.co.kr
393
*/
394
static void se401_auto_resetlevel(struct usb_se401 *se401)
395
{
396
        unsigned int ahrc, alrc;
397
        int oldreset=se401->resetlevel;
398
 
399
        /* For some reason this normally read-only register doesn't get reset
400
           to zero after reading them just once...
401
         */
402
        se401_get_feature(se401, HV7131_REG_HIREFNOH);
403
        se401_get_feature(se401, HV7131_REG_HIREFNOL);
404
        se401_get_feature(se401, HV7131_REG_LOREFNOH);
405
        se401_get_feature(se401, HV7131_REG_LOREFNOL);
406
        ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) +
407
            se401_get_feature(se401, HV7131_REG_HIREFNOL);
408
        alrc=256*se401_get_feature(se401, HV7131_REG_LOREFNOH) +
409
            se401_get_feature(se401, HV7131_REG_LOREFNOL);
410
 
411
        /* Not an exact science, but it seems to work pretty well... */
412
        if (alrc > 10) {
413
                while (alrc>=10 && se401->resetlevel < 63) {
414
                        se401->resetlevel++;
415
                        alrc /=2;
416
                }
417
        } else if (ahrc > 20) {
418
                while (ahrc>=20 && se401->resetlevel > 0) {
419
                        se401->resetlevel--;
420
                        ahrc /=2;
421
                }
422
        }
423
        if (se401->resetlevel!=oldreset)
424
                se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
425
 
426
        return;
427
}
428
 
429
/* irq handler for snapshot button */
430
static void se401_button_irq(struct urb *urb)
431
{
432
        struct usb_se401 *se401 = urb->context;
433
 
434
        if (!se401->dev) {
435
                info("ohoh: device vapourished");
436
                return;
437
        }
438
 
439
        if (urb->actual_length >=2 && !urb->status) {
440
                if (se401->button)
441
                        se401->buttonpressed=1;
442
        }
443
}
444
 
445
static void se401_video_irq(struct urb *urb)
446
{
447
        struct usb_se401 *se401 = urb->context;
448
        int length = urb->actual_length;
449
 
450
        /* ohoh... */
451
        if (!se401->streaming)
452
                return;
453
 
454
        if (!se401->dev) {
455
                info ("ohoh: device vapourished");
456
                return;
457
        }
458
 
459
        /* 0 sized packets happen if we are to fast, but sometimes the camera
460
           keeps sending them forever...
461
         */
462
        if (length && !urb->status) {
463
                se401->nullpackets=0;
464
                switch(se401->scratch[se401->scratch_next].state) {
465
                        case BUFFER_READY:
466
                        case BUFFER_BUSY: {
467
                                se401->dropped++;
468
                                break;
469
                        }
470
                        case BUFFER_UNUSED: {
471
                                memcpy(se401->scratch[se401->scratch_next].data, (unsigned char *)urb->transfer_buffer, length);
472
                                se401->scratch[se401->scratch_next].state=BUFFER_READY;
473
                                se401->scratch[se401->scratch_next].offset=se401->bayeroffset;
474
                                se401->scratch[se401->scratch_next].length=length;
475
                                if (waitqueue_active(&se401->wq)) {
476
                                        wake_up_interruptible(&se401->wq);
477
                                }
478
                                se401->scratch_overflow=0;
479
                                se401->scratch_next++;
480
                                if (se401->scratch_next>=SE401_NUMSCRATCH)
481
                                        se401->scratch_next=0;;
482
                                break;
483
                        }
484
                }
485
                se401->bayeroffset+=length;
486
                if (se401->bayeroffset>=se401->cheight*se401->cwidth) {
487
                        se401->bayeroffset=0;
488
                }
489
        } else {
490
                se401->nullpackets++;
491
                if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
492
                        if (waitqueue_active(&se401->wq)) {
493
                                wake_up_interruptible(&se401->wq);
494
                        }
495
                }
496
        }
497
 
498
        /* Resubmit urb for new data */
499
        urb->status=0;
500
        urb->dev=se401->dev;
501
        if(usb_submit_urb(urb))
502
                info("urb burned down");
503
        return;
504
}
505
 
506
static void se401_send_size(struct usb_se401 *se401, int width, int height)
507
{
508
        int i=0;
509
        int mode=0x03; /* No compression */
510
        int sendheight=height;
511
        int sendwidth=width;
512
 
513
        /* JangGu compression can only be used with the camera supported sizes,
514
           but bayer seems to work with any size that fits on the sensor.
515
           We check if we can use compression with the current size with either
516
           4 or 16 times subcapturing, if not we use uncompressed bayer data
517
           but this will result in cutouts of the maximum size....
518
         */
519
        while (i<se401->sizes && !(se401->width[i]==width && se401->height[i]==height))
520
                i++;
521
        while (i<se401->sizes) {
522
                if (se401->width[i]==width*2 && se401->height[i]==height*2) {
523
                        sendheight=se401->height[i];
524
                        sendwidth=se401->width[i];
525
                        mode=0x40;
526
                }
527
                if (se401->width[i]==width*4 && se401->height[i]==height*4) {
528
                        sendheight=se401->height[i];
529
                        sendwidth=se401->width[i];
530
                        mode=0x42;
531
                }
532
                i++;
533
        }
534
 
535
        se401_sndctrl(1, se401, SE401_REQ_SET_WIDTH, sendwidth, NULL, 0);
536
        se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0);
537
        se401_set_feature(se401, SE401_OPERATINGMODE, mode);
538
 
539
        if (mode==0x03) {
540
                se401->format=FMT_BAYER;
541
        } else {
542
                se401->format=FMT_JANGGU;
543
        }
544
 
545
        return;
546
}
547
 
548
/*
549
        In this function se401_send_pict is called several times,
550
        for some reason (depending on the state of the sensor and the phase of
551
        the moon :) doing this only in either place doesn't always work...
552
*/
553
static int se401_start_stream(struct usb_se401 *se401)
554
{
555
        struct urb *urb;
556
        int err=0, i;
557
        se401->streaming=1;
558
 
559
        se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
560
        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
561
 
562
        /* Set picture settings */
563
        se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */
564
        se401_send_pict(se401);
565
 
566
        se401_send_size(se401, se401->cwidth, se401->cheight);
567
 
568
        se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0);
569
 
570
        /* Do some memory allocation */
571
        for (i=0; i<SE401_NUMFRAMES; i++) {
572
                se401->frame[i].data=se401->fbuf + i * se401->maxframesize;
573
                se401->frame[i].curpix=0;
574
        }
575
        for (i=0; i<SE401_NUMSBUF; i++) {
576
                se401->sbuf[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
577
        }
578
 
579
        se401->bayeroffset=0;
580
        se401->scratch_next=0;
581
        se401->scratch_use=0;
582
        se401->scratch_overflow=0;
583
        for (i=0; i<SE401_NUMSCRATCH; i++) {
584
                se401->scratch[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
585
                se401->scratch[i].state=BUFFER_UNUSED;
586
        }
587
 
588
        for (i=0; i<SE401_NUMSBUF; i++) {
589
                urb=usb_alloc_urb(0);
590
                if(!urb)
591
                        return -ENOMEM;
592
 
593
                FILL_BULK_URB(urb, se401->dev,
594
                        usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT),
595
                        se401->sbuf[i].data, SE401_PACKETSIZE,
596
                        se401_video_irq,
597
                        se401);
598
                urb->transfer_flags |= USB_QUEUE_BULK;
599
 
600
                se401->urb[i]=urb;
601
 
602
                err=usb_submit_urb(se401->urb[i]);
603
                if(err)
604
                        err("urb burned down");
605
        }
606
 
607
        se401->framecount=0;
608
 
609
        return 0;
610
}
611
 
612
static int se401_stop_stream(struct usb_se401 *se401)
613
{
614
        int i;
615
 
616
        if (!se401->streaming || !se401->dev)
617
                return 1;
618
 
619
        se401->streaming=0;
620
 
621
        se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0);
622
 
623
        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
624
        se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
625
 
626
        for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
627
                se401->urb[i]->next=NULL;
628
                usb_unlink_urb(se401->urb[i]);
629
                usb_free_urb(se401->urb[i]);
630
                se401->urb[i]=NULL;
631
                kfree(se401->sbuf[i].data);
632
        }
633
        for (i=0; i<SE401_NUMSCRATCH; i++) {
634
                kfree(se401->scratch[i].data);
635
                se401->scratch[i].data=NULL;
636
        }
637
 
638
        return 0;
639
}
640
 
641
static int se401_set_size(struct usb_se401 *se401, int width, int height)
642
{
643
        int wasstreaming=se401->streaming;
644
        /* Check to see if we need to change */
645
        if (se401->cwidth==width && se401->cheight==height)
646
                return 0;
647
 
648
        /* Check for a valid mode */
649
        if (width <= 0 || height <= 0)
650
                return 1;
651
        if ((width & 1) || (height & 1))
652
                return 1;
653
        if (width>se401->width[se401->sizes-1])
654
                return 1;
655
        if (height>se401->height[se401->sizes-1])
656
                return 1;
657
 
658
        /* Stop a current stream and start it again at the new size */
659
        if (wasstreaming)
660
                se401_stop_stream(se401);
661
        se401->cwidth=width;
662
        se401->cheight=height;
663
        if (wasstreaming)
664
                se401_start_stream(se401);
665
        return 0;
666
}
667
 
668
 
669
/****************************************************************************
670
 *
671
 * Video Decoding
672
 *
673
 ***************************************************************************/
674
 
675
/*
676
        This shouldn't really be done in a v4l driver....
677
        But it does make the image look a lot more usable.
678
        Basicly it lifts the dark pixels more than the light pixels.
679
*/
680
static inline void enhance_picture(unsigned char *frame, int len)
681
{
682
        while (len--) {
683
                *frame=(((*frame^255)*(*frame^255))/255)^255;
684
                frame++;
685
        }
686
}
687
 
688
static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data)
689
{
690
        struct se401_frame *frame=&se401->frame[se401->curframe];
691
        int linelength=se401->cwidth*3;
692
 
693
        if (frame->curlinepix >= linelength) {
694
                frame->curlinepix=0;
695
                frame->curline+=linelength;
696
        }
697
 
698
        /* First three are absolute, all others relative.
699
         * Format is rgb from right to left (mirrorred image),
700
         * we flip it to get bgr from left to right. */
701
        if (frame->curlinepix < 3) {
702
                *(frame->curline-frame->curlinepix)=1+data*4;
703
        } else {
704
                *(frame->curline-frame->curlinepix)=
705
                    *(frame->curline-frame->curlinepix+3)+data*4;
706
        }
707
        frame->curlinepix++;
708
}
709
 
710
static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength)
711
{
712
        int pos=0;
713
        int vlc_cod=0;
714
        int vlc_size=0;
715
        int vlc_data=0;
716
        int bit_cur;
717
        int bit;
718
        data+=4;
719
        while (pos < packetlength) {
720
                bit_cur=8;
721
                while (bit_cur && bit_exp) {
722
                        bit=((*data)>>(bit_cur-1))&1;
723
                        if (!vlc_cod) {
724
                                if (bit) {
725
                                        vlc_size++;
726
                                } else {
727
                                        if (!vlc_size) {
728
                                                decode_JangGu_integrate(se401, 0);
729
                                        } else {
730
                                                vlc_cod=2;
731
                                                vlc_data=0;
732
                                        }
733
                                }
734
                        } else {
735
                                if (vlc_cod==2) {
736
                                        if (!bit) vlc_data=-(1<<vlc_size)+1;
737
                                        vlc_cod--;
738
                                }
739
                                vlc_size--;
740
                                vlc_data+=bit<<vlc_size;
741
                                if (!vlc_size) {
742
                                        decode_JangGu_integrate(se401, vlc_data);
743
                                        vlc_cod=0;
744
                                }
745
                        }
746
                        bit_cur--;
747
                        bit_exp--;
748
                }
749
                pos++;
750
                data++;
751
        }
752
}
753
 
754
static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch *buffer)
755
{
756
        unsigned char *data=buffer->data;
757
        int len=buffer->length;
758
        int bit_exp=0, pix_exp=0, frameinfo=0, packetlength=0, size;
759
        int datapos=0;
760
 
761
        /* New image? */
762
        if (!se401->frame[se401->curframe].curpix) {
763
                se401->frame[se401->curframe].curlinepix=0;
764
                se401->frame[se401->curframe].curline=
765
                    se401->frame[se401->curframe].data+
766
                    se401->cwidth*3-1;
767
                if (se401->frame[se401->curframe].grabstate==FRAME_READY)
768
                        se401->frame[se401->curframe].grabstate=FRAME_GRABBING;
769
                se401->vlcdatapos=0;
770
        }
771
        while (datapos < len) {
772
                size=1024-se401->vlcdatapos;
773
                if (size+datapos > len)
774
                        size=len-datapos;
775
                memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size);
776
                se401->vlcdatapos+=size;
777
                packetlength=0;
778
                if (se401->vlcdatapos >= 4) {
779
                        bit_exp=se401->vlcdata[3]+(se401->vlcdata[2]<<8);
780
                        pix_exp=se401->vlcdata[1]+((se401->vlcdata[0]&0x3f)<<8);
781
                        frameinfo=se401->vlcdata[0]&0xc0;
782
                        packetlength=((bit_exp+47)>>4)<<1;
783
                        if (packetlength > 1024) {
784
                                se401->vlcdatapos=0;
785
                                datapos=len;
786
                                packetlength=0;
787
                                se401->error++;
788
                                se401->frame[se401->curframe].curpix=0;
789
                        }
790
                }
791
                if (packetlength && se401->vlcdatapos >= packetlength) {
792
                        decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength);
793
                        se401->frame[se401->curframe].curpix+=pix_exp*3;
794
                        datapos+=size-(se401->vlcdatapos-packetlength);
795
                        se401->vlcdatapos=0;
796
                        if (se401->frame[se401->curframe].curpix>=se401->cwidth*se401->cheight*3) {
797
                                if (se401->frame[se401->curframe].curpix==se401->cwidth*se401->cheight*3) {
798
                                        if (se401->frame[se401->curframe].grabstate==FRAME_GRABBING) {
799
                                                se401->frame[se401->curframe].grabstate=FRAME_DONE;
800
                                                se401->framecount++;
801
                                                se401->readcount++;
802
                                        }
803
                                        if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
804
                                                se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
805
                                        }
806
                                } else {
807
                                        se401->error++;
808
                                }
809
                                se401->frame[se401->curframe].curpix=0;
810
                                datapos=len;
811
                        }
812
                } else {
813
                        datapos+=size;
814
                }
815
        }
816
}
817
 
818
static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *buffer)
819
{
820
        unsigned char *data=buffer->data;
821
        int len=buffer->length;
822
        int offset=buffer->offset;
823
        int datasize=se401->cwidth*se401->cheight;
824
        struct se401_frame *frame=&se401->frame[se401->curframe];
825
 
826
        unsigned char *framedata=frame->data, *curline, *nextline;
827
        int width=se401->cwidth;
828
        int blineoffset=0, bline;
829
        int linelength=width*3, i;
830
 
831
 
832
        if (frame->curpix==0) {
833
                if (frame->grabstate==FRAME_READY) {
834
                        frame->grabstate=FRAME_GRABBING;
835
                }
836
                frame->curline=framedata+linelength;
837
                frame->curlinepix=0;
838
        }
839
 
840
        if (offset!=frame->curpix) {
841
                /* Regard frame as lost :( */
842
                frame->curpix=0;
843
                se401->error++;
844
                return;
845
        }
846
 
847
        /* Check if we have to much data */
848
        if (frame->curpix+len > datasize) {
849
                len=datasize-frame->curpix;
850
        }
851
        if (se401->cheight%4)
852
                blineoffset=1;
853
        bline=frame->curpix/se401->cwidth+blineoffset;
854
 
855
        curline=frame->curline;
856
        nextline=curline+linelength;
857
        if (nextline >= framedata+datasize*3)
858
                nextline=curline;
859
        while (len) {
860
                if (frame->curlinepix>=width) {
861
                        frame->curlinepix-=width;
862
                        bline=frame->curpix/width+blineoffset;
863
                        curline+=linelength*2;
864
                        nextline+=linelength*2;
865
                        if (curline >= framedata+datasize*3) {
866
                                frame->curlinepix++;
867
                                curline-=3;
868
                                nextline-=3;
869
                                len--;
870
                                data++;
871
                                frame->curpix++;
872
                        }
873
                        if (nextline >= framedata+datasize*3)
874
                                nextline=curline;
875
                }
876
                if ((bline&1)) {
877
                        if ((frame->curlinepix&1)) {
878
                                *(curline+2)=*data;
879
                                *(curline-1)=*data;
880
                                *(nextline+2)=*data;
881
                                *(nextline-1)=*data;
882
                        } else {
883
                                *(curline+1)=
884
                                        (*(curline+1)+*data)/2;
885
                                *(curline-2)=
886
                                        (*(curline-2)+*data)/2;
887
                                *(nextline+1)=*data;
888
                                *(nextline-2)=*data;
889
                        }
890
                } else {
891
                        if ((frame->curlinepix&1)) {
892
                                *(curline+1)=
893
                                        (*(curline+1)+*data)/2;
894
                                *(curline-2)=
895
                                        (*(curline-2)+*data)/2;
896
                                *(nextline+1)=*data;
897
                                *(nextline-2)=*data;
898
                        } else {
899
                                *curline=*data;
900
                                *(curline-3)=*data;
901
                                *nextline=*data;
902
                                *(nextline-3)=*data;
903
                        }
904
                }
905
                frame->curlinepix++;
906
                curline-=3;
907
                nextline-=3;
908
                len--;
909
                data++;
910
                frame->curpix++;
911
        }
912
        frame->curline=curline;
913
 
914
        if (frame->curpix>=datasize) {
915
                /* Fix the top line */
916
                framedata+=linelength;
917
                for (i=0; i<linelength; i++) {
918
                        framedata--;
919
                        *framedata=*(framedata+linelength);
920
                }
921
                /* Fix the left side (green is already present) */
922
                for (i=0; i<se401->cheight; i++) {
923
                        *framedata=*(framedata+3);
924
                        *(framedata+1)=*(framedata+4);
925
                        *(framedata+2)=*(framedata+5);
926
                        framedata+=linelength;
927
                }
928
                frame->curpix=0;
929
                frame->grabstate=FRAME_DONE;
930
                se401->framecount++;
931
                se401->readcount++;
932
                if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
933
                        se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
934
                }
935
        }
936
}
937
 
938
static int se401_newframe(struct usb_se401 *se401, int framenr)
939
{
940
        DECLARE_WAITQUEUE(wait, current);
941
        int errors=0;
942
 
943
        while (se401->streaming &&
944
            (se401->frame[framenr].grabstate==FRAME_READY ||
945
             se401->frame[framenr].grabstate==FRAME_GRABBING) ) {
946
                if(!se401->frame[framenr].curpix) {
947
                        errors++;
948
                }
949
                wait_interruptible(
950
                    se401->scratch[se401->scratch_use].state!=BUFFER_READY,
951
                    &se401->wq,
952
                    &wait
953
                );
954
                if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
955
                        se401->nullpackets=0;
956
                        info("to many null length packets, restarting capture");
957
                        se401_stop_stream(se401);
958
                        se401_start_stream(se401);
959
                } else {
960
                        if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) {
961
                                se401->frame[framenr].grabstate=FRAME_ERROR;
962
                                return -EIO;
963
                        }
964
                        se401->scratch[se401->scratch_use].state=BUFFER_BUSY;
965
                        if (se401->format==FMT_JANGGU) {
966
                                decode_JangGu(se401, &se401->scratch[se401->scratch_use]);
967
                        } else {
968
                                decode_bayer(se401, &se401->scratch[se401->scratch_use]);
969
                        }
970
                        se401->scratch[se401->scratch_use].state=BUFFER_UNUSED;
971
                        se401->scratch_use++;
972
                        if (se401->scratch_use>=SE401_NUMSCRATCH)
973
                                se401->scratch_use=0;
974
                        if (errors > SE401_MAX_ERRORS) {
975
                                errors=0;
976
                                info("to much errors, restarting capture");
977
                                se401_stop_stream(se401);
978
                                se401_start_stream(se401);
979
                        }
980
                }
981
        }
982
 
983
        if (se401->frame[framenr].grabstate==FRAME_DONE)
984
                if (se401->enhance)
985
                        enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3);
986
        return 0;
987
}
988
 
989
 
990
/****************************************************************************
991
 *
992
 * Video4Linux
993
 *
994
 ***************************************************************************/
995
 
996
 
997
static int se401_open(struct video_device *dev, int flags)
998
{
999
        struct usb_se401 *se401 = (struct usb_se401 *)dev;
1000
        int err = 0;
1001
 
1002
        /* we are called with the BKL held */
1003
        MOD_INC_USE_COUNT;
1004
 
1005
        se401->user=1;
1006
        se401->fbuf=rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
1007
        if(!se401->fbuf) err=-ENOMEM;
1008
 
1009
        if (err) {
1010
                MOD_DEC_USE_COUNT;
1011
                se401->user = 0;
1012
        }
1013
 
1014
        return err;
1015
}
1016
 
1017
static void se401_close(struct video_device *dev)
1018
{
1019
        /* called with BKL held */
1020
        struct usb_se401 *se401 = (struct usb_se401 *)dev;
1021
        int i;
1022
 
1023
        for (i=0; i<SE401_NUMFRAMES; i++)
1024
                se401->frame[i].grabstate=FRAME_UNUSED;
1025
        if (se401->streaming)
1026
                se401_stop_stream(se401);
1027
 
1028
        rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
1029
        se401->user=0;
1030
 
1031
        if (se401->removed) {
1032
                video_unregister_device(&se401->vdev);
1033
                kfree(se401->width);
1034
                kfree(se401->height);
1035
                kfree(se401);
1036
                se401 = NULL;
1037
                info("device unregistered");
1038
        }
1039
 
1040
        MOD_DEC_USE_COUNT;
1041
}
1042
 
1043
static int se401_init_done(struct video_device *dev)
1044
{
1045
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
1046
        create_proc_se401_cam((struct usb_se401 *)dev);
1047
#endif
1048
 
1049
        return 0;
1050
}
1051
 
1052
static long se401_write(struct video_device *dev, const char *buf, unsigned long
1053
 count, int noblock)
1054
{
1055
        return -EINVAL;
1056
}
1057
 
1058
static int se401_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
1059
{
1060
        struct usb_se401 *se401 = (struct usb_se401 *)vdev;
1061
 
1062
        if (!se401->dev)
1063
                return -EIO;
1064
 
1065
        switch (cmd) {
1066
        case VIDIOCGCAP:
1067
        {
1068
                struct video_capability b;
1069
                strcpy(b.name, se401->camera_name);
1070
                b.type = VID_TYPE_CAPTURE;
1071
                b.channels = 1;
1072
                b.audios = 0;
1073
                b.maxwidth = se401->width[se401->sizes-1];
1074
                b.maxheight = se401->height[se401->sizes-1];
1075
                b.minwidth = se401->width[0];
1076
                b.minheight = se401->height[0];
1077
 
1078
                if (copy_to_user(arg, &b, sizeof(b)))
1079
                        return -EFAULT;
1080
 
1081
                return 0;
1082
        }
1083
        case VIDIOCGCHAN:
1084
        {
1085
                struct video_channel v;
1086
 
1087
                if (copy_from_user(&v, arg, sizeof(v)))
1088
                        return -EFAULT;
1089
                if (v.channel != 0)
1090
                        return -EINVAL;
1091
 
1092
                v.flags = 0;
1093
                v.tuners = 0;
1094
                v.type = VIDEO_TYPE_CAMERA;
1095
                strcpy(v.name, "Camera");
1096
 
1097
                if (copy_to_user(arg, &v, sizeof(v)))
1098
                        return -EFAULT;
1099
 
1100
                return 0;
1101
        }
1102
        case VIDIOCSCHAN:
1103
        {
1104
                int v;
1105
 
1106
                if (copy_from_user(&v, arg, sizeof(v)))
1107
                        return -EFAULT;
1108
 
1109
                if (v != 0)
1110
                        return -EINVAL;
1111
 
1112
                return 0;
1113
        }
1114
        case VIDIOCGPICT:
1115
        {
1116
                struct video_picture p;
1117
 
1118
                se401_get_pict(se401, &p);
1119
 
1120
                if (copy_to_user(arg, &p, sizeof(p)))
1121
                        return -EFAULT;
1122
                return 0;
1123
        }
1124
        case VIDIOCSPICT:
1125
        {
1126
                struct video_picture p;
1127
 
1128
                if (copy_from_user(&p, arg, sizeof(p)))
1129
                        return -EFAULT;
1130
 
1131
                if (se401_set_pict(se401, &p))
1132
                        return -EINVAL;
1133
                return 0;
1134
        }
1135
        case VIDIOCSWIN:
1136
        {
1137
                struct video_window vw;
1138
 
1139
                if (copy_from_user(&vw, arg, sizeof(vw)))
1140
                        return -EFAULT;
1141
                if (vw.flags)
1142
                        return -EINVAL;
1143
                if (vw.clipcount)
1144
                        return -EINVAL;
1145
                if (se401_set_size(se401, vw.width, vw.height))
1146
                        return -EINVAL;
1147
 
1148
                return 0;
1149
        }
1150
        case VIDIOCGWIN:
1151
        {
1152
                struct video_window vw;
1153
 
1154
                vw.x = 0;               /* FIXME */
1155
                vw.y = 0;
1156
                vw.chromakey = 0;
1157
                vw.flags = 0;
1158
                vw.clipcount = 0;
1159
                vw.width = se401->cwidth;
1160
                vw.height = se401->cheight;
1161
 
1162
                if (copy_to_user(arg, &vw, sizeof(vw)))
1163
                        return -EFAULT;
1164
 
1165
                return 0;
1166
        }
1167
        case VIDIOCGMBUF:
1168
        {
1169
                struct video_mbuf vm;
1170
                int i;
1171
 
1172
                memset(&vm, 0, sizeof(vm));
1173
                vm.size = SE401_NUMFRAMES * se401->maxframesize;
1174
                vm.frames = SE401_NUMFRAMES;
1175
                for (i=0; i<SE401_NUMFRAMES; i++)
1176
                        vm.offsets[i] = se401->maxframesize * i;
1177
 
1178
                if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
1179
                return -EFAULT;
1180
 
1181
                return 0;
1182
        }
1183
        case VIDIOCMCAPTURE:
1184
        {
1185
                struct video_mmap vm;
1186
 
1187
                if (copy_from_user(&vm, arg, sizeof(vm)))
1188
                return -EFAULT;
1189
                if (vm.format != VIDEO_PALETTE_RGB24)
1190
                        return -EINVAL;
1191
                if (vm.frame >= SE401_NUMFRAMES)
1192
                        return -EINVAL;
1193
                if (se401->frame[vm.frame].grabstate != FRAME_UNUSED)
1194
                        return -EBUSY;
1195
 
1196
                /* Is this according to the v4l spec??? */
1197
                if (se401_set_size(se401, vm.width, vm.height))
1198
                        return -EINVAL;
1199
                se401->frame[vm.frame].grabstate=FRAME_READY;
1200
 
1201
                if (!se401->streaming)
1202
                        se401_start_stream(se401);
1203
 
1204
                /* Set the picture properties */
1205
                if (se401->framecount==0)
1206
                        se401_send_pict(se401);
1207
                /* Calibrate the reset level after a few frames. */
1208
                if (se401->framecount%20==1)
1209
                        se401_auto_resetlevel(se401);
1210
 
1211
                return 0;
1212
        }
1213
        case VIDIOCSYNC:
1214
        {
1215
                int frame, ret=0;
1216
 
1217
                if (copy_from_user((void *)&frame, arg, sizeof(int)))
1218
                        return -EFAULT;
1219
 
1220
                if(frame <0 || frame >= SE401_NUMFRAMES)
1221
                        return -EINVAL;
1222
 
1223
                ret=se401_newframe(se401, frame);
1224
                se401->frame[frame].grabstate=FRAME_UNUSED;
1225
                return ret;
1226
        }
1227
        case VIDIOCGFBUF:
1228
        {
1229
                struct video_buffer vb;
1230
 
1231
                memset(&vb, 0, sizeof(vb));
1232
                vb.base = NULL; /* frame buffer not supported, not used */
1233
 
1234
                if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
1235
                        return -EFAULT;
1236
 
1237
                return 0;
1238
        }
1239
        case VIDIOCKEY:
1240
                return 0;
1241
        case VIDIOCCAPTURE:
1242
                return -EINVAL;
1243
        case VIDIOCSFBUF:
1244
                return -EINVAL;
1245
        case VIDIOCGTUNER:
1246
        case VIDIOCSTUNER:
1247
                return -EINVAL;
1248
        case VIDIOCGFREQ:
1249
        case VIDIOCSFREQ:
1250
                return -EINVAL;
1251
        case VIDIOCGAUDIO:
1252
        case VIDIOCSAUDIO:
1253
                return -EINVAL;
1254
        default:
1255
                return -ENOIOCTLCMD;
1256
        } /* end switch */
1257
 
1258
        return 0;
1259
}
1260
 
1261
static long se401_read(struct video_device *dev, char *buf, unsigned long count,
1262
 int noblock)
1263
{
1264
        int realcount=count, ret=0;
1265
        struct usb_se401 *se401 = (struct usb_se401 *)dev;
1266
 
1267
 
1268
        if (se401->dev == NULL)
1269
                return -EIO;
1270
        if (realcount > se401->cwidth*se401->cheight*3)
1271
                realcount=se401->cwidth*se401->cheight*3;
1272
 
1273
        /* Shouldn't happen: */
1274
        if (se401->frame[0].grabstate==FRAME_GRABBING)
1275
                return -EBUSY;
1276
        se401->frame[0].grabstate=FRAME_READY;
1277
        se401->frame[1].grabstate=FRAME_UNUSED;
1278
        se401->curframe=0;
1279
 
1280
        if (!se401->streaming)
1281
                se401_start_stream(se401);
1282
 
1283
        /* Set the picture properties */
1284
        if (se401->framecount==0)
1285
                se401_send_pict(se401);
1286
        /* Calibrate the reset level after a few frames. */
1287
        if (se401->framecount%20==1)
1288
                se401_auto_resetlevel(se401);
1289
 
1290
        ret=se401_newframe(se401, 0);
1291
 
1292
        se401->frame[0].grabstate=FRAME_UNUSED;
1293
        if (ret)
1294
                return ret;
1295
        if (copy_to_user(buf, se401->frame[0].data, realcount))
1296
                return -EFAULT;
1297
 
1298
        return realcount;
1299
}
1300
 
1301
static int se401_mmap(struct video_device *dev, const char *adr,
1302
        unsigned long size)
1303
{
1304
        struct usb_se401 *se401 = (struct usb_se401 *)dev;
1305
        unsigned long start = (unsigned long)adr;
1306
        unsigned long page, pos;
1307
 
1308
        down(&se401->lock);
1309
 
1310
        if (se401->dev == NULL) {
1311
                up(&se401->lock);
1312
                return -EIO;
1313
        }
1314
        if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
1315
                up(&se401->lock);
1316
                return -EINVAL;
1317
        }
1318
        pos = (unsigned long)se401->fbuf;
1319
        while (size > 0) {
1320
                page = kvirt_to_pa(pos);
1321
                if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
1322
                        up(&se401->lock);
1323
                        return -EAGAIN;
1324
                }
1325
                start += PAGE_SIZE;
1326
                pos += PAGE_SIZE;
1327
                if (size > PAGE_SIZE)
1328
                        size -= PAGE_SIZE;
1329
                else
1330
                        size = 0;
1331
        }
1332
        up(&se401->lock);
1333
 
1334
        return 0;
1335
}
1336
 
1337
static struct video_device se401_template = {
1338
        name:           "se401 USB camera",
1339
        type:           VID_TYPE_CAPTURE,
1340
        hardware:       VID_HARDWARE_SE401,
1341
        open:           se401_open,
1342
        close:          se401_close,
1343
        read:           se401_read,
1344
        write:          se401_write,
1345
        ioctl:          se401_ioctl,
1346
        mmap:           se401_mmap,
1347
        initialize:     se401_init_done,
1348
};
1349
 
1350
 
1351
 
1352
/***************************/
1353
static int se401_init(struct usb_se401 *se401)
1354
{
1355
        int i=0, rc;
1356
        unsigned char cp[0x40];
1357
        char temp[200];
1358
 
1359
        /* led on */
1360
        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1361
 
1362
        /* get camera descriptor */
1363
        rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp));
1364
        if (cp[1]!=0x41) {
1365
                err("Wrong descriptor type");
1366
                return 1;
1367
        }
1368
        sprintf (temp, "ExtraFeatures: %d", cp[3]);
1369
 
1370
        se401->sizes=cp[4]+cp[5]*256;
1371
        se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
1372
        if (!se401->width)
1373
                return 1;
1374
        se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
1375
        if (!se401->height) {
1376
                kfree(se401->width);
1377
                return 1;
1378
        }
1379
        for (i=0; i<se401->sizes; i++) {
1380
                    se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256;
1381
                    se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256;
1382
        }
1383
        sprintf (temp, "%s Sizes:", temp);
1384
        for (i=0; i<se401->sizes; i++) {
1385
                sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]);
1386
        }
1387
        info("%s", temp);
1388
        se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3;
1389
 
1390
        rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
1391
        se401->cwidth=cp[0]+cp[1]*256;
1392
        rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
1393
        se401->cheight=cp[0]+cp[1]*256;
1394
 
1395
        if (!cp[2] && SE401_FORMAT_BAYER) {
1396
                err("Bayer format not supported!");
1397
                return 1;
1398
        }
1399
        /* set output mode (BAYER) */
1400
        se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0);
1401
 
1402
        rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
1403
        se401->brightness=cp[0]+cp[1]*256;
1404
        /* some default values */
1405
        se401->resetlevel=0x2d;
1406
        se401->rgain=0x20;
1407
        se401->ggain=0x20;
1408
        se401->bgain=0x20;
1409
        se401_set_exposure(se401, 20000);
1410
        se401->palette=VIDEO_PALETTE_RGB24;
1411
        se401->enhance=1;
1412
        se401->dropped=0;
1413
        se401->error=0;
1414
        se401->framecount=0;
1415
        se401->readcount=0;
1416
 
1417
        /* Start interrupt transfers for snapshot button */
1418
        se401->inturb=usb_alloc_urb(0);
1419
        if (!se401->inturb) {
1420
                info("Allocation of inturb failed");
1421
                return 1;
1422
        }
1423
        FILL_INT_URB(se401->inturb, se401->dev,
1424
            usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT),
1425
            &se401->button, sizeof(se401->button),
1426
            se401_button_irq,
1427
            se401,
1428
            HZ/10
1429
        );
1430
        if (usb_submit_urb(se401->inturb)) {
1431
                info("int urb burned down");
1432
                return 1;
1433
        }
1434
 
1435
        /* Flash the led */
1436
        se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
1437
        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1438
        se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
1439
        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
1440
 
1441
        return 0;
1442
}
1443
 
1444
static void* se401_probe(struct usb_device *dev, unsigned int ifnum,
1445
        const struct usb_device_id *id)
1446
{
1447
        struct usb_interface_descriptor *interface;
1448
        struct usb_se401 *se401;
1449
        char *camera_name=NULL;
1450
 
1451
        /* We don't handle multi-config cameras */
1452
        if (dev->descriptor.bNumConfigurations != 1)
1453
                return NULL;
1454
 
1455
        interface = &dev->actconfig->interface[ifnum].altsetting[0];
1456
 
1457
        /* Is it an se401? */
1458
        if (dev->descriptor.idVendor == 0x03e8 &&
1459
            dev->descriptor.idProduct == 0x0004) {
1460
                camera_name="Endpoints/Aox SE401";
1461
        } else if (dev->descriptor.idVendor == 0x0471 &&
1462
            dev->descriptor.idProduct == 0x030b) {
1463
                camera_name="Philips PCVC665K";
1464
        } else if (dev->descriptor.idVendor == 0x047d &&
1465
            dev->descriptor.idProduct == 0x5001) {
1466
                camera_name="Kensington VideoCAM 67014";
1467
        } else if (dev->descriptor.idVendor == 0x047d &&
1468
            dev->descriptor.idProduct == 0x5002) {
1469
                camera_name="Kensington VideoCAM 6701(5/7)";
1470
        } else if (dev->descriptor.idVendor == 0x047d &&
1471
            dev->descriptor.idProduct == 0x5003) {
1472
                camera_name="Kensington VideoCAM 67016";
1473
        } else
1474
                return NULL;
1475
 
1476
        /* Checking vendor/product should be enough, but what the hell */
1477
        if (interface->bInterfaceClass != 0x00)
1478
                return NULL;
1479
        if (interface->bInterfaceSubClass != 0x00)
1480
                return NULL;
1481
 
1482
        /* We found one */
1483
        info("SE401 camera found: %s", camera_name);
1484
 
1485
        if ((se401 = kmalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
1486
                err("couldn't kmalloc se401 struct");
1487
                return NULL;
1488
        }
1489
 
1490
        memset(se401, 0, sizeof(*se401));
1491
 
1492
        se401->dev = dev;
1493
        se401->iface = interface->bInterfaceNumber;
1494
        se401->camera_name = camera_name;
1495
 
1496
        info("firmware version: %02x", dev->descriptor.bcdDevice & 255);
1497
 
1498
        if (se401_init(se401)) {
1499
                kfree(se401);
1500
                return NULL;
1501
        }
1502
 
1503
        memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
1504
        memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name));
1505
        init_waitqueue_head(&se401->wq);
1506
        init_MUTEX(&se401->lock);
1507
        wmb();
1508
 
1509
        if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
1510
                kfree(se401);
1511
                err("video_register_device failed");
1512
                return NULL;
1513
        }
1514
        info("registered new video device: video%d", se401->vdev.minor);
1515
 
1516
        return se401;
1517
}
1518
 
1519
static void se401_disconnect(struct usb_device *dev, void *ptr)
1520
{
1521
        struct usb_se401 *se401 = (struct usb_se401 *) ptr;
1522
 
1523
        lock_kernel();
1524
        /* We don't want people trying to open up the device */
1525
        if (!se401->user){
1526
                video_unregister_device(&se401->vdev);
1527
                usb_se401_remove_disconnected(se401);
1528
        } else {
1529
                se401->removed = 1;
1530
        }
1531
        unlock_kernel();
1532
}
1533
 
1534
static inline void usb_se401_remove_disconnected (struct usb_se401 *se401)
1535
{
1536
        int i;
1537
 
1538
        se401->dev = NULL;
1539
        se401->frame[0].grabstate = FRAME_ERROR;
1540
        se401->frame[1].grabstate = FRAME_ERROR;
1541
 
1542
        se401->streaming = 0;
1543
 
1544
        wake_up_interruptible(&se401->wq);
1545
 
1546
        for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
1547
                se401->urb[i]->next = NULL;
1548
                usb_unlink_urb(se401->urb[i]);
1549
                usb_free_urb(se401->urb[i]);
1550
                se401->urb[i] = NULL;
1551
                kfree(se401->sbuf[i].data);
1552
        }
1553
        for (i=0; i<SE401_NUMSCRATCH; i++) if (se401->scratch[i].data) {
1554
                kfree(se401->scratch[i].data);
1555
        }
1556
        if (se401->inturb) {
1557
                usb_unlink_urb(se401->inturb);
1558
                usb_free_urb(se401->inturb);
1559
        }
1560
        info("%s disconnected", se401->camera_name);
1561
 
1562
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
1563
        destroy_proc_se401_cam(se401);
1564
#endif
1565
 
1566
        /* Free the memory */
1567
        kfree(se401->width);
1568
        kfree(se401->height);
1569
        kfree(se401);
1570
}
1571
 
1572
static struct usb_driver se401_driver = {
1573
        name:           "se401",
1574
        id_table:       device_table,
1575
        probe:          se401_probe,
1576
        disconnect:     se401_disconnect
1577
};
1578
 
1579
 
1580
 
1581
/****************************************************************************
1582
 *
1583
 *  Module routines
1584
 *
1585
 ***************************************************************************/
1586
 
1587
static int __init usb_se401_init(void)
1588
{
1589
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
1590
        proc_se401_create();
1591
#endif
1592
 
1593
        info("SE401 usb camera driver version %s registering", version);
1594
        if (flickerless)
1595
                if (flickerless!=50 && flickerless!=60) {
1596
                        info("Invallid flickerless value, use 0, 50 or 60.");
1597
                        return -1;
1598
        }
1599
        if (usb_register(&se401_driver) < 0)
1600
                return -1;
1601
        return 0;
1602
}
1603
 
1604
static void __exit usb_se401_exit(void)
1605
{
1606
        usb_deregister(&se401_driver);
1607
        info("SE401 driver deregistered");
1608
 
1609
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
1610
        proc_se401_destroy();
1611
#endif
1612
}
1613
 
1614
module_init(usb_se401_init);
1615
module_exit(usb_se401_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.