Commit a0fe3373 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

USB - removed the dc2xx driver

parent ca433637
14 April 2000
david-b@pacbell.net
This is an overview of how to use the "dc2xx" USB driver with certain
digital still cameras from Kodak and other vendors.
CAMERAS
This driver will mostly be used with Kodak DC-2xx series digital still
cameras, but it should be trivial to tell it about several non-Kodak
USB-enabled cameras.
You'll most likely want to hook it up to recent versions of "gPhoto"
(www.gphoto.org), since version 0.4 and later know how to use it to talk
to Kodak DC-240 and DC-280 cameras over USB.
In addition the DC-220, DC-260, DC-265, and DC-290 are also recognized.
However, like other cameras using the "Digita OS" (from www.flashpoint.com)
there is no gPhoto support for this camera. There is a python script
for accessing these cameras (see archives of the linux-usb mailing list)
and a "Digita Services" library that can also use this driver.
The HP PhotoSmart C500 should also work, since it's another Digita camera
with USB support.
USB HARDWARE
Recent kernels have had no particular problems using this driver with
either OHCI or UHCI chipsets, and have worked on the PowerMac platform.
Note that in some cases changes in BIOS settings may be needed before
your USB works. At least one user has reported a need for SMP-related
settings as well, and some old hardware may not handle USB correctly.
SETUP
Configure in the DC2XX USB driver, and have it in your kernel. It works
as a module, or compiled in directly.
Create at least one device, perhaps like this (both read and write):
# mknod -m 0660 /dev/usb/dc2xx0 c 180 80
# mknod -m 0660 /dev/usb/dc2xx1 c 180 81
...
NOTE: you would normally configure PAM so that the user logged in at
the console is granted ownership of these devices. console.perms(5)
explains how to do this.
The driver supports multiple device nodes. The USB framework supports
a maximum of sixteen device nodes (up to minor device number 96).
When you plug in one camera, it will use the first device node (dc2xx0
in the example above). A second camera will use the second device node,
and so on.
SANITY TESTING
First: if you've got /proc support, make sure that the driver has hooked
itself up correctly.
- You should see an entry in /proc/bus/usb/drivers for "dc2xx",
if you enabled USB /proc support and correctly mounted the
usbdevfs on /proc/bus/usb.
Second: when you connect your camera to the computer, does it get recognized
by the driver? (Make sure the camera is powered on!)
- if you've got /proc/bus/usb/devices, you should see an entry
something like this. The "ProdID" may be different if you didn't
plug in a DC-240, as may the strings presented, but "Driver=dc2xx"
had better be there.
T: Lev=01 Prnt=00 Port=00 Cnt=01 Dev#= 1 Spd=12 MxCh= 0
D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=040a ProdID=0120 Rev= 1.08
S: Manufacturer=Eastman Kodak Company
S: Product=KODAK DC240 Zoom Digital Camera
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 2 Cls=00(>ifc ) Sub=00 Prot=00 Driver=dc2xx
E: Ad=01(O) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
- see if "dmesg" output tells you that you plugged in your camera.
Manufacturer: Eastman Kodak Company
Product: KODAK DC240 Zoom Digital Camera
dc2xx.c: USB Camera #0 connected
Third: (optional) can you use gPhoto to talk to the camera?
- When you configure your camera, tell it to use "/dev/usb/dc2xx0"
(or whatever name you used). Right now, gPhoto emits a diagnostic
message (non-GUI) saying that it since it didn't act like a TTY,
it's assuming it's got a USB connection.
- With the camera turned on, get the "camera summary". It'll
talk to the camera -- and tell you you're using USB.
If you got that far, you should be able to use everything fine.
ADDITIONAL INFORMATION
You may find that you need more driver-specific information, which is
currently accessible through a link from http://www.linux-usb.org/
along with other Linux USB resources.
CONFIG_USB_DC2XX
Say Y here if you want to connect this type of still camera to your
computer's USB port. See <file:Documentation/usb/dc2xx.txt> for
more information; some non-Kodak cameras may also work with this
driver, given application support (such as <http://www.gphoto.org/>).
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called dc2xx.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_MDC800 CONFIG_USB_MDC800
Say Y here if you want to connect this type of still camera to Say Y here if you want to connect this type of still camera to
your computer's USB port. This driver can be used with gphoto 0.4.3 your computer's USB port. This driver can be used with gphoto 0.4.3
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
# USB Imageing devices configuration # USB Imageing devices configuration
# #
comment 'USB Imaging devices' comment 'USB Imaging devices'
dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB $CONFIG_EXPERIMENTAL dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB $CONFIG_EXPERIMENTAL
dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
dep_tristate ' Microtek X6USB scanner support' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI dep_tristate ' Microtek X6USB scanner support' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI
...@@ -10,10 +9,10 @@ dep_tristate ' HP53xx USB scanner support (EXPERIMENTAL)' CONFIG_USB_HPUSBSCSI ...@@ -10,10 +9,10 @@ dep_tristate ' HP53xx USB scanner support (EXPERIMENTAL)' CONFIG_USB_HPUSBSCSI
# Turn on CONFIG_USB_IMAGE if any of the drivers are compiled into the kernel to # Turn on CONFIG_USB_IMAGE if any of the drivers are compiled into the kernel to
# make our Makefile logic a bit simpler # make our Makefile logic a bit simpler
if [ "$CONFIG_USB_DC2XX" = "y" -o "$CONFIG_USB_MDC800" = "y" ]; then if [ "$CONFIG_USB_MDC800" = "y" -o "$CONFIG_USB_SCANNER" = "y" ]; then
define_bool CONFIG_USB_IMAGE y define_bool CONFIG_USB_IMAGE y
fi fi
if [ "$CONFIG_USB_SCANNER" = "y" -o "$CONFIG_USB_MICROTEK" = "y" -o "$CONFIG_USB_HPUSBSCSI" = "y" ]; then if [ "$CONFIG_USB_MICROTEK" = "y" -o "$CONFIG_USB_HPUSBSCSI" = "y" ]; then
define_bool CONFIG_USB_IMAGE y define_bool CONFIG_USB_IMAGE y
fi fi
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
O_TARGET := usb-image.o O_TARGET := usb-image.o
obj-$(CONFIG_USB_DC2XX) += dc2xx.o
obj-$(CONFIG_USB_MDC800) += mdc800.o obj-$(CONFIG_USB_MDC800) += mdc800.o
obj-$(CONFIG_USB_HPUSBSCSI) += hpusbscsi.o obj-$(CONFIG_USB_HPUSBSCSI) += hpusbscsi.o
obj-$(CONFIG_USB_MICROTEK) += microtek.o obj-$(CONFIG_USB_MICROTEK) += microtek.o
......
/*
* 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");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment