| /* |
| * 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 != -ETIMEDOUT) |
| 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 == -ETIMEDOUT) { /* 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"); |
| |