linux-old/drivers/usb/se401.c
<<
>>
Prefs
   1/*
   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
  28static 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
  46static int flickerless=0;
  47static int video_nr = -1;
  48
  49static 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
  58MODULE_DEVICE_TABLE(usb, device_table);
  59
  60MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
  61MODULE_DESCRIPTION("SE401 USB Camera Driver");
  62MODULE_LICENSE("GPL");
  63MODULE_PARM(flickerless, "i");
  64MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)");
  65MODULE_PARM(video_nr, "i");
  66EXPORT_NO_SYMBOLS;
  67
  68
  69static 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 */
  81static 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
  91static 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
 112static 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
 138static struct proc_dir_entry *se401_proc_entry = NULL;
 139extern struct proc_dir_entry *video_proc_entry;
 140
 141#define YES_NO(x) ((x) ? "yes" : "no")
 142
 143static 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
 185static int se401_write_proc(struct file *file, const char *buffer, 
 186                            unsigned long count, void *data)
 187{
 188        return -EINVAL;
 189}
 190
 191static 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
 213static 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
 226static 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
 241static 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
 257static 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
 273static 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
 293static 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
 321static 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
 334static 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
 350static 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
 367static 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*/
 394static 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 */
 430static 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
 445static 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
 506static 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*/
 553static 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
 612static 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
 641static 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*/
 680static 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
 688static 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
 710static 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
 754static 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
 818static 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
 938static 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
 989static inline void usb_se401_remove_disconnected (struct usb_se401 *se401)
 990{
 991        int i;
 992
 993        se401->dev = NULL;
 994        se401->frame[0].grabstate = FRAME_ERROR;
 995        se401->frame[1].grabstate = FRAME_ERROR;
 996
 997        se401->streaming = 0;
 998
 999        wake_up_interruptible(&se401->wq);
1000
1001        for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
1002                se401->urb[i]->next = NULL;
1003                usb_unlink_urb(se401->urb[i]);
1004                usb_free_urb(se401->urb[i]);
1005                se401->urb[i] = NULL;
1006                kfree(se401->sbuf[i].data);
1007        }
1008        for (i=0; i<SE401_NUMSCRATCH; i++) if (se401->scratch[i].data) {
1009                kfree(se401->scratch[i].data);
1010        }
1011        if (se401->inturb) {
1012                usb_unlink_urb(se401->inturb);
1013                usb_free_urb(se401->inturb);
1014        }
1015        info("%s disconnected", se401->camera_name);
1016
1017#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
1018        destroy_proc_se401_cam(se401);
1019#endif
1020
1021        /* Free the memory */
1022        kfree(se401->width);
1023        kfree(se401->height);
1024        kfree(se401);
1025}
1026
1027
1028/****************************************************************************
1029 *
1030 * Video4Linux
1031 *
1032 ***************************************************************************/
1033
1034
1035static int se401_open(struct video_device *dev, int flags)
1036{
1037        struct usb_se401 *se401 = (struct usb_se401 *)dev;
1038        int err = 0;
1039
1040        /* we are called with the BKL held */
1041        MOD_INC_USE_COUNT;
1042
1043        se401->user=1;
1044        se401->fbuf=rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
1045        if(!se401->fbuf) err=-ENOMEM;
1046
1047        if (err) {
1048                MOD_DEC_USE_COUNT;
1049                se401->user = 0;
1050        }
1051
1052        return err;
1053}
1054
1055static void se401_close(struct video_device *dev)
1056{
1057        /* called with BKL held */
1058        struct usb_se401 *se401 = (struct usb_se401 *)dev;
1059        int i;
1060
1061        for (i=0; i<SE401_NUMFRAMES; i++)
1062                se401->frame[i].grabstate=FRAME_UNUSED;
1063        if (se401->streaming)
1064                se401_stop_stream(se401);
1065
1066        rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
1067        se401->user=0;
1068
1069        if (se401->removed) {
1070                video_unregister_device(&se401->vdev);
1071                kfree(se401->width);
1072                kfree(se401->height);
1073                kfree(se401);
1074                se401 = NULL;
1075                info("device unregistered");
1076        }
1077
1078        MOD_DEC_USE_COUNT;
1079}
1080
1081static int se401_init_done(struct video_device *dev)
1082{
1083#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
1084        create_proc_se401_cam((struct usb_se401 *)dev);
1085#endif
1086
1087        return 0;
1088}
1089
1090static long se401_write(struct video_device *dev, const char *buf, unsigned long
1091 count, int noblock)
1092{
1093        return -EINVAL;
1094}
1095
1096static int se401_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
1097{
1098        struct usb_se401 *se401 = (struct usb_se401 *)vdev;
1099
1100        if (!se401->dev)
1101                return -EIO;
1102
1103        switch (cmd) {
1104        case VIDIOCGCAP:
1105        {
1106                struct video_capability b;
1107                strcpy(b.name, se401->camera_name);
1108                b.type = VID_TYPE_CAPTURE;
1109                b.channels = 1;
1110                b.audios = 0;
1111                b.maxwidth = se401->width[se401->sizes-1];
1112                b.maxheight = se401->height[se401->sizes-1];
1113                b.minwidth = se401->width[0];
1114                b.minheight = se401->height[0];
1115
1116                if (copy_to_user(arg, &b, sizeof(b)))
1117                        return -EFAULT;
1118
1119                return 0;
1120        }
1121        case VIDIOCGCHAN:
1122        {
1123                struct video_channel v;
1124
1125                if (copy_from_user(&v, arg, sizeof(v)))
1126                        return -EFAULT;
1127                if (v.channel != 0)
1128                        return -EINVAL;
1129
1130                v.flags = 0;
1131                v.tuners = 0;
1132                v.type = VIDEO_TYPE_CAMERA;
1133                strcpy(v.name, "Camera");
1134
1135                if (copy_to_user(arg, &v, sizeof(v)))
1136                        return -EFAULT;
1137
1138                return 0;
1139        }
1140        case VIDIOCSCHAN:
1141        {
1142                int v;
1143
1144                if (copy_from_user(&v, arg, sizeof(v)))
1145                        return -EFAULT;
1146
1147                if (v != 0)
1148                        return -EINVAL;
1149
1150                return 0;
1151        }
1152        case VIDIOCGPICT:
1153        {
1154                struct video_picture p;
1155
1156                se401_get_pict(se401, &p);
1157
1158                if (copy_to_user(arg, &p, sizeof(p)))
1159                        return -EFAULT;
1160                return 0;
1161        }
1162        case VIDIOCSPICT:
1163        {
1164                struct video_picture p;
1165
1166                if (copy_from_user(&p, arg, sizeof(p)))
1167                        return -EFAULT;
1168
1169                if (se401_set_pict(se401, &p))
1170                        return -EINVAL;
1171                return 0;
1172        }
1173        case VIDIOCSWIN:
1174        {
1175                struct video_window vw;
1176
1177                if (copy_from_user(&vw, arg, sizeof(vw)))
1178                        return -EFAULT;
1179                if (vw.flags)
1180                        return -EINVAL;
1181                if (vw.clipcount)
1182                        return -EINVAL;
1183                if (se401_set_size(se401, vw.width, vw.height))
1184                        return -EINVAL;
1185
1186                return 0;
1187        }
1188        case VIDIOCGWIN:
1189        {
1190                struct video_window vw;
1191
1192                vw.x = 0;               /* FIXME */
1193                vw.y = 0;
1194                vw.chromakey = 0;
1195                vw.flags = 0;
1196                vw.clipcount = 0;
1197                vw.width = se401->cwidth;
1198                vw.height = se401->cheight;
1199
1200                if (copy_to_user(arg, &vw, sizeof(vw)))
1201                        return -EFAULT;
1202
1203                return 0;
1204        }
1205        case VIDIOCGMBUF:
1206        {
1207                struct video_mbuf vm;
1208                int i;
1209
1210                memset(&vm, 0, sizeof(vm));
1211                vm.size = SE401_NUMFRAMES * se401->maxframesize;
1212                vm.frames = SE401_NUMFRAMES;
1213                for (i=0; i<SE401_NUMFRAMES; i++)
1214                        vm.offsets[i] = se401->maxframesize * i;
1215
1216                if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
1217                return -EFAULT;
1218
1219                return 0;
1220        }
1221        case VIDIOCMCAPTURE:
1222        {
1223                struct video_mmap vm;
1224
1225                if (copy_from_user(&vm, arg, sizeof(vm)))
1226                return -EFAULT;
1227                if (vm.format != VIDEO_PALETTE_RGB24)
1228                        return -EINVAL;
1229                if (vm.frame >= SE401_NUMFRAMES)
1230                        return -EINVAL;
1231                if (se401->frame[vm.frame].grabstate != FRAME_UNUSED)
1232                        return -EBUSY;
1233
1234                /* Is this according to the v4l spec??? */
1235                if (se401_set_size(se401, vm.width, vm.height))
1236                        return -EINVAL;
1237                se401->frame[vm.frame].grabstate=FRAME_READY;
1238
1239                if (!se401->streaming)
1240                        se401_start_stream(se401);
1241
1242                /* Set the picture properties */
1243                if (se401->framecount==0)
1244                        se401_send_pict(se401);
1245                /* Calibrate the reset level after a few frames. */
1246                if (se401->framecount%20==1)
1247                        se401_auto_resetlevel(se401);
1248
1249                return 0;
1250        }
1251        case VIDIOCSYNC:
1252        {
1253                int frame, ret=0;
1254
1255                if (copy_from_user((void *)&frame, arg, sizeof(int)))
1256                        return -EFAULT;
1257
1258                if(frame <0 || frame >= SE401_NUMFRAMES)
1259                        return -EINVAL;
1260
1261                ret=se401_newframe(se401, frame);
1262                se401->frame[frame].grabstate=FRAME_UNUSED;
1263                return ret;
1264        }
1265        case VIDIOCGFBUF:
1266        {
1267                struct video_buffer vb;
1268
1269                memset(&vb, 0, sizeof(vb));
1270                vb.base = NULL; /* frame buffer not supported, not used */
1271
1272                if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
1273                        return -EFAULT;
1274
1275                return 0;
1276        }
1277        case VIDIOCKEY:
1278                return 0;
1279        case VIDIOCCAPTURE:
1280                return -EINVAL;
1281        case VIDIOCSFBUF:
1282                return -EINVAL;
1283        case VIDIOCGTUNER:
1284        case VIDIOCSTUNER:
1285                return -EINVAL;
1286        case VIDIOCGFREQ:
1287        case VIDIOCSFREQ:
1288                return -EINVAL;
1289        case VIDIOCGAUDIO:
1290        case VIDIOCSAUDIO:
1291                return -EINVAL;
1292        default:
1293                return -ENOIOCTLCMD;
1294        } /* end switch */
1295
1296        return 0;
1297}
1298
1299static long se401_read(struct video_device *dev, char *buf, unsigned long count,
1300 int noblock)
1301{
1302        int realcount=count, ret=0;
1303        struct usb_se401 *se401 = (struct usb_se401 *)dev;
1304
1305
1306        if (se401->dev == NULL)
1307                return -EIO;
1308        if (realcount > se401->cwidth*se401->cheight*3)
1309                realcount=se401->cwidth*se401->cheight*3;
1310
1311        /* Shouldn't happen: */
1312        if (se401->frame[0].grabstate==FRAME_GRABBING)
1313                return -EBUSY;
1314        se401->frame[0].grabstate=FRAME_READY;
1315        se401->frame[1].grabstate=FRAME_UNUSED;
1316        se401->curframe=0;
1317
1318        if (!se401->streaming)
1319                se401_start_stream(se401);
1320
1321        /* Set the picture properties */
1322        if (se401->framecount==0)
1323                se401_send_pict(se401);
1324        /* Calibrate the reset level after a few frames. */
1325        if (se401->framecount%20==1)
1326                se401_auto_resetlevel(se401);
1327
1328        ret=se401_newframe(se401, 0);
1329
1330        se401->frame[0].grabstate=FRAME_UNUSED;
1331        if (ret)
1332                return ret;     
1333        if (copy_to_user(buf, se401->frame[0].data, realcount))
1334                return -EFAULT;
1335
1336        return realcount;
1337}
1338
1339static int se401_mmap(struct video_device *dev, const char *adr,
1340        unsigned long size)
1341{
1342        struct usb_se401 *se401 = (struct usb_se401 *)dev;
1343        unsigned long start = (unsigned long)adr;
1344        unsigned long page, pos;
1345
1346        down(&se401->lock);
1347
1348        if (se401->dev == NULL) {
1349                up(&se401->lock);
1350                return -EIO;
1351        }
1352        if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
1353                up(&se401->lock);
1354                return -EINVAL;
1355        }
1356        pos = (unsigned long)se401->fbuf;
1357        while (size > 0) {
1358                page = kvirt_to_pa(pos);
1359                if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
1360                        up(&se401->lock);
1361                        return -EAGAIN;
1362                }
1363                start += PAGE_SIZE;
1364                pos += PAGE_SIZE;
1365                if (size > PAGE_SIZE)
1366                        size -= PAGE_SIZE;
1367                else
1368                        size = 0;
1369        }
1370        up(&se401->lock);
1371
1372        return 0;
1373}
1374
1375static struct video_device se401_template = {
1376        name:           "se401 USB camera",
1377        type:           VID_TYPE_CAPTURE,
1378        hardware:       VID_HARDWARE_SE401,
1379        open:           se401_open,
1380        close:          se401_close,
1381        read:           se401_read,
1382        write:          se401_write,
1383        ioctl:          se401_ioctl,
1384        mmap:           se401_mmap,
1385        initialize:     se401_init_done,
1386};
1387
1388
1389
1390/***************************/
1391static int se401_init(struct usb_se401 *se401)
1392{
1393        int i=0, rc;
1394        unsigned char cp[0x40];
1395        char temp[200];
1396
1397        /* led on */
1398        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1399
1400        /* get camera descriptor */
1401        rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp));
1402        if (cp[1]!=0x41) {
1403                err("Wrong descriptor type");
1404                return 1;
1405        }
1406        sprintf (temp, "ExtraFeatures: %d", cp[3]);
1407
1408        se401->sizes=cp[4]+cp[5]*256;
1409        se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
1410        if (!se401->width)
1411                return 1;
1412        se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
1413        if (!se401->height) {
1414                kfree(se401->width);
1415                return 1;
1416        }
1417        for (i=0; i<se401->sizes; i++) {
1418                    se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256;
1419                    se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256;
1420        }
1421        sprintf (temp, "%s Sizes:", temp);
1422        for (i=0; i<se401->sizes; i++) {
1423                sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]);
1424        }
1425        info("%s", temp);
1426        se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3;
1427
1428        rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
1429        se401->cwidth=cp[0]+cp[1]*256;
1430        rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
1431        se401->cheight=cp[0]+cp[1]*256;
1432
1433        if (!cp[2] && SE401_FORMAT_BAYER) {
1434                err("Bayer format not supported!");
1435                return 1;
1436        }
1437        /* set output mode (BAYER) */
1438        se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0);
1439
1440        rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
1441        se401->brightness=cp[0]+cp[1]*256;
1442        /* some default values */
1443        se401->resetlevel=0x2d;
1444        se401->rgain=0x20;
1445        se401->ggain=0x20;
1446        se401->bgain=0x20;
1447        se401_set_exposure(se401, 20000);
1448        se401->palette=VIDEO_PALETTE_RGB24;
1449        se401->enhance=1;
1450        se401->dropped=0;
1451        se401->error=0;
1452        se401->framecount=0;
1453        se401->readcount=0;
1454
1455        /* Start interrupt transfers for snapshot button */
1456        se401->inturb=usb_alloc_urb(0);
1457        if (!se401->inturb) {
1458                info("Allocation of inturb failed");
1459                return 1;
1460        }
1461        FILL_INT_URB(se401->inturb, se401->dev,
1462            usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT),
1463            &se401->button, sizeof(se401->button),
1464            se401_button_irq,
1465            se401,
1466            HZ/10
1467        );
1468        if (usb_submit_urb(se401->inturb)) {
1469                info("int urb burned down");
1470                return 1;
1471        }
1472
1473        /* Flash the led */
1474        se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
1475        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1476        se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
1477        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
1478
1479        return 0;
1480}
1481
1482static void* se401_probe(struct usb_device *dev, unsigned int ifnum,
1483        const struct usb_device_id *id)
1484{
1485        struct usb_interface_descriptor *interface;
1486        struct usb_se401 *se401;
1487        char *camera_name=NULL;
1488
1489        /* We don't handle multi-config cameras */
1490        if (dev->descriptor.bNumConfigurations != 1)
1491                return NULL;
1492
1493        interface = &dev->actconfig->interface[ifnum].altsetting[0];
1494
1495        /* Is it an se401? */
1496        if (dev->descriptor.idVendor == 0x03e8 &&
1497            dev->descriptor.idProduct == 0x0004) {
1498                camera_name="Endpoints/Aox SE401";
1499        } else if (dev->descriptor.idVendor == 0x0471 &&
1500            dev->descriptor.idProduct == 0x030b) {
1501                camera_name="Philips PCVC665K";
1502        } else if (dev->descriptor.idVendor == 0x047d &&
1503            dev->descriptor.idProduct == 0x5001) {
1504                camera_name="Kensington VideoCAM 67014";
1505        } else if (dev->descriptor.idVendor == 0x047d &&
1506            dev->descriptor.idProduct == 0x5002) {
1507                camera_name="Kensington VideoCAM 6701(5/7)";
1508        } else if (dev->descriptor.idVendor == 0x047d &&
1509            dev->descriptor.idProduct == 0x5003) {
1510                camera_name="Kensington VideoCAM 67016";
1511        } else
1512                return NULL;
1513
1514        /* Checking vendor/product should be enough, but what the hell */
1515        if (interface->bInterfaceClass != 0x00)
1516                return NULL;
1517        if (interface->bInterfaceSubClass != 0x00)
1518                return NULL;
1519
1520        /* We found one */
1521        info("SE401 camera found: %s", camera_name);
1522
1523        if ((se401 = kmalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
1524                err("couldn't kmalloc se401 struct");
1525                return NULL;
1526        }
1527
1528        memset(se401, 0, sizeof(*se401));
1529
1530        se401->dev = dev;
1531        se401->iface = interface->bInterfaceNumber;
1532        se401->camera_name = camera_name;
1533
1534        info("firmware version: %02x", dev->descriptor.bcdDevice & 255);
1535
1536        if (se401_init(se401)) {
1537                kfree(se401);
1538                return NULL;
1539        }
1540
1541        memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
1542        memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name));
1543        init_waitqueue_head(&se401->wq);
1544        init_MUTEX(&se401->lock);
1545        wmb();
1546
1547        if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
1548                kfree(se401);
1549                err("video_register_device failed");
1550                return NULL;
1551        }
1552        info("registered new video device: video%d", se401->vdev.minor);
1553
1554        return se401;
1555}
1556
1557static void se401_disconnect(struct usb_device *dev, void *ptr)
1558{
1559        struct usb_se401 *se401 = (struct usb_se401 *) ptr;
1560
1561        lock_kernel();
1562        /* We don't want people trying to open up the device */
1563        if (!se401->user){
1564                video_unregister_device(&se401->vdev);
1565                usb_se401_remove_disconnected(se401);
1566        } else {
1567                se401->removed = 1;
1568        }
1569        unlock_kernel();
1570}
1571
1572static 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
1587static 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
1604static 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
1614module_init(usb_se401_init);
1615module_exit(usb_se401_exit);
1616
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.