Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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