vicam.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:22k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* -*- linux-c -*-
  2.  * USB ViCAM driver
  3.  *
  4.  * Copyright (c) 2001 Christopher L Cheney (ccheney@cheney.cx)
  5.  * Copyright (c) 2001 Pavel Machek (pavel@suse.cz) sponsored by SuSE
  6.  *
  7.  *      This program is free software; you can redistribute it and/or
  8.  *      modify it under the terms of the GNU General Public License as
  9.  *      published by the Free Software Foundation; either version 2 of
  10.  *      the License, or (at your option) any later version.
  11.  *
  12.  * This driver is for the Vista Imaging ViCAM and 3Com HomeConnect USB
  13.  *
  14.  * Thanks to Greg Kroah-Hartman for the USB Skeleton driver
  15.  *
  16.  * TODO:
  17.  * - find out the ids for the Vista Imaging ViCAM
  18.  *
  19.  * History:
  20.  *
  21.  * 2001_07_07 - 0.1 - christopher: first version
  22.  * 2001_08_28 - 0.2 - pavel: messed it up, but for some fun, try 
  23.   while true; do dd if=/dev/video of=/dev/fb0 bs=$[0x1e480] count=1 2> /dev/null; done
  24.       yep, moving pictures.
  25.  * 2001_08_29 - 0.3 - pavel: played a little bit more. Experimental mmap support. For some fun,
  26.   get gqcam-0.9, compile it and run. Better than dd ;-).
  27.  * 2001_08_29 - 0.4 - pavel: added shutter speed control (not much functional)
  28.   kill update_params if it does not seem to work for you.
  29.  * 2001_08_30 - 0.5 - pavel: fixed stupid bug with update_params & vicam_bulk
  30.  *
  31.  * FIXME: It crashes on rmmod with camera plugged.
  32.  */
  33. #define DEBUG 1
  34. #include <linux/config.h>
  35. #include <linux/kernel.h>
  36. #include <linux/sched.h>
  37. #include <linux/signal.h>
  38. #include <linux/errno.h>
  39. #include <linux/poll.h>
  40. #include <linux/init.h>
  41. #include <linux/slab.h>
  42. #include <linux/fcntl.h>
  43. #include <linux/module.h>
  44. #include <linux/spinlock.h>
  45. #include <linux/list.h>
  46. #include <linux/smp_lock.h>
  47. #include <linux/devfs_fs_kernel.h>
  48. #include <linux/usb.h>
  49. #include <asm/io.h>
  50. #include <linux/wrapper.h>
  51. #include <linux/vmalloc.h>
  52. #include <linux/videodev.h>
  53. #include "vicam.h"
  54. #include "vicamurbs.h"
  55. /* Version Information */
  56. #define DRIVER_VERSION "v0"
  57. #define DRIVER_AUTHOR "Christopher L Cheney <ccheney@cheney.cx>, Pavel Machek <pavel@suse.cz>"
  58. #define DRIVER_DESC "USB ViCAM Driver"
  59. /* Define these values to match your device */
  60. #define USB_VICAM_VENDOR_ID 0x04C1
  61. #define USB_VICAM_PRODUCT_ID 0x009D
  62. /* table of devices that work with this driver */
  63. static struct usb_device_id vicam_table [] = {
  64. { USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID) },
  65. { } /* Terminating entry */
  66. };
  67. MODULE_DEVICE_TABLE (usb, vicam_table);
  68. static int video_nr = -1;  /* next avail video device */
  69. static struct usb_driver vicam_driver;
  70. static char *buf, *buf2;
  71. static volatile int change_pending = 0; 
  72. static int vicam_parameters(struct usb_vicam *vicam);
  73. /******************************************************************************
  74.  *
  75.  *  Memory management functions
  76.  *
  77.  *  Taken from bttv-drivers.c 2.4.7-pre3
  78.  *
  79.  ******************************************************************************/
  80. /* Here we want the physical address of the memory.
  81.  * This is used when initializing the contents of the area.
  82.  */
  83. static inline unsigned long kvirt_to_pa(unsigned long adr)
  84. {
  85. unsigned long kva, ret;
  86. kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
  87. kva |= adr & (PAGE_SIZE-1); /* restore the offset */
  88. ret = __pa(kva);
  89. return ret;
  90. }
  91. static void * rvmalloc(unsigned long size)
  92. {
  93. void * mem;
  94. unsigned long adr;
  95. size=PAGE_ALIGN(size);
  96. mem=vmalloc_32(size);
  97. if (mem)
  98. {
  99. memset(mem, 0, size); /* Clear the ram out, no junk to the user */
  100. adr=(unsigned long) mem;
  101. while (size > 0)
  102. {
  103. mem_map_reserve(vmalloc_to_page((void *)adr));
  104. adr+=PAGE_SIZE;
  105. size-=PAGE_SIZE;
  106. }
  107. }
  108. return mem;
  109. }
  110. static void rvfree(void * mem, unsigned long size)
  111. {
  112. unsigned long adr;
  113. if (mem)
  114. {
  115. adr=(unsigned long) mem;
  116. while ((long) size > 0)
  117. {
  118. mem_map_unreserve(vmalloc_to_page((void *)adr));
  119. adr+=PAGE_SIZE;
  120. size-=PAGE_SIZE;
  121. }
  122. vfree(mem);
  123. }
  124. }
  125. /******************************************************************************
  126.  *
  127.  *  Foo Bar
  128.  *
  129.  ******************************************************************************/
  130. /**
  131.  * usb_vicam_debug_data
  132.  */
  133. static inline void usb_vicam_debug_data (const char *function, int size, const unsigned char *data)
  134. {
  135. int i;
  136. if (!debug)
  137. return;
  138. printk (KERN_DEBUG __FILE__": %s - length = %d, data = ",
  139. function, size);
  140. for (i = 0; i < size; ++i) {
  141. printk ("%.2x ", data[i]);
  142. }
  143. printk ("n");
  144. }
  145. /*****************************************************************************
  146.  *
  147.  *  Send command to vicam
  148.  *
  149.  *****************************************************************************/
  150. static int vicam_sndctrl(int set, struct usb_vicam *vicam, unsigned short req,
  151. unsigned short value, unsigned char *cp, int size)
  152. {
  153. int ret;
  154. unsigned char *transfer_buffer = kmalloc (size, GFP_KERNEL);
  155. /* Needs to return data I think, works for sending though */
  156. memcpy(transfer_buffer, cp, size);
  157. ret = usb_control_msg ( vicam->udev, set ? usb_sndctrlpipe(vicam->udev, 0) : usb_rcvctrlpipe(vicam->udev, 0), req, (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, 0, transfer_buffer, size, HZ);
  158. kfree(transfer_buffer);
  159. if (ret)
  160. printk("vicam: error: %dn", ret);
  161. mdelay(100);
  162. return ret;
  163. }
  164. /*****************************************************************************
  165.  *
  166.  *  Video4Linux Helpers
  167.  * 
  168.  *****************************************************************************/
  169. static int vicam_get_capability(struct usb_vicam *vicam, struct video_capability *b)
  170. {
  171. dbg("vicam_get_capability");
  172. strcpy(b->name, vicam->camera_name);
  173. b->type = VID_TYPE_CAPTURE | VID_TYPE_MONOCHROME;
  174. b->channels = 1;
  175. b->audios = 0;
  176. b->maxwidth = vicam->width[vicam->sizes-1];
  177. b->maxheight = vicam->height[vicam->sizes-1];
  178. b->minwidth = vicam->width[0];
  179. b->minheight = vicam->height[0];
  180. return 0;
  181. }
  182. static int vicam_get_channel(struct usb_vicam *vicam, struct video_channel *v)
  183. {
  184. dbg("vicam_get_channel");
  185. if (v->channel != 0)
  186. return -EINVAL;
  187.  
  188. v->flags = 0;
  189. v->tuners = 0;
  190. v->type = VIDEO_TYPE_CAMERA;
  191. strcpy(v->name, "Camera");
  192. return 0;
  193. static int vicam_set_channel(struct usb_vicam *vicam, struct video_channel *v)
  194. {
  195. dbg("vicam_set_channel");
  196. if (v->channel != 0)
  197. return -EINVAL;
  198. return 0;
  199. }
  200. static int vicam_get_mmapbuffer(struct usb_vicam *vicam, struct video_mbuf *vm)
  201. {
  202. int i;
  203. dbg("vicam_get_mmapbuffer");
  204. memset(vm, 0, sizeof(vm));
  205. vm->size = VICAM_NUMFRAMES * vicam->maxframesize;
  206. vm->frames = VICAM_NUMFRAMES;
  207. for (i=0; i<VICAM_NUMFRAMES; i++)
  208. vm->offsets[i] = vicam->maxframesize * i;
  209. return 0;
  210. }
  211. static int vicam_get_picture(struct usb_vicam *vicam, struct video_picture *p)
  212. {
  213. dbg("vicam_get_picture");
  214. /* This is probably where that weird 0x56 call goes */
  215. p->brightness = vicam->win.brightness;
  216. p->hue = vicam->win.hue;
  217. p->colour = vicam->win.colour;
  218. p->contrast = vicam->win.contrast;
  219. p->whiteness = vicam->win.whiteness;
  220. p->depth = vicam->win.depth;
  221. p->palette = vicam->win.palette;
  222. return 0;
  223. }
  224. static void synchronize(struct usb_vicam *vicam)
  225. {
  226. DECLARE_WAITQUEUE(wait, current);
  227. change_pending = 1;
  228. set_current_state(TASK_INTERRUPTIBLE);
  229. add_wait_queue(&vicam->wait, &wait);
  230. if (change_pending)
  231. schedule();
  232. remove_wait_queue(&vicam->wait, &wait);
  233. set_current_state(TASK_RUNNING);
  234. vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
  235. mdelay(10);
  236. vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
  237. mdelay(10);
  238. }
  239. static void params_changed(struct usb_vicam *vicam)
  240. {
  241. #if 1
  242. synchronize(vicam);
  243. mdelay(10);
  244. vicam_parameters(vicam);
  245. printk("Submiting urb: %dn", usb_submit_urb(&vicam->readurb));
  246. #endif
  247. }
  248. static int vicam_set_picture(struct usb_vicam *vicam, struct video_picture *p)
  249. {
  250. int changed = 0;
  251. info("vicam_set_picture (%d)", p->brightness);
  252. #define SET(x) 
  253. if (vicam->win.x != p->x) 
  254. vicam->win.x = p->x, changed = 1;
  255. SET(brightness);
  256. SET(hue);
  257. SET(colour);
  258. SET(contrast);
  259. SET(whiteness);
  260. SET(depth);
  261. SET(palette);
  262. if (changed)
  263. params_changed(vicam);
  264. return 0;
  265. /* Investigate what should be done maybe 0x56 type call */
  266. if (p->depth != 8) return 1;
  267. if (p->palette != VIDEO_PALETTE_GREY) return 1;
  268. return 0;
  269. }
  270. /* FIXME - vicam_sync_frame - important */
  271. static int vicam_sync_frame(struct usb_vicam *vicam, int frame)
  272. {
  273. dbg("vicam_sync_frame");
  274. if(frame <0 || frame >= VICAM_NUMFRAMES)
  275. return -EINVAL;
  276. /* Probably need to handle various cases */
  277. /* ret=vicam_newframe(vicam, frame);
  278. vicam->frame[frame].grabstate=FRAME_UNUSED;
  279. */
  280. return 0;
  281. }
  282. static int vicam_get_window(struct usb_vicam *vicam, struct video_window *vw)
  283. {
  284. dbg("vicam_get_window");
  285. vw->x = 0;
  286. vw->y = 0;
  287. vw->chromakey = 0;
  288. vw->flags = 0;
  289. vw->clipcount = 0;
  290. vw->width = vicam->win.width;
  291. vw->height = vicam->win.height;
  292. return 0;
  293. }
  294. static int vicam_set_window(struct usb_vicam *vicam, struct video_window *vw)
  295. {
  296. info("vicam_set_window");
  297. if (vw->flags)
  298. return -EINVAL;
  299. if (vw->clipcount)
  300. return -EINVAL;
  301. if (vicam->win.width == vw->width && vicam->win.height == vw->height)
  302. return 0;
  303. /* Pick largest mode that is smaller than specified res */
  304. /* If specified res is too small reject                 */
  305. /* Add urb send to device... */
  306. vicam->win.width = vw->width;
  307. vicam->win.height = vw->height;
  308. params_changed(vicam);
  309. return 0;
  310. }
  311. /* FIXME - vicam_mmap_capture - important */
  312. static int vicam_mmap_capture(struct usb_vicam *vicam, struct video_mmap *vm)
  313. {
  314. dbg("vicam_mmap_capture");
  315. /* usbvideo.c looks good for using here */
  316. /* 
  317. if (vm->frame >= VICAM_NUMFRAMES)
  318. return -EINVAL;
  319. if (vicam->frame[vm->frame].grabstate != FRAME_UNUSED)
  320. return -EBUSY;
  321. vicam->frame[vm->frame].grabstate=FRAME_READY;
  322. */
  323. /* No need to vicam_set_window here according to Alan */
  324. /*
  325. if (!vicam->streaming)
  326. vicam_start_stream(vicam);
  327. */
  328. /* set frame as ready */
  329. return 0;
  330. }
  331. /*****************************************************************************
  332.  *
  333.  *  Video4Linux
  334.  * 
  335.  *****************************************************************************/
  336. static int vicam_v4l_open(struct video_device *vdev, int flags)
  337. {
  338. struct usb_vicam *vicam = (struct usb_vicam *)vdev;
  339. int err = 0;
  340. dbg("vicam_v4l_open");
  341. MOD_INC_USE_COUNT; 
  342. down(&vicam->sem);
  343. if (vicam->open_count) /* Maybe not needed? */
  344. err = -EBUSY;
  345. else {
  346. vicam->fbuf = rvmalloc(vicam->maxframesize * VICAM_NUMFRAMES);
  347. if (!vicam->fbuf)
  348. err=-ENOMEM;
  349. else {
  350. vicam->open_count = 1;
  351. }
  352. #ifdef BLINKING
  353. vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
  354. info ("led on");
  355. vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
  356. #endif
  357. }
  358. up(&vicam->sem);
  359. if (err)
  360. MOD_DEC_USE_COUNT;
  361. return err;
  362. }
  363. static void vicam_v4l_close(struct video_device *vdev)
  364. {
  365. struct usb_vicam *vicam = (struct usb_vicam *)vdev;
  366. dbg("vicam_v4l_close");
  367. down(&vicam->sem);
  368. #ifdef BLINKING
  369. info ("led off");
  370. vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
  371. // vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0); Leave it on
  372. #endif
  373. rvfree(vicam->fbuf, vicam->maxframesize * VICAM_NUMFRAMES);
  374. vicam->fbuf = 0;
  375. vicam->open_count=0;
  376. up(&vicam->sem);
  377. /* Why does se401.c have a usbdevice check here? */
  378. /* If device is unplugged while open, I guess we only may unregister now */
  379. MOD_DEC_USE_COUNT;
  380. }
  381. static long vicam_v4l_read(struct video_device *vdev, char *user_buf, unsigned long buflen, int noblock)
  382. {
  383. //struct usb_vicam *vicam = (struct usb_vicam *)vdev;
  384. dbg("vicam_v4l_read(%ld)", buflen);
  385. if (!vdev || !buf)
  386. return -EFAULT;
  387. if(buflen > 0x1e480)
  388. buflen = 0x1e480;
  389. if (copy_to_user(user_buf, buf2, buflen))
  390. return -EFAULT;
  391. return buflen;
  392. }
  393. static long vicam_v4l_write(struct video_device *dev, const char *buf, unsigned long count, int noblock)
  394. {
  395. info("vicam_v4l_write");
  396. return -EINVAL;
  397. }
  398. static int vicam_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
  399. {
  400. struct usb_vicam *vicam = (struct usb_vicam *)vdev;
  401. int ret = -EL3RST;
  402. if (!vicam->udev)
  403. return -EIO;
  404. down(&vicam->sem);
  405. switch (cmd) {
  406. case VIDIOCGCAP:
  407. {
  408. struct video_capability b;
  409. ret = vicam_get_capability(vicam,&b);
  410. dbg("name %s",b.name);
  411. if (copy_to_user(arg, &b, sizeof(b)))
  412. ret = -EFAULT;
  413. }
  414. case VIDIOCGFBUF:
  415. {
  416. struct video_buffer vb;
  417. info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param");
  418. /* frame buffer not supported, not used */
  419. memset(&vb, 0, sizeof(vb));
  420. vb.base = NULL;
  421. /* FIXME - VIDIOCGFBUF - why the void */
  422. if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
  423. ret = -EFAULT;
  424. ret = 0;
  425. }
  426. case VIDIOCGWIN:
  427. {
  428. struct video_window vw;
  429. ret = vicam_get_window(vicam, &vw);
  430. if (copy_to_user(arg, &vw, sizeof(vw)))
  431. ret = -EFAULT;
  432. }
  433. case VIDIOCSWIN:
  434. {
  435. struct video_window vw;
  436. if (copy_from_user(&vw, arg, sizeof(vw)))
  437. ret = -EFAULT;
  438. else
  439. ret = vicam_set_window(vicam, &vw);
  440. return ret;
  441. }
  442. case VIDIOCGCHAN:
  443. {
  444. struct video_channel v;
  445. if (copy_from_user(&v, arg, sizeof(v)))
  446. ret = -EFAULT;
  447. else {
  448. ret = vicam_get_channel(vicam,&v);
  449. if (copy_to_user(arg, &v, sizeof(v)))
  450. ret = -EFAULT;
  451. }
  452. }
  453. case VIDIOCSCHAN:
  454. {
  455. struct video_channel v;
  456. if (copy_from_user(&v, arg, sizeof(v)))
  457. ret = -EFAULT;
  458. else
  459. ret = vicam_set_channel(vicam,&v);
  460.   }
  461. case VIDIOCGPICT:
  462. {
  463. struct video_picture p;
  464. ret = vicam_get_picture(vicam, &p);
  465. if (copy_to_user(arg, &p, sizeof(p)))
  466. ret = -EFAULT;
  467. }
  468. case VIDIOCSPICT:
  469. {
  470. struct video_picture p;
  471. if (copy_from_user(&p, arg, sizeof(p)))
  472. ret = -EFAULT;
  473. else
  474. ret = vicam_set_picture(vicam, &p);
  475. }
  476. case VIDIOCGMBUF:
  477. {
  478. struct video_mbuf vm;
  479. ret = vicam_get_mmapbuffer(vicam,&vm);
  480. /* FIXME - VIDIOCGMBUF - why the void */
  481. if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
  482. ret = -EFAULT;
  483. }
  484. case VIDIOCMCAPTURE:
  485. {
  486. struct video_mmap vm;
  487. ret = vicam_mmap_capture(vicam, &vm);
  488. /* FIXME: This is probably not right */
  489. }
  490. case VIDIOCSYNC:
  491. {
  492. int frame;
  493. /* FIXME - VIDIOCSYNC - why the void */
  494. if (copy_from_user((void *)&frame, arg, sizeof(int)))
  495. ret = -EFAULT;
  496. else
  497. ret = vicam_sync_frame(vicam,frame);
  498. }
  499. case VIDIOCKEY:
  500. ret = 0;
  501.  
  502. case VIDIOCCAPTURE:
  503. case VIDIOCSFBUF:
  504. case VIDIOCGTUNER:
  505. case VIDIOCSTUNER:
  506. case VIDIOCGFREQ:
  507. case VIDIOCSFREQ:
  508. case VIDIOCGAUDIO:
  509. case VIDIOCSAUDIO:
  510. case VIDIOCGUNIT:
  511. ret = -EINVAL;
  512. default:
  513. {
  514. info("vicam_v4l_ioctl - %ui",cmd);
  515. ret = -ENOIOCTLCMD;
  516. }
  517. } /* end switch */
  518. up(&vicam->sem);
  519.         return ret;
  520. }
  521. static int vicam_v4l_mmap(struct video_device *dev, const char *adr, unsigned long size)
  522. {
  523. struct usb_vicam *vicam = (struct usb_vicam *)dev;
  524. unsigned long start = (unsigned long)adr;
  525. unsigned long page, pos;
  526. down(&vicam->sem);
  527. if (vicam->udev == NULL) {
  528. up(&vicam->sem);
  529. return -EIO;
  530. }
  531. #if 0
  532. if (size > (((VICAM_NUMFRAMES * vicam->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
  533. up(&vicam->sem);
  534. return -EINVAL;
  535. }
  536. #endif
  537. pos = (unsigned long)vicam->fbuf;
  538. while (size > 0) {
  539. page = kvirt_to_pa(pos);
  540. if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
  541. up(&vicam->sem);
  542. return -EAGAIN;
  543. }
  544. start += PAGE_SIZE;
  545. pos += PAGE_SIZE;
  546. if (size > PAGE_SIZE)
  547. size -= PAGE_SIZE;
  548. else
  549. size = 0;
  550. }
  551. up(&vicam->sem);
  552.         return 0;
  553. }
  554. /* FIXME - vicam_v4l_init */
  555. static int vicam_v4l_init(struct video_device *dev)
  556. {
  557. /* stick proc fs stuff in here if wanted */
  558. dbg("vicam_v4l_init");
  559. return 0;
  560. }
  561. /* FIXME - vicam_template - important */
  562. static struct video_device vicam_template = {
  563. name: "vicam USB camera",
  564. type: VID_TYPE_CAPTURE,
  565. hardware: VID_HARDWARE_SE401, /* need to ask for own id */
  566. open: vicam_v4l_open,
  567. close: vicam_v4l_close,
  568. read: vicam_v4l_read,
  569. write: vicam_v4l_write,
  570. ioctl: vicam_v4l_ioctl,
  571. mmap: vicam_v4l_mmap,
  572. initialize: vicam_v4l_init,
  573. };
  574. /******************************************************************************
  575.  *
  576.  *  Some Routines
  577.  *
  578.  ******************************************************************************/
  579. /*
  580. Flash the led
  581. vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
  582. info ("led on");
  583. vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
  584. info ("led off");
  585. vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
  586. vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
  587. */
  588. static void vicam_bulk(struct urb *urb)
  589. {
  590. struct usb_vicam *vicam = urb->context;
  591. /* if (!vicam || !vicam->dev || !vicam->used)
  592. return;
  593. */
  594. if (urb->status)
  595. printk("vicam%d: nonzero read/write bulk status received: %d",
  596. 0, urb->status);
  597. urb->actual_length = 0;
  598. urb->dev = vicam->udev;
  599. memcpy(buf2, buf+64, 0x1e480);
  600. if (vicam->fbuf)
  601. memcpy(vicam->fbuf, buf+64, 0x1e480);
  602. if (!change_pending) {
  603. if (usb_submit_urb(urb))
  604. dbg("failed resubmitting read urb");
  605. } else {
  606. change_pending = 0;
  607. wake_up_interruptible(&vicam->wait);
  608. }
  609. }
  610. static int vicam_parameters(struct usb_vicam *vicam)
  611. {
  612. unsigned char req[0x10];
  613. unsigned int shutter;
  614. shutter = 10;
  615. switch (vicam->win.width) {
  616. case 512:
  617. default:
  618. memcpy(req, s512x242bw, 0x10);
  619. break;
  620. case 256:
  621. memcpy(req, s256x242bw, 0x10);
  622. break;
  623. case 128:
  624. memcpy(req, s128x122bw, 0x10);
  625. break;
  626. }
  627. mdelay(10);
  628. vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
  629. info ("led on");
  630. vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
  631. mdelay(10);
  632. shutter = vicam->win.contrast / 256;
  633. if (shutter == 0)
  634. shutter = 1;
  635. printk("vicam_parameters: brightness %d, shutter %dn", vicam->win.brightness, shutter );
  636. req[0] = vicam->win.brightness /256;
  637. shutter = 15600/shutter - 1;
  638. req[6] = shutter & 0xff;
  639. req[7] = (shutter >> 8) & 0xff;
  640. vicam_sndctrl(1, vicam, VICAM_REQ_CAPTURE, 0x80, req, 0x10);
  641. mdelay(10);
  642. vicam_sndctrl(0, vicam, VICAM_REQ_GET_SOMETHIN, 0, buf, 0x10);
  643. mdelay(10);
  644. return 0;
  645. }
  646. static int vicam_init(struct usb_vicam *vicam)
  647. {
  648. int width[] = {128, 256, 512};
  649. int height[] = {122, 242, 242};
  650. dbg("vicam_init");
  651. buf = kmalloc(0x1e480, GFP_KERNEL);
  652. buf2 = kmalloc(0x1e480, GFP_KERNEL);
  653. if ((!buf) || (!buf2)) {
  654. printk("Not enough memory for vicam!n");
  655. goto error;
  656. }
  657. /* do we do aspect correction in kernel or not? */
  658. vicam->sizes = 3;
  659. vicam->width = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
  660. vicam->height = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
  661. memcpy(vicam->width, &width, sizeof(width));
  662. memcpy(vicam->height, &height, sizeof(height));
  663. vicam->maxframesize = vicam->width[vicam->sizes-1] * vicam->height[vicam->sizes-1];
  664. /* Download firmware to camera */
  665. vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware1, sizeof(firmware1));
  666. vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex1, sizeof(findex1));
  667. vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
  668. vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware2, sizeof(firmware2));
  669. vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex2, sizeof(findex2));
  670. vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
  671. vicam_parameters(vicam);
  672. FILL_BULK_URB(&vicam->readurb, vicam->udev, usb_rcvbulkpipe(vicam->udev, 0x81),
  673.       buf, 0x1e480, vicam_bulk, vicam);
  674. printk("Submiting urb: %dn", usb_submit_urb(&vicam->readurb));
  675. return 0;
  676. error:
  677. if (buf)
  678. kfree(buf);
  679. if (buf2)
  680. kfree(buf2);
  681. return 1;
  682. }
  683. static void * vicam_probe(struct usb_device *udev, unsigned int ifnum,
  684. const struct usb_device_id *id)
  685. {
  686. struct usb_vicam *vicam;
  687. char *camera_name=NULL;
  688. dbg("vicam_probe");
  689. /* See if the device offered us matches what we can accept */
  690. if ((udev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
  691.     (udev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
  692. return NULL;
  693. }
  694. camera_name="3Com HomeConnect USB";
  695. info("ViCAM camera found: %s", camera_name);
  696. vicam = kmalloc (sizeof(struct usb_vicam), GFP_KERNEL);
  697. if (vicam == NULL) {
  698. err ("couldn't kmalloc vicam struct");
  699. return NULL;
  700. }
  701. memset(vicam, 0, sizeof(*vicam));
  702. vicam->udev = udev;
  703. vicam->camera_name = camera_name;
  704. vicam->win.brightness = 128;
  705. vicam->win.contrast = 10;
  706. /* FIXME */
  707. if (vicam_init(vicam)) {
  708. kfree(vicam);
  709. return NULL;
  710. }
  711. memcpy(&vicam->vdev, &vicam_template, sizeof(vicam_template));
  712. memcpy(vicam->vdev.name, vicam->camera_name, strlen(vicam->camera_name));
  713. if (video_register_device(&vicam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
  714. err("video_register_device");
  715. kfree(vicam);
  716. return NULL;
  717. }
  718. info("registered new video device: video%d", vicam->vdev.minor);
  719. init_MUTEX (&vicam->sem);
  720. init_waitqueue_head(&vicam->wait);
  721. return vicam;
  722. }
  723. /* FIXME - vicam_disconnect - important */
  724. static void vicam_disconnect(struct usb_device *udev, void *ptr)
  725. {
  726. struct usb_vicam *vicam;
  727. vicam = (struct usb_vicam *) ptr;
  728. if (!vicam->open_count)
  729. video_unregister_device(&vicam->vdev);
  730. vicam->udev = NULL;
  731. /*
  732. vicam->frame[0].grabstate = FRAME_ERROR;
  733. vicam->frame[1].grabstate = FRAME_ERROR;
  734. */
  735. /* Free buffers and shit */
  736. info("%s disconnected", vicam->camera_name);
  737. synchronize(vicam);
  738. if (!vicam->open_count) {
  739. /* Other random junk */
  740. kfree(vicam);
  741. vicam = NULL;
  742. }
  743. }
  744. /* usb specific object needed to register this driver with the usb subsystem */
  745. static struct usb_driver vicam_driver = {
  746. name: "vicam",
  747. probe: vicam_probe,
  748. disconnect: vicam_disconnect,
  749. id_table: vicam_table,
  750. };
  751. /******************************************************************************
  752.  *
  753.  *  Module Routines
  754.  *
  755.  ******************************************************************************/
  756. MODULE_AUTHOR(DRIVER_AUTHOR);
  757. MODULE_DESCRIPTION(DRIVER_DESC);
  758. MODULE_LICENSE("GPL");
  759. /* Module paramaters */
  760. MODULE_PARM(debug, "i");
  761. MODULE_PARM_DESC(debug, "Debug enabled or not");
  762. static int __init usb_vicam_init(void)
  763. {
  764. int result;
  765. printk("VICAM: initializingn");
  766. /* register this driver with the USB subsystem */
  767. result = usb_register(&vicam_driver);
  768. if (result < 0) {
  769. err("usb_register failed for the "__FILE__" driver. Error number %d",
  770.     result);
  771. return -1;
  772. }
  773. info(DRIVER_VERSION " " DRIVER_AUTHOR);
  774. info(DRIVER_DESC);
  775. return 0;
  776. }
  777. static void __exit usb_vicam_exit(void)
  778. {
  779. /* deregister this driver with the USB subsystem */
  780. usb_deregister(&vicam_driver);
  781. }
  782. module_init(usb_vicam_init);
  783. module_exit(usb_vicam_exit);