vicam.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:23k
源码类别:

嵌入式Linux

开发平台:

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 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. /* [DaveM] I've recoded most of this so that:
  81.  * 1) It's easier to tell what is happening
  82.  * 2) It's more portable, especially for translating things
  83.  *    out of vmalloc mapped areas in the kernel.
  84.  * 3) Less unnecessary translations happen.
  85.  *
  86.  * The code used to assume that the kernel vmalloc mappings
  87.  * existed in the page tables of every process, this is simply
  88.  * not guarenteed.  We now use pgd_offset_k which is the
  89.  * defined way to get at the kernel page tables.
  90.  */
  91. /* Given PGD from the address space's page table, return the kernel
  92.  * virtual mapping of the physical memory mapped at ADR.
  93.  */
  94. static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
  95. {
  96. unsigned long ret = 0UL;
  97. pmd_t *pmd;
  98. pte_t *ptep, pte;
  99. if (!pgd_none(*pgd)) {
  100. pmd = pmd_offset(pgd, adr);
  101. if (!pmd_none(*pmd)) {
  102. ptep = pte_offset(pmd, adr);
  103. pte = *ptep;
  104. if(pte_present(pte)) {
  105. ret  = (unsigned long) page_address(pte_page(pte));
  106. ret |= (adr & (PAGE_SIZE - 1));
  107. }
  108. }
  109. }
  110. return ret;
  111. }
  112. static inline unsigned long uvirt_to_bus(unsigned long adr)
  113. {
  114. unsigned long kva, ret;
  115. kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
  116. ret = virt_to_bus((void *)kva);
  117. return ret;
  118. }
  119. static inline unsigned long kvirt_to_bus(unsigned long adr)
  120. {
  121. unsigned long va, kva, ret;
  122. va = VMALLOC_VMADDR(adr);
  123. kva = uvirt_to_kva(pgd_offset_k(va), va);
  124. ret = virt_to_bus((void *)kva);
  125. return ret;
  126. }
  127. /* Here we want the physical address of the memory.
  128.  * This is used when initializing the contents of the
  129.  * area and marking the pages as reserved.
  130.  */
  131. static inline unsigned long kvirt_to_pa(unsigned long adr)
  132. {
  133. unsigned long va, kva, ret;
  134. va = VMALLOC_VMADDR(adr);
  135. kva = uvirt_to_kva(pgd_offset_k(va), va);
  136. ret = __pa(kva);
  137. return ret;
  138. }
  139. static void * rvmalloc(signed long size)
  140. {
  141. void * mem;
  142. unsigned long adr, page;
  143. mem=vmalloc_32(size);
  144. if (mem)
  145. {
  146. memset(mem, 0, size); /* Clear the ram out, no junk to the user */
  147. adr=(unsigned long) mem;
  148. while (size > 0)
  149. {
  150. page = kvirt_to_pa(adr);
  151. mem_map_reserve(virt_to_page(__va(page)));
  152. adr+=PAGE_SIZE;
  153. size-=PAGE_SIZE;
  154. }
  155. }
  156. return mem;
  157. }
  158. static void rvfree(void * mem, signed long size)
  159. {
  160. unsigned long adr, page;
  161. if (mem)
  162. {
  163. adr=(unsigned long) mem;
  164. while (size > 0)
  165. {
  166. page = kvirt_to_pa(adr);
  167. mem_map_unreserve(virt_to_page(__va(page)));
  168. adr+=PAGE_SIZE;
  169. size-=PAGE_SIZE;
  170. }
  171. vfree(mem);
  172. }
  173. }
  174. /******************************************************************************
  175.  *
  176.  *  Foo Bar
  177.  *
  178.  ******************************************************************************/
  179. /**
  180.  * usb_vicam_debug_data
  181.  */
  182. static inline void usb_vicam_debug_data (const char *function, int size, const unsigned char *data)
  183. {
  184. int i;
  185. if (!debug)
  186. return;
  187. printk (KERN_DEBUG __FILE__": %s - length = %d, data = ",
  188. function, size);
  189. for (i = 0; i < size; ++i) {
  190. printk ("%.2x ", data[i]);
  191. }
  192. printk ("n");
  193. }
  194. /*****************************************************************************
  195.  *
  196.  *  Send command to vicam
  197.  *
  198.  *****************************************************************************/
  199. static int vicam_sndctrl(int set, struct usb_vicam *vicam, unsigned short req,
  200. unsigned short value, unsigned char *cp, int size)
  201. {
  202. int ret;
  203. unsigned char *transfer_buffer = kmalloc (size, GFP_KERNEL);
  204. /* Needs to return data I think, works for sending though */
  205. memcpy(transfer_buffer, cp, size);
  206. 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);
  207. kfree(transfer_buffer);
  208. if (ret)
  209. printk("vicam: error: %dn", ret);
  210. mdelay(100);
  211. return ret;
  212. }
  213. /*****************************************************************************
  214.  *
  215.  *  Video4Linux Helpers
  216.  * 
  217.  *****************************************************************************/
  218. static int vicam_get_capability(struct usb_vicam *vicam, struct video_capability *b)
  219. {
  220. dbg("vicam_get_capability");
  221. strcpy(b->name, vicam->camera_name);
  222. b->type = VID_TYPE_CAPTURE | VID_TYPE_MONOCHROME;
  223. b->channels = 1;
  224. b->audios = 0;
  225. b->maxwidth = vicam->width[vicam->sizes-1];
  226. b->maxheight = vicam->height[vicam->sizes-1];
  227. b->minwidth = vicam->width[0];
  228. b->minheight = vicam->height[0];
  229. return 0;
  230. }
  231. static int vicam_get_channel(struct usb_vicam *vicam, struct video_channel *v)
  232. {
  233. dbg("vicam_get_channel");
  234. if (v->channel != 0)
  235. return -EINVAL;
  236.  
  237. v->flags = 0;
  238. v->tuners = 0;
  239. v->type = VIDEO_TYPE_CAMERA;
  240. strcpy(v->name, "Camera");
  241. return 0;
  242. static int vicam_set_channel(struct usb_vicam *vicam, struct video_channel *v)
  243. {
  244. dbg("vicam_set_channel");
  245. if (v->channel != 0)
  246. return -EINVAL;
  247. return 0;
  248. }
  249. static int vicam_get_mmapbuffer(struct usb_vicam *vicam, struct video_mbuf *vm)
  250. {
  251. int i;
  252. dbg("vicam_get_mmapbuffer");
  253. memset(vm, 0, sizeof(vm));
  254. vm->size = VICAM_NUMFRAMES * vicam->maxframesize;
  255. vm->frames = VICAM_NUMFRAMES;
  256. for (i=0; i<VICAM_NUMFRAMES; i++)
  257. vm->offsets[i] = vicam->maxframesize * i;
  258. return 0;
  259. }
  260. static int vicam_get_picture(struct usb_vicam *vicam, struct video_picture *p)
  261. {
  262. dbg("vicam_get_picture");
  263. /* This is probably where that weird 0x56 call goes */
  264. p->brightness = vicam->win.brightness;
  265. p->hue = vicam->win.hue;
  266. p->colour = vicam->win.colour;
  267. p->contrast = vicam->win.contrast;
  268. p->whiteness = vicam->win.whiteness;
  269. p->depth = vicam->win.depth;
  270. p->palette = vicam->win.palette;
  271. return 0;
  272. }
  273. static void synchronize(struct usb_vicam *vicam)
  274. {
  275. change_pending = 1;
  276. interruptible_sleep_on(&vicam->wait);
  277. vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
  278. mdelay(10);
  279. vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
  280. mdelay(10);
  281. }
  282. static void params_changed(struct usb_vicam *vicam)
  283. {
  284. #if 1
  285. synchronize(vicam);
  286. mdelay(10);
  287. vicam_parameters(vicam);
  288. printk("Submiting urb: %dn", usb_submit_urb(&vicam->readurb));
  289. #endif
  290. }
  291. static int vicam_set_picture(struct usb_vicam *vicam, struct video_picture *p)
  292. {
  293. int changed = 0;
  294. info("vicam_set_picture (%d)", p->brightness);
  295. #define SET(x) 
  296. if (vicam->win.x != p->x) 
  297. vicam->win.x = p->x, changed = 1;
  298. SET(brightness);
  299. SET(hue);
  300. SET(colour);
  301. SET(contrast);
  302. SET(whiteness);
  303. SET(depth);
  304. SET(palette);
  305. if (changed)
  306. params_changed(vicam);
  307. return 0;
  308. /* Investigate what should be done maybe 0x56 type call */
  309. if (p->depth != 8) return 1;
  310. if (p->palette != VIDEO_PALETTE_GREY) return 1;
  311. return 0;
  312. }
  313. /* FIXME - vicam_sync_frame - important */
  314. static int vicam_sync_frame(struct usb_vicam *vicam, int frame)
  315. {
  316. dbg("vicam_sync_frame");
  317. if(frame <0 || frame >= VICAM_NUMFRAMES)
  318. return -EINVAL;
  319. /* Probably need to handle various cases */
  320. /* ret=vicam_newframe(vicam, frame);
  321. vicam->frame[frame].grabstate=FRAME_UNUSED;
  322. */
  323. return 0;
  324. }
  325. static int vicam_get_window(struct usb_vicam *vicam, struct video_window *vw)
  326. {
  327. dbg("vicam_get_window");
  328. vw->x = 0;
  329. vw->y = 0;
  330. vw->chromakey = 0;
  331. vw->flags = 0;
  332. vw->clipcount = 0;
  333. vw->width = vicam->win.width;
  334. vw->height = vicam->win.height;
  335. return 0;
  336. }
  337. static int vicam_set_window(struct usb_vicam *vicam, struct video_window *vw)
  338. {
  339. info("vicam_set_window");
  340. if (vw->flags)
  341. return -EINVAL;
  342. if (vw->clipcount)
  343. return -EINVAL;
  344. if (vicam->win.width == vw->width && vicam->win.height == vw->height)
  345. return 0;
  346. /* Pick largest mode that is smaller than specified res */
  347. /* If specified res is too small reject                 */
  348. /* Add urb send to device... */
  349. vicam->win.width = vw->width;
  350. vicam->win.height = vw->height;
  351. params_changed(vicam);
  352. return 0;
  353. }
  354. /* FIXME - vicam_mmap_capture - important */
  355. static int vicam_mmap_capture(struct usb_vicam *vicam, struct video_mmap *vm)
  356. {
  357. dbg("vicam_mmap_capture");
  358. /* usbvideo.c looks good for using here */
  359. /* 
  360. if (vm->frame >= VICAM_NUMFRAMES)
  361. return -EINVAL;
  362. if (vicam->frame[vm->frame].grabstate != FRAME_UNUSED)
  363. return -EBUSY;
  364. vicam->frame[vm->frame].grabstate=FRAME_READY;
  365. */
  366. /* No need to vicam_set_window here according to Alan */
  367. /*
  368. if (!vicam->streaming)
  369. vicam_start_stream(vicam);
  370. */
  371. /* set frame as ready */
  372. return 0;
  373. }
  374. /*****************************************************************************
  375.  *
  376.  *  Video4Linux
  377.  * 
  378.  *****************************************************************************/
  379. static int vicam_v4l_open(struct video_device *vdev, int flags)
  380. {
  381. struct usb_vicam *vicam = (struct usb_vicam *)vdev;
  382. int err = 0;
  383. dbg("vicam_v4l_open");
  384. MOD_INC_USE_COUNT; 
  385. down(&vicam->sem);
  386. if (vicam->open_count) /* Maybe not needed? */
  387. err = -EBUSY;
  388. else {
  389. vicam->fbuf = rvmalloc(vicam->maxframesize * VICAM_NUMFRAMES);
  390. if (!vicam->fbuf)
  391. err=-ENOMEM;
  392. else {
  393. vicam->open_count = 1;
  394. }
  395. #ifdef BLINKING
  396. vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
  397. info ("led on");
  398. vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
  399. #endif
  400. }
  401. up(&vicam->sem);
  402. if (err)
  403. MOD_DEC_USE_COUNT;
  404. return err;
  405. }
  406. static void vicam_v4l_close(struct video_device *vdev)
  407. {
  408. struct usb_vicam *vicam = (struct usb_vicam *)vdev;
  409. dbg("vicam_v4l_close");
  410. down(&vicam->sem);
  411. #ifdef BLINKING
  412. info ("led off");
  413. vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
  414. // vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0); Leave it on
  415. #endif
  416. rvfree(vicam->fbuf, vicam->maxframesize * VICAM_NUMFRAMES);
  417. vicam->fbuf = 0;
  418. vicam->open_count=0;
  419. up(&vicam->sem);
  420. /* Why does se401.c have a usbdevice check here? */
  421. /* If device is unplugged while open, I guess we only may unregister now */
  422. MOD_DEC_USE_COUNT;
  423. }
  424. static long vicam_v4l_read(struct video_device *vdev, char *user_buf, unsigned long buflen, int noblock)
  425. {
  426. //struct usb_vicam *vicam = (struct usb_vicam *)vdev;
  427. dbg("vicam_v4l_read(%ld)", buflen);
  428. if (!vdev || !buf)
  429. return -EFAULT;
  430. if (copy_to_user(user_buf, buf2, buflen))
  431. return -EFAULT;
  432. return buflen;
  433. }
  434. static long vicam_v4l_write(struct video_device *dev, const char *buf, unsigned long count, int noblock)
  435. {
  436. info("vicam_v4l_write");
  437. return -EINVAL;
  438. }
  439. static int vicam_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
  440. {
  441. struct usb_vicam *vicam = (struct usb_vicam *)vdev;
  442. int ret = -EL3RST;
  443. if (!vicam->udev)
  444. return -EIO;
  445. down(&vicam->sem);
  446. switch (cmd) {
  447. case VIDIOCGCAP:
  448. {
  449. struct video_capability b;
  450. ret = vicam_get_capability(vicam,&b);
  451. dbg("name %s",b.name);
  452. if (copy_to_user(arg, &b, sizeof(b)))
  453. ret = -EFAULT;
  454. }
  455. case VIDIOCGFBUF:
  456. {
  457. struct video_buffer vb;
  458. info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param");
  459. /* frame buffer not supported, not used */
  460. memset(&vb, 0, sizeof(vb));
  461. vb.base = NULL;
  462. /* FIXME - VIDIOCGFBUF - why the void */
  463. if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
  464. ret = -EFAULT;
  465. ret = 0;
  466. }
  467. case VIDIOCGWIN:
  468. {
  469. struct video_window vw;
  470. ret = vicam_get_window(vicam, &vw);
  471. if (copy_to_user(arg, &vw, sizeof(vw)))
  472. ret = -EFAULT;
  473. }
  474. case VIDIOCSWIN:
  475. {
  476. struct video_window vw;
  477. if (copy_from_user(&vw, arg, sizeof(vw)))
  478. ret = -EFAULT;
  479. else
  480. ret = vicam_set_window(vicam, &vw);
  481. return ret;
  482. }
  483. case VIDIOCGCHAN:
  484. {
  485. struct video_channel v;
  486. if (copy_from_user(&v, arg, sizeof(v)))
  487. ret = -EFAULT;
  488. else {
  489. ret = vicam_get_channel(vicam,&v);
  490. if (copy_to_user(arg, &v, sizeof(v)))
  491. ret = -EFAULT;
  492. }
  493. }
  494. case VIDIOCSCHAN:
  495. {
  496. struct video_channel v;
  497. if (copy_from_user(&v, arg, sizeof(v)))
  498. ret = -EFAULT;
  499. else
  500. ret = vicam_set_channel(vicam,&v);
  501.   }
  502. case VIDIOCGPICT:
  503. {
  504. struct video_picture p;
  505. ret = vicam_get_picture(vicam, &p);
  506. if (copy_to_user(arg, &p, sizeof(p)))
  507. ret = -EFAULT;
  508. }
  509. case VIDIOCSPICT:
  510. {
  511. struct video_picture p;
  512. if (copy_from_user(&p, arg, sizeof(p)))
  513. ret = -EFAULT;
  514. else
  515. ret = vicam_set_picture(vicam, &p);
  516. }
  517. case VIDIOCGMBUF:
  518. {
  519. struct video_mbuf vm;
  520. ret = vicam_get_mmapbuffer(vicam,&vm);
  521. /* FIXME - VIDIOCGMBUF - why the void */
  522. if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
  523. ret = -EFAULT;
  524. }
  525. case VIDIOCMCAPTURE:
  526. {
  527. struct video_mmap vm;
  528. ret = vicam_mmap_capture(vicam, &vm);
  529. /* FIXME: This is probably not right */
  530. }
  531. case VIDIOCSYNC:
  532. {
  533. int frame;
  534. /* FIXME - VIDIOCSYNC - why the void */
  535. if (copy_from_user((void *)&frame, arg, sizeof(int)))
  536. ret = -EFAULT;
  537. else
  538. ret = vicam_sync_frame(vicam,frame);
  539. }
  540. case VIDIOCKEY:
  541. ret = 0;
  542.  
  543. case VIDIOCCAPTURE:
  544. case VIDIOCSFBUF:
  545. case VIDIOCGTUNER:
  546. case VIDIOCSTUNER:
  547. case VIDIOCGFREQ:
  548. case VIDIOCSFREQ:
  549. case VIDIOCGAUDIO:
  550. case VIDIOCSAUDIO:
  551. case VIDIOCGUNIT:
  552. ret = -EINVAL;
  553. default:
  554. {
  555. info("vicam_v4l_ioctl - %ui",cmd);
  556. ret = -ENOIOCTLCMD;
  557. }
  558. } /* end switch */
  559. up(&vicam->sem);
  560.         return ret;
  561. }
  562. static int vicam_v4l_mmap(struct video_device *dev, const char *adr, unsigned long size)
  563. {
  564. struct usb_vicam *vicam = (struct usb_vicam *)dev;
  565. unsigned long start = (unsigned long)adr;
  566. unsigned long page, pos;
  567. down(&vicam->sem);
  568. if (vicam->udev == NULL) {
  569. up(&vicam->sem);
  570. return -EIO;
  571. }
  572. #if 0
  573. if (size > (((VICAM_NUMFRAMES * vicam->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
  574. up(&vicam->sem);
  575. return -EINVAL;
  576. }
  577. #endif
  578. pos = (unsigned long)vicam->fbuf;
  579. while (size > 0) {
  580. page = kvirt_to_pa(pos);
  581. if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
  582. up(&vicam->sem);
  583. return -EAGAIN;
  584. }
  585. start += PAGE_SIZE;
  586. pos += PAGE_SIZE;
  587. if (size > PAGE_SIZE)
  588. size -= PAGE_SIZE;
  589. else
  590. size = 0;
  591. }
  592. up(&vicam->sem);
  593.         return 0;
  594. }
  595. /* FIXME - vicam_v4l_init */
  596. static int vicam_v4l_init(struct video_device *dev)
  597. {
  598. /* stick proc fs stuff in here if wanted */
  599. dbg("vicam_v4l_init");
  600. return 0;
  601. }
  602. /* FIXME - vicam_template - important */
  603. static struct video_device vicam_template = {
  604. name: "vicam USB camera",
  605. type: VID_TYPE_CAPTURE,
  606. hardware: VID_HARDWARE_SE401, /* need to ask for own id */
  607. open: vicam_v4l_open,
  608. close: vicam_v4l_close,
  609. read: vicam_v4l_read,
  610. write: vicam_v4l_write,
  611. ioctl: vicam_v4l_ioctl,
  612. mmap: vicam_v4l_mmap,
  613. initialize: vicam_v4l_init,
  614. };
  615. /******************************************************************************
  616.  *
  617.  *  Some Routines
  618.  *
  619.  ******************************************************************************/
  620. /*
  621. Flash the led
  622. vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
  623. info ("led on");
  624. vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
  625. info ("led off");
  626. vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
  627. vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
  628. */
  629. static void vicam_bulk(struct urb *urb)
  630. {
  631. struct usb_vicam *vicam = urb->context;
  632. /* if (!vicam || !vicam->dev || !vicam->used)
  633. return;
  634. */
  635. if (urb->status)
  636. printk("vicam%d: nonzero read/write bulk status received: %d",
  637. 0, urb->status);
  638. urb->actual_length = 0;
  639. urb->dev = vicam->udev;
  640. memcpy(buf2, buf+64, 0x1e480);
  641. if (vicam->fbuf)
  642. memcpy(vicam->fbuf, buf+64, 0x1e480);
  643. if (!change_pending) {
  644. if (usb_submit_urb(urb))
  645. dbg("failed resubmitting read urb");
  646. } else {
  647. change_pending = 0;
  648. wake_up_interruptible(&vicam->wait);
  649. }
  650. }
  651. static int vicam_parameters(struct usb_vicam *vicam)
  652. {
  653. unsigned char req[0x10];
  654. unsigned int shutter;
  655. shutter = 10;
  656. switch (vicam->win.width) {
  657. case 512:
  658. default:
  659. memcpy(req, s512x242bw, 0x10);
  660. break;
  661. case 256:
  662. memcpy(req, s256x242bw, 0x10);
  663. break;
  664. case 128:
  665. memcpy(req, s128x122bw, 0x10);
  666. break;
  667. }
  668. mdelay(10);
  669. vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
  670. info ("led on");
  671. vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
  672. mdelay(10);
  673. shutter = vicam->win.contrast / 256;
  674. if (shutter == 0)
  675. shutter = 1;
  676. printk("vicam_parameters: brightness %d, shutter %dn", vicam->win.brightness, shutter );
  677. req[0] = vicam->win.brightness /256;
  678. shutter = 15600/shutter - 1;
  679. req[6] = shutter & 0xff;
  680. req[7] = (shutter >> 8) & 0xff;
  681. vicam_sndctrl(1, vicam, VICAM_REQ_CAPTURE, 0x80, req, 0x10);
  682. mdelay(10);
  683. vicam_sndctrl(0, vicam, VICAM_REQ_GET_SOMETHIN, 0, buf, 0x10);
  684. mdelay(10);
  685. return 0;
  686. }
  687. static int vicam_init(struct usb_vicam *vicam)
  688. {
  689. int width[] = {128, 256, 512};
  690. int height[] = {122, 242, 242};
  691. dbg("vicam_init");
  692. buf = kmalloc(0x1e480, GFP_KERNEL);
  693. buf2 = kmalloc(0x1e480, GFP_KERNEL);
  694. if ((!buf) || (!buf2)) {
  695. printk("Not enough memory for vicam!n");
  696. goto error;
  697. }
  698. /* do we do aspect correction in kernel or not? */
  699. vicam->sizes = 3;
  700. vicam->width = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
  701. vicam->height = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
  702. memcpy(vicam->width, &width, sizeof(width));
  703. memcpy(vicam->height, &height, sizeof(height));
  704. vicam->maxframesize = vicam->width[vicam->sizes-1] * vicam->height[vicam->sizes-1];
  705. /* Download firmware to camera */
  706. vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware1, sizeof(firmware1));
  707. vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex1, sizeof(findex1));
  708. vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
  709. vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware2, sizeof(firmware2));
  710. vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex2, sizeof(findex2));
  711. vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
  712. vicam_parameters(vicam);
  713. FILL_BULK_URB(&vicam->readurb, vicam->udev, usb_rcvbulkpipe(vicam->udev, 0x81),
  714.       buf, 0x1e480, vicam_bulk, vicam);
  715. printk("Submiting urb: %dn", usb_submit_urb(&vicam->readurb));
  716. return 0;
  717. error:
  718. if (buf)
  719. kfree(buf);
  720. if (buf2)
  721. kfree(buf2);
  722. return 1;
  723. }
  724. static void * __devinit vicam_probe(struct usb_device *udev, unsigned int ifnum,
  725. const struct usb_device_id *id)
  726. {
  727. struct usb_vicam *vicam;
  728. char *camera_name=NULL;
  729. dbg("vicam_probe");
  730. /* See if the device offered us matches what we can accept */
  731. if ((udev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
  732.     (udev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
  733. return NULL;
  734. }
  735. camera_name="3Com HomeConnect USB";
  736. info("ViCAM camera found: %s", camera_name);
  737. vicam = kmalloc (sizeof(struct usb_vicam), GFP_KERNEL);
  738. if (vicam == NULL) {
  739. err ("couldn't kmalloc vicam struct");
  740. return NULL;
  741. }
  742. memset(vicam, 0, sizeof(*vicam));
  743. vicam->udev = udev;
  744. vicam->camera_name = camera_name;
  745. vicam->win.brightness = 128;
  746. vicam->win.contrast = 10;
  747. /* FIXME */
  748. if (vicam_init(vicam))
  749. return NULL;
  750. memcpy(&vicam->vdev, &vicam_template, sizeof(vicam_template));
  751. memcpy(vicam->vdev.name, vicam->camera_name, strlen(vicam->camera_name));
  752. if (video_register_device(&vicam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
  753. err("video_register_device");
  754. return NULL;
  755. }
  756. info("registered new video device: video%d", vicam->vdev.minor);
  757. init_MUTEX (&vicam->sem);
  758. init_waitqueue_head(&vicam->wait);
  759. return vicam;
  760. }
  761. /* FIXME - vicam_disconnect - important */
  762. static void vicam_disconnect(struct usb_device *udev, void *ptr)
  763. {
  764. struct usb_vicam *vicam;
  765. vicam = (struct usb_vicam *) ptr;
  766. if (!vicam->open_count)
  767. video_unregister_device(&vicam->vdev);
  768. vicam->udev = NULL;
  769. /*
  770. vicam->frame[0].grabstate = FRAME_ERROR;
  771. vicam->frame[1].grabstate = FRAME_ERROR;
  772. */
  773. /* Free buffers and shit */
  774. info("%s disconnected", vicam->camera_name);
  775. synchronize(vicam);
  776. if (!vicam->open_count) {
  777. /* Other random junk */
  778. kfree(vicam);
  779. vicam = NULL;
  780. }
  781. }
  782. /* usb specific object needed to register this driver with the usb subsystem */
  783. static struct usb_driver vicam_driver = {
  784. name: "vicam",
  785. probe: vicam_probe,
  786. disconnect: vicam_disconnect,
  787. id_table: vicam_table,
  788. };
  789. /******************************************************************************
  790.  *
  791.  *  Module Routines
  792.  *
  793.  ******************************************************************************/
  794. MODULE_AUTHOR(DRIVER_AUTHOR);
  795. MODULE_DESCRIPTION(DRIVER_DESC);
  796. MODULE_LICENSE("GPL");
  797. /* Module paramaters */
  798. MODULE_PARM(debug, "i");
  799. MODULE_PARM_DESC(debug, "Debug enabled or not");
  800. static int __init usb_vicam_init(void)
  801. {
  802. int result;
  803. printk("VICAM: initializingn");
  804. /* register this driver with the USB subsystem */
  805. result = usb_register(&vicam_driver);
  806. if (result < 0) {
  807. err("usb_register failed for the "__FILE__" driver. Error number %d",
  808.     result);
  809. return -1;
  810. }
  811. info(DRIVER_VERSION " " DRIVER_AUTHOR);
  812. info(DRIVER_DESC);
  813. return 0;
  814. }
  815. static void __exit usb_vicam_exit(void)
  816. {
  817. /* deregister this driver with the USB subsystem */
  818. usb_deregister(&vicam_driver);
  819. }
  820. module_init(usb_vicam_init);
  821. module_exit(usb_vicam_exit);