vicam.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:23k
- /* -*- linux-c -*-
- * USB ViCAM driver
- *
- * Copyright (c) 2001 Christopher L Cheney (ccheney@cheney.cx)
- * Copyright (c) 2001 Pavel Machek (pavel@suse.cz) sponsored by SuSE
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This driver is for the Vista Imaging ViCAM and 3Com HomeConnect USB
- *
- * Thanks to Greg Kroah-Hartman for the USB Skeleton driver
- *
- * TODO:
- * - find out the ids for the Vista Imaging ViCAM
- *
- * History:
- *
- * 2001_07_07 - 0.1 - christopher: first version
- * 2001_08_28 - 0.2 - pavel: messed it up, but for some fun, try
- while true; do dd if=/dev/video of=/dev/fb0 bs=$[0x1e480] count=1 2> /dev/null; done
- yep, moving pictures.
- * 2001_08_29 - 0.3 - pavel: played a little bit more. Experimental mmap support. For some fun,
- get gqcam-0.9, compile it and run. Better than dd ;-).
- * 2001_08_29 - 0.4 - pavel: added shutter speed control (not much functional)
- kill update_params if it does not seem to work for you.
- * 2001_08_30 - 0.5 - pavel: fixed stupid bug with update_params & vicam_bulk
- *
- * FIXME: It crashes on rmmod with camera plugged.
- */
- #define DEBUG 1
- #include <linux/config.h>
- #include <linux/kernel.h>
- #include <linux/sched.h>
- #include <linux/signal.h>
- #include <linux/errno.h>
- #include <linux/poll.h>
- #include <linux/init.h>
- #include <linux/slab.h>
- #include <linux/fcntl.h>
- #include <linux/module.h>
- #include <linux/spinlock.h>
- #include <linux/list.h>
- #include <linux/smp_lock.h>
- #include <linux/devfs_fs_kernel.h>
- #include <linux/usb.h>
- #include <asm/io.h>
- #include <linux/wrapper.h>
- #include <linux/vmalloc.h>
- #include <linux/videodev.h>
- #include "vicam.h"
- #include "vicamurbs.h"
- /* Version Information */
- #define DRIVER_VERSION "v0"
- #define DRIVER_AUTHOR "Christopher L Cheney <ccheney@cheney.cx>, Pavel Machek <pavel@suse.cz>"
- #define DRIVER_DESC "USB ViCAM Driver"
- /* Define these values to match your device */
- #define USB_VICAM_VENDOR_ID 0x04C1
- #define USB_VICAM_PRODUCT_ID 0x009D
- /* table of devices that work with this driver */
- static struct usb_device_id vicam_table [] = {
- { USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID) },
- { } /* Terminating entry */
- };
- MODULE_DEVICE_TABLE (usb, vicam_table);
- static int video_nr = -1; /* next avail video device */
- static struct usb_driver vicam_driver;
- static char *buf, *buf2;
- static int change_pending = 0;
- static int vicam_parameters(struct usb_vicam *vicam);
- /******************************************************************************
- *
- * Memory management functions
- *
- * Taken from bttv-drivers.c 2.4.7-pre3
- *
- ******************************************************************************/
- /* [DaveM] I've recoded most of this so that:
- * 1) It's easier to tell what is happening
- * 2) It's more portable, especially for translating things
- * out of vmalloc mapped areas in the kernel.
- * 3) Less unnecessary translations happen.
- *
- * The code used to assume that the kernel vmalloc mappings
- * existed in the page tables of every process, this is simply
- * not guarenteed. We now use pgd_offset_k which is the
- * defined way to get at the kernel page tables.
- */
- /* Given PGD from the address space's page table, return the kernel
- * virtual mapping of the physical memory mapped at ADR.
- */
- static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
- {
- unsigned long ret = 0UL;
- pmd_t *pmd;
- pte_t *ptep, pte;
- if (!pgd_none(*pgd)) {
- pmd = pmd_offset(pgd, adr);
- if (!pmd_none(*pmd)) {
- ptep = pte_offset(pmd, adr);
- pte = *ptep;
- if(pte_present(pte)) {
- ret = (unsigned long) page_address(pte_page(pte));
- ret |= (adr & (PAGE_SIZE - 1));
- }
- }
- }
- return ret;
- }
- static inline unsigned long uvirt_to_bus(unsigned long adr)
- {
- unsigned long kva, ret;
- kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
- ret = virt_to_bus((void *)kva);
- return ret;
- }
- static inline unsigned long kvirt_to_bus(unsigned long adr)
- {
- unsigned long va, kva, ret;
- va = VMALLOC_VMADDR(adr);
- kva = uvirt_to_kva(pgd_offset_k(va), va);
- ret = virt_to_bus((void *)kva);
- return ret;
- }
- /* Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved.
- */
- static inline unsigned long kvirt_to_pa(unsigned long adr)
- {
- unsigned long va, kva, ret;
- va = VMALLOC_VMADDR(adr);
- kva = uvirt_to_kva(pgd_offset_k(va), va);
- ret = __pa(kva);
- return ret;
- }
- static void * rvmalloc(signed long size)
- {
- void * mem;
- unsigned long adr, page;
- mem=vmalloc_32(size);
- if (mem)
- {
- memset(mem, 0, size); /* Clear the ram out, no junk to the user */
- adr=(unsigned long) mem;
- while (size > 0)
- {
- page = kvirt_to_pa(adr);
- mem_map_reserve(virt_to_page(__va(page)));
- adr+=PAGE_SIZE;
- size-=PAGE_SIZE;
- }
- }
- return mem;
- }
- static void rvfree(void * mem, signed long size)
- {
- unsigned long adr, page;
- if (mem)
- {
- adr=(unsigned long) mem;
- while (size > 0)
- {
- page = kvirt_to_pa(adr);
- mem_map_unreserve(virt_to_page(__va(page)));
- adr+=PAGE_SIZE;
- size-=PAGE_SIZE;
- }
- vfree(mem);
- }
- }
- /******************************************************************************
- *
- * Foo Bar
- *
- ******************************************************************************/
- /**
- * usb_vicam_debug_data
- */
- static inline void usb_vicam_debug_data (const char *function, int size, const unsigned char *data)
- {
- int i;
- if (!debug)
- return;
- printk (KERN_DEBUG __FILE__": %s - length = %d, data = ",
- function, size);
- for (i = 0; i < size; ++i) {
- printk ("%.2x ", data[i]);
- }
- printk ("n");
- }
- /*****************************************************************************
- *
- * Send command to vicam
- *
- *****************************************************************************/
- static int vicam_sndctrl(int set, struct usb_vicam *vicam, unsigned short req,
- unsigned short value, unsigned char *cp, int size)
- {
- int ret;
- unsigned char *transfer_buffer = kmalloc (size, GFP_KERNEL);
- /* Needs to return data I think, works for sending though */
- memcpy(transfer_buffer, cp, size);
-
- 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);
- kfree(transfer_buffer);
- if (ret)
- printk("vicam: error: %dn", ret);
- mdelay(100);
- return ret;
- }
- /*****************************************************************************
- *
- * Video4Linux Helpers
- *
- *****************************************************************************/
- static int vicam_get_capability(struct usb_vicam *vicam, struct video_capability *b)
- {
- dbg("vicam_get_capability");
- strcpy(b->name, vicam->camera_name);
- b->type = VID_TYPE_CAPTURE | VID_TYPE_MONOCHROME;
- b->channels = 1;
- b->audios = 0;
- b->maxwidth = vicam->width[vicam->sizes-1];
- b->maxheight = vicam->height[vicam->sizes-1];
- b->minwidth = vicam->width[0];
- b->minheight = vicam->height[0];
- return 0;
- }
-
- static int vicam_get_channel(struct usb_vicam *vicam, struct video_channel *v)
- {
- dbg("vicam_get_channel");
- if (v->channel != 0)
- return -EINVAL;
-
- v->flags = 0;
- v->tuners = 0;
- v->type = VIDEO_TYPE_CAMERA;
- strcpy(v->name, "Camera");
- return 0;
- }
-
- static int vicam_set_channel(struct usb_vicam *vicam, struct video_channel *v)
- {
- dbg("vicam_set_channel");
- if (v->channel != 0)
- return -EINVAL;
-
- return 0;
- }
-
- static int vicam_get_mmapbuffer(struct usb_vicam *vicam, struct video_mbuf *vm)
- {
- int i;
- dbg("vicam_get_mmapbuffer");
- memset(vm, 0, sizeof(vm));
- vm->size = VICAM_NUMFRAMES * vicam->maxframesize;
- vm->frames = VICAM_NUMFRAMES;
- for (i=0; i<VICAM_NUMFRAMES; i++)
- vm->offsets[i] = vicam->maxframesize * i;
- return 0;
- }
- static int vicam_get_picture(struct usb_vicam *vicam, struct video_picture *p)
- {
- dbg("vicam_get_picture");
- /* This is probably where that weird 0x56 call goes */
- p->brightness = vicam->win.brightness;
- p->hue = vicam->win.hue;
- p->colour = vicam->win.colour;
- p->contrast = vicam->win.contrast;
- p->whiteness = vicam->win.whiteness;
- p->depth = vicam->win.depth;
- p->palette = vicam->win.palette;
- return 0;
- }
- static void synchronize(struct usb_vicam *vicam)
- {
- change_pending = 1;
- interruptible_sleep_on(&vicam->wait);
- vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
- mdelay(10);
- vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
- mdelay(10);
- }
- static void params_changed(struct usb_vicam *vicam)
- {
- #if 1
- synchronize(vicam);
- mdelay(10);
- vicam_parameters(vicam);
- printk("Submiting urb: %dn", usb_submit_urb(&vicam->readurb));
- #endif
- }
- static int vicam_set_picture(struct usb_vicam *vicam, struct video_picture *p)
- {
- int changed = 0;
- info("vicam_set_picture (%d)", p->brightness);
- #define SET(x)
- if (vicam->win.x != p->x)
- vicam->win.x = p->x, changed = 1;
- SET(brightness);
- SET(hue);
- SET(colour);
- SET(contrast);
- SET(whiteness);
- SET(depth);
- SET(palette);
- if (changed)
- params_changed(vicam);
- return 0;
- /* Investigate what should be done maybe 0x56 type call */
- if (p->depth != 8) return 1;
- if (p->palette != VIDEO_PALETTE_GREY) return 1;
- return 0;
- }
- /* FIXME - vicam_sync_frame - important */
- static int vicam_sync_frame(struct usb_vicam *vicam, int frame)
- {
- dbg("vicam_sync_frame");
- if(frame <0 || frame >= VICAM_NUMFRAMES)
- return -EINVAL;
- /* Probably need to handle various cases */
- /* ret=vicam_newframe(vicam, frame);
- vicam->frame[frame].grabstate=FRAME_UNUSED;
- */
- return 0;
- }
-
- static int vicam_get_window(struct usb_vicam *vicam, struct video_window *vw)
- {
- dbg("vicam_get_window");
- vw->x = 0;
- vw->y = 0;
- vw->chromakey = 0;
- vw->flags = 0;
- vw->clipcount = 0;
- vw->width = vicam->win.width;
- vw->height = vicam->win.height;
- return 0;
- }
- static int vicam_set_window(struct usb_vicam *vicam, struct video_window *vw)
- {
- info("vicam_set_window");
-
- if (vw->flags)
- return -EINVAL;
- if (vw->clipcount)
- return -EINVAL;
- if (vicam->win.width == vw->width && vicam->win.height == vw->height)
- return 0;
- /* Pick largest mode that is smaller than specified res */
- /* If specified res is too small reject */
- /* Add urb send to device... */
- vicam->win.width = vw->width;
- vicam->win.height = vw->height;
- params_changed(vicam);
- return 0;
- }
- /* FIXME - vicam_mmap_capture - important */
- static int vicam_mmap_capture(struct usb_vicam *vicam, struct video_mmap *vm)
- {
- dbg("vicam_mmap_capture");
- /* usbvideo.c looks good for using here */
- /*
- if (vm->frame >= VICAM_NUMFRAMES)
- return -EINVAL;
- if (vicam->frame[vm->frame].grabstate != FRAME_UNUSED)
- return -EBUSY;
- vicam->frame[vm->frame].grabstate=FRAME_READY;
- */
- /* No need to vicam_set_window here according to Alan */
- /*
- if (!vicam->streaming)
- vicam_start_stream(vicam);
- */
- /* set frame as ready */
- return 0;
- }
- /*****************************************************************************
- *
- * Video4Linux
- *
- *****************************************************************************/
- static int vicam_v4l_open(struct video_device *vdev, int flags)
- {
- struct usb_vicam *vicam = (struct usb_vicam *)vdev;
- int err = 0;
-
- dbg("vicam_v4l_open");
- MOD_INC_USE_COUNT;
- down(&vicam->sem);
- if (vicam->open_count) /* Maybe not needed? */
- err = -EBUSY;
- else {
- vicam->fbuf = rvmalloc(vicam->maxframesize * VICAM_NUMFRAMES);
- if (!vicam->fbuf)
- err=-ENOMEM;
- else {
- vicam->open_count = 1;
- }
- #ifdef BLINKING
- vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
- info ("led on");
- vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
- #endif
- }
- up(&vicam->sem);
- if (err)
- MOD_DEC_USE_COUNT;
- return err;
- }
- static void vicam_v4l_close(struct video_device *vdev)
- {
- struct usb_vicam *vicam = (struct usb_vicam *)vdev;
- dbg("vicam_v4l_close");
-
- down(&vicam->sem);
- #ifdef BLINKING
- info ("led off");
- vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
- // vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0); Leave it on
- #endif
- rvfree(vicam->fbuf, vicam->maxframesize * VICAM_NUMFRAMES);
- vicam->fbuf = 0;
- vicam->open_count=0;
- up(&vicam->sem);
- /* Why does se401.c have a usbdevice check here? */
- /* If device is unplugged while open, I guess we only may unregister now */
- MOD_DEC_USE_COUNT;
- }
- static long vicam_v4l_read(struct video_device *vdev, char *user_buf, unsigned long buflen, int noblock)
- {
- //struct usb_vicam *vicam = (struct usb_vicam *)vdev;
- dbg("vicam_v4l_read(%ld)", buflen);
- if (!vdev || !buf)
- return -EFAULT;
- if (copy_to_user(user_buf, buf2, buflen))
- return -EFAULT;
- return buflen;
- }
- static long vicam_v4l_write(struct video_device *dev, const char *buf, unsigned long count, int noblock)
- {
- info("vicam_v4l_write");
- return -EINVAL;
- }
- static int vicam_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
- {
- struct usb_vicam *vicam = (struct usb_vicam *)vdev;
- int ret = -EL3RST;
- if (!vicam->udev)
- return -EIO;
- down(&vicam->sem);
- switch (cmd) {
- case VIDIOCGCAP:
- {
- struct video_capability b;
- ret = vicam_get_capability(vicam,&b);
- dbg("name %s",b.name);
- if (copy_to_user(arg, &b, sizeof(b)))
- ret = -EFAULT;
- }
- case VIDIOCGFBUF:
- {
- struct video_buffer vb;
- info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param");
- /* frame buffer not supported, not used */
- memset(&vb, 0, sizeof(vb));
- vb.base = NULL;
-
- /* FIXME - VIDIOCGFBUF - why the void */
- if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
- ret = -EFAULT;
- ret = 0;
- }
- case VIDIOCGWIN:
- {
- struct video_window vw;
- ret = vicam_get_window(vicam, &vw);
- if (copy_to_user(arg, &vw, sizeof(vw)))
- ret = -EFAULT;
- }
- case VIDIOCSWIN:
- {
- struct video_window vw;
- if (copy_from_user(&vw, arg, sizeof(vw)))
- ret = -EFAULT;
- else
- ret = vicam_set_window(vicam, &vw);
- return ret;
- }
- case VIDIOCGCHAN:
- {
- struct video_channel v;
- if (copy_from_user(&v, arg, sizeof(v)))
- ret = -EFAULT;
- else {
- ret = vicam_get_channel(vicam,&v);
- if (copy_to_user(arg, &v, sizeof(v)))
- ret = -EFAULT;
- }
- }
- case VIDIOCSCHAN:
- {
- struct video_channel v;
- if (copy_from_user(&v, arg, sizeof(v)))
- ret = -EFAULT;
- else
- ret = vicam_set_channel(vicam,&v);
- }
- case VIDIOCGPICT:
- {
- struct video_picture p;
- ret = vicam_get_picture(vicam, &p);
- if (copy_to_user(arg, &p, sizeof(p)))
- ret = -EFAULT;
- }
- case VIDIOCSPICT:
- {
- struct video_picture p;
- if (copy_from_user(&p, arg, sizeof(p)))
- ret = -EFAULT;
- else
- ret = vicam_set_picture(vicam, &p);
- }
- case VIDIOCGMBUF:
- {
- struct video_mbuf vm;
- ret = vicam_get_mmapbuffer(vicam,&vm);
- /* FIXME - VIDIOCGMBUF - why the void */
- if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
- ret = -EFAULT;
- }
- case VIDIOCMCAPTURE:
- {
- struct video_mmap vm;
- ret = vicam_mmap_capture(vicam, &vm);
- /* FIXME: This is probably not right */
- }
- case VIDIOCSYNC:
- {
- int frame;
- /* FIXME - VIDIOCSYNC - why the void */
- if (copy_from_user((void *)&frame, arg, sizeof(int)))
- ret = -EFAULT;
- else
- ret = vicam_sync_frame(vicam,frame);
- }
- case VIDIOCKEY:
- ret = 0;
-
- case VIDIOCCAPTURE:
- case VIDIOCSFBUF:
- case VIDIOCGTUNER:
- case VIDIOCSTUNER:
- case VIDIOCGFREQ:
- case VIDIOCSFREQ:
- case VIDIOCGAUDIO:
- case VIDIOCSAUDIO:
- case VIDIOCGUNIT:
- ret = -EINVAL;
- default:
- {
- info("vicam_v4l_ioctl - %ui",cmd);
- ret = -ENOIOCTLCMD;
- }
- } /* end switch */
- up(&vicam->sem);
- return ret;
- }
- static int vicam_v4l_mmap(struct video_device *dev, const char *adr, unsigned long size)
- {
- struct usb_vicam *vicam = (struct usb_vicam *)dev;
- unsigned long start = (unsigned long)adr;
- unsigned long page, pos;
- down(&vicam->sem);
-
- if (vicam->udev == NULL) {
- up(&vicam->sem);
- return -EIO;
- }
- #if 0
- if (size > (((VICAM_NUMFRAMES * vicam->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
- up(&vicam->sem);
- return -EINVAL;
- }
- #endif
- pos = (unsigned long)vicam->fbuf;
- while (size > 0) {
- page = kvirt_to_pa(pos);
- if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
- up(&vicam->sem);
- return -EAGAIN;
- }
- start += PAGE_SIZE;
- pos += PAGE_SIZE;
- if (size > PAGE_SIZE)
- size -= PAGE_SIZE;
- else
- size = 0;
- }
- up(&vicam->sem);
- return 0;
- }
- /* FIXME - vicam_v4l_init */
- static int vicam_v4l_init(struct video_device *dev)
- {
- /* stick proc fs stuff in here if wanted */
- dbg("vicam_v4l_init");
- return 0;
- }
- /* FIXME - vicam_template - important */
- static struct video_device vicam_template = {
- name: "vicam USB camera",
- type: VID_TYPE_CAPTURE,
- hardware: VID_HARDWARE_SE401, /* need to ask for own id */
- open: vicam_v4l_open,
- close: vicam_v4l_close,
- read: vicam_v4l_read,
- write: vicam_v4l_write,
- ioctl: vicam_v4l_ioctl,
- mmap: vicam_v4l_mmap,
- initialize: vicam_v4l_init,
- };
- /******************************************************************************
- *
- * Some Routines
- *
- ******************************************************************************/
- /*
- Flash the led
- vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
- info ("led on");
- vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
- info ("led off");
- vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
- vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
- */
- static void vicam_bulk(struct urb *urb)
- {
- struct usb_vicam *vicam = urb->context;
- /* if (!vicam || !vicam->dev || !vicam->used)
- return;
- */
- if (urb->status)
- printk("vicam%d: nonzero read/write bulk status received: %d",
- 0, urb->status);
- urb->actual_length = 0;
- urb->dev = vicam->udev;
- memcpy(buf2, buf+64, 0x1e480);
- if (vicam->fbuf)
- memcpy(vicam->fbuf, buf+64, 0x1e480);
- if (!change_pending) {
- if (usb_submit_urb(urb))
- dbg("failed resubmitting read urb");
- } else {
- change_pending = 0;
- wake_up_interruptible(&vicam->wait);
- }
- }
- static int vicam_parameters(struct usb_vicam *vicam)
- {
- unsigned char req[0x10];
- unsigned int shutter;
- shutter = 10;
- switch (vicam->win.width) {
- case 512:
- default:
- memcpy(req, s512x242bw, 0x10);
- break;
- case 256:
- memcpy(req, s256x242bw, 0x10);
- break;
- case 128:
- memcpy(req, s128x122bw, 0x10);
- break;
- }
- mdelay(10);
- vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
- info ("led on");
- vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
- mdelay(10);
- shutter = vicam->win.contrast / 256;
- if (shutter == 0)
- shutter = 1;
- printk("vicam_parameters: brightness %d, shutter %dn", vicam->win.brightness, shutter );
- req[0] = vicam->win.brightness /256;
- shutter = 15600/shutter - 1;
- req[6] = shutter & 0xff;
- req[7] = (shutter >> 8) & 0xff;
- vicam_sndctrl(1, vicam, VICAM_REQ_CAPTURE, 0x80, req, 0x10);
- mdelay(10);
- vicam_sndctrl(0, vicam, VICAM_REQ_GET_SOMETHIN, 0, buf, 0x10);
- mdelay(10);
- return 0;
- }
- static int vicam_init(struct usb_vicam *vicam)
- {
- int width[] = {128, 256, 512};
- int height[] = {122, 242, 242};
- dbg("vicam_init");
- buf = kmalloc(0x1e480, GFP_KERNEL);
- buf2 = kmalloc(0x1e480, GFP_KERNEL);
- if ((!buf) || (!buf2)) {
- printk("Not enough memory for vicam!n");
- goto error;
- }
- /* do we do aspect correction in kernel or not? */
- vicam->sizes = 3;
- vicam->width = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
- vicam->height = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
- memcpy(vicam->width, &width, sizeof(width));
- memcpy(vicam->height, &height, sizeof(height));
- vicam->maxframesize = vicam->width[vicam->sizes-1] * vicam->height[vicam->sizes-1];
- /* Download firmware to camera */
- vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware1, sizeof(firmware1));
- vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex1, sizeof(findex1));
- vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
- vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware2, sizeof(firmware2));
- vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex2, sizeof(findex2));
- vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
- vicam_parameters(vicam);
- FILL_BULK_URB(&vicam->readurb, vicam->udev, usb_rcvbulkpipe(vicam->udev, 0x81),
- buf, 0x1e480, vicam_bulk, vicam);
- printk("Submiting urb: %dn", usb_submit_urb(&vicam->readurb));
- return 0;
- error:
- if (buf)
- kfree(buf);
- if (buf2)
- kfree(buf2);
- return 1;
- }
- static void * __devinit vicam_probe(struct usb_device *udev, unsigned int ifnum,
- const struct usb_device_id *id)
- {
- struct usb_vicam *vicam;
- char *camera_name=NULL;
- dbg("vicam_probe");
- /* See if the device offered us matches what we can accept */
- if ((udev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
- (udev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
- return NULL;
- }
-
- camera_name="3Com HomeConnect USB";
- info("ViCAM camera found: %s", camera_name);
-
- vicam = kmalloc (sizeof(struct usb_vicam), GFP_KERNEL);
- if (vicam == NULL) {
- err ("couldn't kmalloc vicam struct");
- return NULL;
- }
- memset(vicam, 0, sizeof(*vicam));
-
- vicam->udev = udev;
- vicam->camera_name = camera_name;
- vicam->win.brightness = 128;
- vicam->win.contrast = 10;
- /* FIXME */
- if (vicam_init(vicam))
- return NULL;
- memcpy(&vicam->vdev, &vicam_template, sizeof(vicam_template));
- memcpy(vicam->vdev.name, vicam->camera_name, strlen(vicam->camera_name));
-
- if (video_register_device(&vicam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
- err("video_register_device");
- return NULL;
- }
- info("registered new video device: video%d", vicam->vdev.minor);
-
- init_MUTEX (&vicam->sem);
- init_waitqueue_head(&vicam->wait);
-
- return vicam;
- }
- /* FIXME - vicam_disconnect - important */
- static void vicam_disconnect(struct usb_device *udev, void *ptr)
- {
- struct usb_vicam *vicam;
- vicam = (struct usb_vicam *) ptr;
- if (!vicam->open_count)
- video_unregister_device(&vicam->vdev);
- vicam->udev = NULL;
- /*
- vicam->frame[0].grabstate = FRAME_ERROR;
- vicam->frame[1].grabstate = FRAME_ERROR;
- */
- /* Free buffers and shit */
- info("%s disconnected", vicam->camera_name);
- synchronize(vicam);
- if (!vicam->open_count) {
- /* Other random junk */
- kfree(vicam);
- vicam = NULL;
- }
- }
- /* usb specific object needed to register this driver with the usb subsystem */
- static struct usb_driver vicam_driver = {
- name: "vicam",
- probe: vicam_probe,
- disconnect: vicam_disconnect,
- id_table: vicam_table,
- };
- /******************************************************************************
- *
- * Module Routines
- *
- ******************************************************************************/
- MODULE_AUTHOR(DRIVER_AUTHOR);
- MODULE_DESCRIPTION(DRIVER_DESC);
- MODULE_LICENSE("GPL");
- /* Module paramaters */
- MODULE_PARM(debug, "i");
- MODULE_PARM_DESC(debug, "Debug enabled or not");
- static int __init usb_vicam_init(void)
- {
- int result;
- printk("VICAM: initializingn");
- /* register this driver with the USB subsystem */
- result = usb_register(&vicam_driver);
- if (result < 0) {
- err("usb_register failed for the "__FILE__" driver. Error number %d",
- result);
- return -1;
- }
- info(DRIVER_VERSION " " DRIVER_AUTHOR);
- info(DRIVER_DESC);
- return 0;
- }
- static void __exit usb_vicam_exit(void)
- {
- /* deregister this driver with the USB subsystem */
- usb_deregister(&vicam_driver);
- }
- module_init(usb_vicam_init);
- module_exit(usb_vicam_exit);