dc2xx.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:14k
- /*
- * Copyright (C) 1999-2000 by David Brownell <dbrownell@users.sourceforge.net>
- *
- * 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 program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
- /*
- * USB driver for Kodak DC-2XX series digital still cameras
- *
- * The protocol here is the same as the one going over a serial line, but
- * it uses USB for speed. Set up /dev/kodak, get gphoto (www.gphoto.org),
- * and have fun!
- *
- * This should also work for a number of other digital (non-Kodak) cameras,
- * by adding the vendor and product IDs to the table below. They'll need
- * to be the sort using USB just as a fast bulk data channel.
- */
- /*
- * HISTORY
- *
- * 26 August, 1999 -- first release (0.1), works with my DC-240.
- * The DC-280 (2Mpixel) should also work, but isn't tested.
- * If you use gphoto, make sure you have the USB updates.
- * Lives in a 2.3.14 or so Linux kernel, in drivers/usb.
- * 31 August, 1999 -- minor update to recognize DC-260 and handle
- * its endpoints being in a different order. Note that as
- * of gPhoto 0.36pre, the USB updates are integrated.
- * 12 Oct, 1999 -- handle DC-280 interface class (0xff not 0x0);
- * added timeouts to bulk_msg calls. Minor updates, docs.
- * 03 Nov, 1999 -- update for 2.3.25 kernel API changes.
- * 08 Jan, 2000 .. multiple camera support
- * 12 Aug, 2000 .. add some real locking, remove an Oops
- * 10 Oct, 2000 .. usb_device_id table created.
- * 01 Nov, 2000 .. usb_device_id support added by Adam J. Richter
- * 08 Apr, 2001 .. Identify version on module load. gb
- *
- * Thanks to: the folk who've provided USB product IDs, sent in
- * patches, and shared their successes!
- */
- #include <linux/config.h>
- #include <linux/kernel.h>
- #include <linux/sched.h>
- #include <linux/signal.h>
- #include <linux/errno.h>
- #include <linux/miscdevice.h>
- #include <linux/random.h>
- #include <linux/poll.h>
- #include <linux/init.h>
- #include <linux/slab.h>
- #include <linux/module.h>
- #include <linux/devfs_fs_kernel.h>
- #ifdef CONFIG_USB_DEBUG
- #define DEBUG
- #else
- #undef DEBUG
- #endif
- #include <linux/usb.h>
- /* /dev/usb dir. */
- extern devfs_handle_t usb_devfs_handle;
- /*
- * Version Information
- */
- #define DRIVER_VERSION "v1.0.0"
- #define DRIVER_AUTHOR "David Brownell, <dbrownell@users.sourceforge.net>"
- #define DRIVER_DESC "USB Camera Driver for Kodak DC-2xx series cameras"
- /* current USB framework handles max of 16 USB devices per driver */
- #define MAX_CAMERAS 16
- /* USB char devs use USB_MAJOR and from USB_CAMERA_MINOR_BASE up */
- #define USB_CAMERA_MINOR_BASE 80
- // XXX remove packet size limit, now that bulk transfers seem fixed
- /* Application protocol limit is 0x8002; USB has disliked that limit! */
- #define MAX_PACKET_SIZE 0x2000 /* e.g. image downloading */
- #define MAX_READ_RETRY 5 /* times to retry reads */
- #define MAX_WRITE_RETRY 5 /* times to retry writes */
- #define RETRY_TIMEOUT (HZ) /* sleep between retries */
- /* table of cameras that work through this driver */
- static struct usb_device_id camera_table [] = {
- /* These have the same application level protocol */
- { USB_DEVICE(0x040a, 0x0120) }, // Kodak DC-240
- { USB_DEVICE(0x040a, 0x0130) }, // Kodak DC-280
- { USB_DEVICE(0x040a, 0x0131) }, // Kodak DC-5000
- { USB_DEVICE(0x040a, 0x0132) }, // Kodak DC-3400
- /* These have a different application level protocol which
- * is part of the Flashpoint "DigitaOS". That supports some
- * non-camera devices, and some non-Kodak cameras.
- * Use this driver to get USB and "OpenDis" to talk.
- */
- { USB_DEVICE(0x040a, 0x0100) }, // Kodak DC-220
- { USB_DEVICE(0x040a, 0x0110) }, // Kodak DC-260
- { USB_DEVICE(0x040a, 0x0111) }, // Kodak DC-265
- { USB_DEVICE(0x040a, 0x0112) }, // Kodak DC-290
- { USB_DEVICE(0xf003, 0x6002) }, // HP PhotoSmart C500
- { USB_DEVICE(0x03f0, 0x4102) }, // HP PhotoSmart C618
- { USB_DEVICE(0x0a17, 0x1001) }, // Pentax EI-200
- /* Other USB devices may well work here too, so long as they
- * just stick to half duplex bulk packet exchanges. That
- * means, among other things, no iso or interrupt endpoints.
- */
- { } /* Terminating entry */
- };
- MODULE_DEVICE_TABLE (usb, camera_table);
- struct camera_state {
- struct usb_device *dev; /* USB device handle */
- int inEP; /* read endpoint */
- int outEP; /* write endpoint */
- const struct usb_device_id *info; /* DC-240, etc */
- int subminor; /* which minor dev #? */
- struct semaphore sem; /* locks this struct */
- /* this is non-null iff the device is open */
- char *buf; /* buffer for I/O */
- devfs_handle_t devfs; /* devfs device */
- /* always valid */
- wait_queue_head_t wait; /* for timed waits */
- };
- /* Support multiple cameras, possibly of different types. */
- static struct camera_state *minor_data [MAX_CAMERAS];
- /* make this an rwlock if contention becomes an issue */
- static DECLARE_MUTEX (state_table_mutex);
- static ssize_t camera_read (struct file *file,
- char *buf, size_t len, loff_t *ppos)
- {
- struct camera_state *camera;
- int retries;
- int retval = 0;
- if (len > MAX_PACKET_SIZE)
- return -EINVAL;
- camera = (struct camera_state *) file->private_data;
- down (&camera->sem);
- if (!camera->dev) {
- up (&camera->sem);
- return -ENODEV;
- }
- /* Big reads are common, for image downloading. Smaller ones
- * are also common (even "directory listing" commands don't
- * send very much data). We preserve packet boundaries here,
- * they matter in the application protocol.
- */
- for (retries = 0; retries < MAX_READ_RETRY; retries++) {
- int count;
- if (signal_pending (current)) {
- retval = -EINTR;
- break;
- }
- retval = usb_bulk_msg (camera->dev,
- usb_rcvbulkpipe (camera->dev, camera->inEP),
- camera->buf, len, &count, HZ*10);
- dbg ("read (%Zd) - 0x%x %d", len, retval, count);
- if (!retval) {
- if (copy_to_user (buf, camera->buf, count))
- retval = -EFAULT;
- else
- retval = count;
- break;
- }
- if (retval != USB_ST_TIMEOUT)
- break;
- interruptible_sleep_on_timeout (&camera->wait, RETRY_TIMEOUT);
- dbg ("read (%Zd) - retry", len);
- }
- up (&camera->sem);
- return retval;
- }
- static ssize_t camera_write (struct file *file,
- const char *buf, size_t len, loff_t *ppos)
- {
- struct camera_state *camera;
- ssize_t bytes_written = 0;
- if (len > MAX_PACKET_SIZE)
- return -EINVAL;
- camera = (struct camera_state *) file->private_data;
- down (&camera->sem);
- if (!camera->dev) {
- up (&camera->sem);
- return -ENODEV;
- }
-
- /* most writes will be small: simple commands, sometimes with
- * parameters. putting images (like borders) into the camera
- * would be the main use of big writes.
- */
- while (len > 0) {
- char *obuf = camera->buf;
- int maxretry = MAX_WRITE_RETRY;
- unsigned long copy_size, thistime;
- /* it's not clear that retrying can do any good ... or that
- * fragmenting application packets into N writes is correct.
- */
- thistime = copy_size = len;
- if (copy_from_user (obuf, buf, copy_size)) {
- bytes_written = -EFAULT;
- break;
- }
- while (thistime) {
- int result;
- int count;
- if (signal_pending (current)) {
- if (!bytes_written)
- bytes_written = -EINTR;
- goto done;
- }
- result = usb_bulk_msg (camera->dev,
- usb_sndbulkpipe (camera->dev, camera->outEP),
- obuf, thistime, &count, HZ*10);
- if (result)
- dbg ("write USB err - %d", result);
- if (count) {
- obuf += count;
- thistime -= count;
- maxretry = MAX_WRITE_RETRY;
- continue;
- } else if (!result)
- break;
-
- if (result == USB_ST_TIMEOUT) { /* NAK - delay a bit */
- if (!maxretry--) {
- if (!bytes_written)
- bytes_written = -ETIME;
- goto done;
- }
- interruptible_sleep_on_timeout (&camera->wait,
- RETRY_TIMEOUT);
- continue;
- }
- if (!bytes_written)
- bytes_written = -EIO;
- goto done;
- }
- bytes_written += copy_size;
- len -= copy_size;
- buf += copy_size;
- }
- done:
- up (&camera->sem);
- dbg ("wrote %Zd", bytes_written);
- return bytes_written;
- }
- static int camera_open (struct inode *inode, struct file *file)
- {
- struct camera_state *camera = NULL;
- int subminor;
- int value = 0;
- down (&state_table_mutex);
- subminor = MINOR (inode->i_rdev) - USB_CAMERA_MINOR_BASE;
- if (subminor < 0 || subminor >= MAX_CAMERAS
- || !(camera = minor_data [subminor])) {
- up (&state_table_mutex);
- return -ENODEV;
- }
- down (&camera->sem);
- up (&state_table_mutex);
- if (camera->buf) {
- value = -EBUSY;
- goto done;
- }
- if (!(camera->buf = (char *) kmalloc (MAX_PACKET_SIZE, GFP_KERNEL))) {
- value = -ENOMEM;
- goto done;
- }
- dbg ("open #%d", subminor);
- file->private_data = camera;
- done:
- up (&camera->sem);
- return value;
- }
- static int camera_release (struct inode *inode, struct file *file)
- {
- struct camera_state *camera;
- int subminor;
- camera = (struct camera_state *) file->private_data;
- down (&state_table_mutex);
- down (&camera->sem);
- if (camera->buf) {
- kfree (camera->buf);
- camera->buf = 0;
- }
- subminor = camera->subminor;
- /* If camera was unplugged with open file ... */
- if (!camera->dev) {
- minor_data [subminor] = NULL;
- kfree (camera);
- } else
- up (&camera->sem);
-
- up (&state_table_mutex);
- dbg ("close #%d", subminor);
- return 0;
- }
- /* XXX should define some ioctls to expose camera type
- * to applications ... what USB exposes should suffice.
- * apps should be able to see the camera type.
- */
- static /* const */ struct file_operations usb_camera_fops = {
- /* Uses GCC initializer extension; simpler to maintain */
- owner: THIS_MODULE,
- read: camera_read,
- write: camera_write,
- open: camera_open,
- release: camera_release,
- };
- static void *
- camera_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *camera_info)
- {
- int i;
- struct usb_interface_descriptor *interface;
- struct usb_endpoint_descriptor *endpoint;
- int direction, ep;
- char name[8];
- struct camera_state *camera = NULL;
- /* these have one config, one interface */
- if (dev->descriptor.bNumConfigurations != 1
- || dev->config[0].bNumInterfaces != 1) {
- dbg ("Bogus camera config info");
- return NULL;
- }
- /* models differ in how they report themselves */
- interface = &dev->actconfig->interface[ifnum].altsetting[0];
- if ((interface->bInterfaceClass != USB_CLASS_PER_INTERFACE
- && interface->bInterfaceClass != USB_CLASS_VENDOR_SPEC)
- || interface->bInterfaceSubClass != 0
- || interface->bInterfaceProtocol != 0
- || interface->bNumEndpoints != 2
- ) {
- dbg ("Bogus camera interface info");
- return NULL;
- }
- /* select "subminor" number (part of a minor number) */
- down (&state_table_mutex);
- for (i = 0; i < MAX_CAMERAS; i++) {
- if (!minor_data [i])
- break;
- }
- if (i >= MAX_CAMERAS) {
- info ("Ignoring additional USB Camera");
- goto bye;
- }
- /* allocate & init camera state */
- camera = minor_data [i] = kmalloc (sizeof *camera, GFP_KERNEL);
- if (!camera) {
- err ("no memory!");
- goto bye;
- }
- init_MUTEX (&camera->sem);
- camera->info = camera_info;
- camera->subminor = i;
- camera->buf = NULL;
- init_waitqueue_head (&camera->wait);
- /* get input and output endpoints (either order) */
- endpoint = interface->endpoint;
- camera->outEP = camera->inEP = -1;
- ep = endpoint [0].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
- direction = endpoint [0].bEndpointAddress & USB_ENDPOINT_DIR_MASK;
- if (direction == USB_DIR_IN)
- camera->inEP = ep;
- else
- camera->outEP = ep;
- ep = endpoint [1].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
- direction = endpoint [1].bEndpointAddress & USB_ENDPOINT_DIR_MASK;
- if (direction == USB_DIR_IN)
- camera->inEP = ep;
- else
- camera->outEP = ep;
- if (camera->outEP == -1 || camera->inEP == -1
- || endpoint [0].bmAttributes != USB_ENDPOINT_XFER_BULK
- || endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK
- ) {
- dbg ("Bogus endpoints");
- goto error;
- }
- info ("USB Camera #%d connected, major/minor %d/%d", camera->subminor,
- USB_MAJOR, USB_CAMERA_MINOR_BASE + camera->subminor);
- camera->dev = dev;
- usb_inc_dev_use (dev);
- /* If we have devfs, register the device */
- sprintf(name, "dc2xx%d", camera->subminor);
- camera->devfs = devfs_register(usb_devfs_handle, name,
- DEVFS_FL_DEFAULT, USB_MAJOR,
- USB_CAMERA_MINOR_BASE + camera->subminor,
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
- S_IWGRP, &usb_camera_fops, NULL);
- goto bye;
- error:
- minor_data [camera->subminor] = NULL;
- kfree (camera);
- camera = NULL;
- bye:
- up (&state_table_mutex);
- return camera;
- }
- static void camera_disconnect(struct usb_device *dev, void *ptr)
- {
- struct camera_state *camera = (struct camera_state *) ptr;
- int subminor = camera->subminor;
- down (&state_table_mutex);
- down (&camera->sem);
- devfs_unregister(camera->devfs);
- /* If camera's not opened, we can clean up right away.
- * Else apps see a disconnect on next I/O; the release cleans.
- */
- if (!camera->buf) {
- minor_data [subminor] = NULL;
- kfree (camera);
- camera = NULL;
- } else
- camera->dev = NULL;
- info ("USB Camera #%d disconnected", subminor);
- usb_dec_dev_use (dev);
- if (camera != NULL)
- up (&camera->sem);
- up (&state_table_mutex);
- }
- static /* const */ struct usb_driver camera_driver = {
- name: "dc2xx",
- id_table: camera_table,
- probe: camera_probe,
- disconnect: camera_disconnect,
- fops: &usb_camera_fops,
- minor: USB_CAMERA_MINOR_BASE
- };
- int __init usb_dc2xx_init(void)
- {
- if (usb_register (&camera_driver) < 0)
- return -1;
- info(DRIVER_VERSION ":" DRIVER_DESC);
- return 0;
- }
- void __exit usb_dc2xx_cleanup(void)
- {
- usb_deregister (&camera_driver);
- }
- module_init (usb_dc2xx_init);
- module_exit (usb_dc2xx_cleanup);
- MODULE_AUTHOR( DRIVER_AUTHOR );
- MODULE_DESCRIPTION( DRIVER_DESC );
- MODULE_LICENSE("GPL");