Commit f4e1c439 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://linuxusb.bkbits.net/linus-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents c4c88b92 868cac6d
......@@ -33,12 +33,6 @@ if [ "$CONFIG_USB" = "y" -o "$CONFIG_USB" = "m" ]; then
source drivers/usb/serial/Config.in
comment 'USB Miscellaneous drivers'
dep_tristate ' EMI 2|6 USB Audio interface support' CONFIG_USB_EMI26 $CONFIG_USB_AUDIO
dep_tristate ' Texas Instruments Graph Link USB (aka SilverLink) cable support' CONFIG_USB_TIGL $CONFIG_USB
dep_tristate ' USB Auerswald ISDN support (EXPERIMENTAL)' CONFIG_USB_AUERSWALD $CONFIG_USB $CONFIG_EXPERIMENTAL
dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL
dep_tristate ' Tieman Voyager USB Braille display support (EXPERIMENTAL)' CONFIG_USB_BRLVGER $CONFIG_USB $CONFIG_EXPERIMENTAL
source drivers/usb/misc/Config.in
fi
endmenu
......@@ -57,7 +57,9 @@ obj-$(CONFIG_USB_SERIAL) += serial/
obj-$(CONFIG_USB_AUERSWALD) += misc/
obj-$(CONFIG_USB_BRLVGER) += misc/
obj-$(CONFIG_USB_EMI26) += misc/
obj-$(CONFIG_USB_LCD) += misc/
obj-$(CONFIG_USB_RIO500) += misc/
obj-$(CONFIG_USB_SPEEDTOUCH) += misc/
obj-$(CONFIG_USB_TIGL) += misc/
obj-$(CONFIG_USB_USS720) += misc/
......
......@@ -7,7 +7,7 @@ obj-$(CONFIG_USB_ACM) += cdc-acm.o
obj-$(CONFIG_USB_AUDIO) += audio.o
obj-$(CONFIG_USB_BLUETOOTH_TTY) += bluetty.o
obj-$(CONFIG_USB_MIDI) += usb-midi.o
obj-$(CONFIG_USB_PRINTER) += printer.o
obj-$(CONFIG_USB_PRINTER) += usblp.o
include $(TOPDIR)/Rules.make
/*
* printer.c Version 0.12
* usblp.c Version 0.12
*
* Copyright (c) 1999 Michael Gee <michael@linuxspecific.com>
* Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
......
......@@ -289,7 +289,7 @@ static int rh_string (
// language ids
if (id == 0) {
*data++ = 4; *data++ = 3; /* 4 bytes string data */
*data++ = 0; *data++ = 0; /* some language id */
*data++ = 0x09; *data++ = 0x04; /* MSFT-speak for "en-us" */
return 4;
// serial number
......@@ -585,9 +585,7 @@ void usb_bus_init (struct usb_bus *bus)
{
memset (&bus->devmap, 0, sizeof(struct usb_devmap));
#ifdef DEVNUM_ROUND_ROBIN
bus->devnum_next = 1;
#endif /* DEVNUM_ROUND_ROBIN */
bus->root_hub = NULL;
bus->hcpriv = NULL;
......@@ -738,10 +736,10 @@ EXPORT_SYMBOL (usb_register_root_hub);
/*-------------------------------------------------------------------------*/
/**
* usb_calc_bus_time: approximate periodic transaction time in nanoseconds
* usb_calc_bus_time - approximate periodic transaction time in nanoseconds
* @speed: from dev->speed; USB_SPEED_{LOW,FULL,HIGH}
* @is_input: true iff the transaction sends data to the host
* @is_isoc: true for isochronous transactions, false for interrupt ones
* @isoc: true for isochronous transactions, false for interrupt ones
* @bytecount: how many bytes in the transaction.
*
* Returns approximate bus time in nanoseconds for a periodic transaction.
......@@ -1286,8 +1284,8 @@ EXPORT_SYMBOL (usb_hcd_operations);
* This hands the URB from HCD to its USB device driver, using its
* completion function. The HCD has freed all per-urb resources
* (and is done using urb->hcpriv). It also released all HCD locks;
* the device driver won't cause deadlocks if it resubmits this URB,
* and won't confuse things by modifying and resubmitting this one.
* the device driver won't cause problems if it frees, modifies,
* or resubmits this URB.
* Bandwidth and other resources will be deallocated.
*
* HCDs must not use this for periodic URBs that are still scheduled
......
......@@ -19,6 +19,31 @@
#ifdef __KERNEL__
/* This file contains declarations of usbcore internals that are mostly
* used or exposed by Host Controller Drivers.
*/
/*
* USB Packet IDs (PIDs)
*/
#define USB_PID_UNDEF_0 0xf0
#define USB_PID_OUT 0xe1
#define USB_PID_ACK 0xd2
#define USB_PID_DATA0 0xc3
#define USB_PID_PING 0xb4 /* USB 2.0 */
#define USB_PID_SOF 0xa5
#define USB_PID_NYET 0x96 /* USB 2.0 */
#define USB_PID_DATA2 0x87 /* USB 2.0 */
#define USB_PID_SPLIT 0x78 /* USB 2.0 */
#define USB_PID_IN 0x69
#define USB_PID_NAK 0x5a
#define USB_PID_DATA1 0x4b
#define USB_PID_PREAMBLE 0x3c /* Token mode */
#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */
#define USB_PID_SETUP 0x2d
#define USB_PID_STALL 0x1e
#define USB_PID_MDATA 0x0f /* USB 2.0 */
/*-------------------------------------------------------------------------*/
/*
......@@ -234,13 +259,11 @@ extern int usb_new_device(struct usb_device *dev);
extern void usb_connect(struct usb_device *dev);
extern void usb_disconnect(struct usb_device **);
#ifndef _LINUX_HUB_H
/* exported to hub driver ONLY to support usb_reset_device () */
extern int usb_get_configuration(struct usb_device *dev);
extern void usb_set_maxpacket(struct usb_device *dev);
extern void usb_destroy_configuration(struct usb_device *dev);
extern int usb_set_address(struct usb_device *dev);
#endif /* _LINUX_HUB_H */
/*-------------------------------------------------------------------------*/
......@@ -354,10 +377,48 @@ extern struct usb_interface *usb_ifnum_to_if (struct usb_device *dev,
extern int usb_find_interface_driver (struct usb_device *dev,
struct usb_interface *interface);
#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN))
/* for probe/disconnect with correct module usage counting */
void *usb_bind_driver(struct usb_driver *driver, struct usb_interface *intf);
void usb_unbind_driver(struct usb_device *device, struct usb_interface *intf);
extern struct list_head usb_driver_list;
/*
* USB device fs stuff
*/
#ifdef CONFIG_USB_DEVICEFS
/*
* these are expected to be called from the USB core/hub thread
* with the kernel lock held
*/
extern void usbfs_add_bus(struct usb_bus *bus);
extern void usbfs_remove_bus(struct usb_bus *bus);
extern void usbfs_add_device(struct usb_device *dev);
extern void usbfs_remove_device(struct usb_device *dev);
extern void usbfs_update_special (void);
extern int usbfs_init(void);
extern void usbfs_cleanup(void);
#else /* CONFIG_USB_DEVICEFS */
static inline void usbfs_add_bus(struct usb_bus *bus) {}
static inline void usbfs_remove_bus(struct usb_bus *bus) {}
static inline void usbfs_add_device(struct usb_device *dev) {}
static inline void usbfs_remove_device(struct usb_device *dev) {}
static inline void usbfs_update_special (void) {}
static inline int usbfs_init(void) { return 0; }
static inline void usbfs_cleanup(void) { }
#endif /* CONFIG_USB_DEVICEFS */
/*-------------------------------------------------------------------------*/
/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
......
......@@ -261,9 +261,8 @@ static int usb_hub_configure(struct usb_hub *hub,
{
struct usb_device *dev = hub->dev;
struct usb_hub_status hubstatus;
char portstr[USB_MAXCHILDREN + 1];
unsigned int pipe;
int i, maxp, ret;
int maxp, ret;
hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
if (!hub->descriptor) {
......@@ -294,9 +293,17 @@ static int usb_hub_configure(struct usb_hub *hub,
le16_to_cpus(&hub->descriptor->wHubCharacteristics);
if (hub->descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND)
dbg("part of a compound device");
else
if (hub->descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND) {
int i;
char portstr [USB_MAXCHILDREN + 1];
for (i = 0; i < dev->maxchild; i++)
portstr[i] = hub->descriptor->DeviceRemovable
[((i + 1) / 8)] & (1 << ((i + 1) % 8))
? 'F' : 'R';
portstr[dev->maxchild] = 0;
dbg("compound device; port removable status: %s", portstr);
} else
dbg("standalone hub");
switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) {
......@@ -371,14 +378,6 @@ static int usb_hub_configure(struct usb_hub *hub,
dbg("hub controller current requirement: %dmA",
hub->descriptor->bHubContrCurrent);
for (i = 0; i < dev->maxchild; i++)
portstr[i] = hub->descriptor->DeviceRemovable
[((i + 1) / 8)] & (1 << ((i + 1) % 8))
? 'F' : 'R';
portstr[dev->maxchild] = 0;
dbg("port removable status: %s", portstr);
ret = usb_get_hub_status(dev, &hubstatus);
if (ret < 0) {
err("Unable to get hub status (err = %d)", ret);
......
......@@ -88,15 +88,17 @@ struct urb * usb_get_urb(struct urb *urb)
/*-------------------------------------------------------------------*/
/**
* usb_submit_urb - asynchronously issue a transfer request for an endpoint
* usb_submit_urb - issue an asynchronous transfer request for an endpoint
* @urb: pointer to the urb describing the request
* @mem_flags: the type of memory to allocate, see kmalloc() for a list
* of valid options for this.
*
* This submits a transfer request, and transfers control of the URB
* describing that request to the USB subsystem. Request completion will
* indicated later, asynchronously, by calling the completion handler.
* This call may be issued in interrupt context.
* be indicated later, asynchronously, by calling the completion handler.
* The three types of completion are success, error, and unlink
* (also called "request cancellation").
* URBs may be submitted in interrupt context.
*
* The caller must have correctly initialized the URB before submitting
* it. Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are
......@@ -148,20 +150,19 @@ struct urb * usb_get_urb(struct urb *urb)
*
* Memory Flags:
*
* General rules for how to decide which mem_flags to use:
*
* Basically the rules are the same as for kmalloc. There are four
* The general rules for how to decide which mem_flags to use
* are the same as for kmalloc. There are four
* different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and
* GFP_ATOMIC.
*
* GFP_NOFS is not ever used, as it has not been implemented yet.
*
* There are three situations you must use GFP_ATOMIC.
* a) you are inside a completion handler, an interrupt, bottom half,
* tasklet or timer.
* b) you are holding a spinlock or rwlock (does not apply to
* semaphores)
* c) current->state != TASK_RUNNING, this is the case only after
* GFP_ATOMIC is used when
* (a) you are inside a completion handler, an interrupt, bottom half,
* tasklet or timer, or
* (b) you are holding a spinlock or rwlock (does not apply to
* semaphores), or
* (c) current->state != TASK_RUNNING, this is the case only after
* you've changed it.
*
* GFP_NOIO is used in the block io path and error handling of storage
......@@ -169,17 +170,17 @@ struct urb * usb_get_urb(struct urb *urb)
*
* All other situations use GFP_KERNEL.
*
* Specfic rules for how to decide which mem_flags to use:
*
* - start_xmit, timeout, and receive methods of network drivers must
* use GFP_ATOMIC (spinlock)
* - queuecommand methods of scsi drivers must use GFP_ATOMIC (spinlock)
* - If you use a kernel thread with a network driver you must use
* GFP_NOIO, unless b) or c) apply
* - After you have done a down() you use GFP_KERNEL, unless b) or c)
* apply or your are in a storage driver's block io path
* - probe and disconnect use GFP_KERNEL unless b) or c) apply
* - Changing firmware on a running storage or net device uses
* Some more specific rules for mem_flags can be inferred, such as
* (1) start_xmit, timeout, and receive methods of network drivers must
* use GFP_ATOMIC (they are called with a spinlock held);
* (2) queuecommand methods of scsi drivers must use GFP_ATOMIC (also
* called with a spinlock held);
* (3) If you use a kernel thread with a network driver you must use
* GFP_NOIO, unless (b) or (c) apply;
* (4) after you have done a down() you can use GFP_KERNEL, unless (b) or (c)
* apply or your are in a storage driver's block io path;
* (5) USB probe and disconnect can use GFP_KERNEL unless (b) or (c) apply; and
* (6) changing firmware on a running storage or net device uses
* GFP_NOIO, unless b) or c) apply
*
*/
......
......@@ -1057,56 +1057,6 @@ int usb_get_current_frame_number(struct usb_device *dev)
}
/*-------------------------------------------------------------------*/
/* for returning string descriptors in UTF-16LE */
static int ascii2utf (char *ascii, __u8 *utf, int utfmax)
{
int retval;
for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) {
*utf++ = *ascii++ & 0x7f;
*utf++ = 0;
}
return retval;
}
/*
* root_hub_string is used by each host controller's root hub code,
* so that they're identified consistently throughout the system.
*/
int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len)
{
char buf [30];
// assert (len > (2 * (sizeof (buf) + 1)));
// assert (strlen (type) <= 8);
// language ids
if (id == 0) {
*data++ = 4; *data++ = 3; /* 4 bytes data */
*data++ = 0; *data++ = 0; /* some language id */
return 4;
// serial number
} else if (id == 1) {
sprintf (buf, "%x", serial);
// product description
} else if (id == 2) {
sprintf (buf, "USB %s Root Hub", type);
// id 3 == vendor description
// unsupported IDs --> "stall"
} else
return 0;
data [0] = 2 + ascii2utf (buf, data + 2, len - 2);
data [1] = 3;
return data [0];
}
/*
* __usb_get_extra_descriptor() finds a descriptor of specific type in the
* extra field of the interface and endpoint descriptor structs.
......@@ -1221,16 +1171,13 @@ void usb_connect(struct usb_device *dev)
* won't have seen this, but not so for reinit ...
*/
dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */
#ifndef DEVNUM_ROUND_ROBIN
devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1);
#else /* round_robin alloc of devnums */
/* Try to allocate the next devnum beginning at bus->devnum_next. */
devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, dev->bus->devnum_next);
if (devnum >= 128)
devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1);
dev->bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
#endif /* round_robin alloc of devnums */
if (devnum < 128) {
set_bit(devnum, dev->bus->devmap.devicemap);
......@@ -1649,7 +1596,6 @@ EXPORT_SYMBOL(usb_interface_claimed);
EXPORT_SYMBOL(usb_driver_release_interface);
EXPORT_SYMBOL(usb_match_id);
EXPORT_SYMBOL(usb_root_hub_string);
EXPORT_SYMBOL(usb_new_device);
EXPORT_SYMBOL(usb_reset_device);
EXPORT_SYMBOL(usb_connect);
......
......@@ -21,6 +21,8 @@
*
*-------------------------------------------------------------------------*/
/* FIXME: reuse the root hub framework in usbcore, shrinking this code. */
#ifdef DEBUG
#undef DEBUG
#endif
......@@ -229,6 +231,52 @@ static int rh_init_int_timer (struct urb * urb)
/*-------------------------------------------------------------------------*/
/* for returning string descriptors in UTF-16LE */
static int ascii2utf (char *ascii, __u8 *utf, int utfmax)
{
int retval;
for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) {
*utf++ = *ascii++ & 0x7f;
*utf++ = 0;
}
return retval;
}
static int root_hub_string (int id, int serial, char *type, __u8 *data, int len)
{
char buf [30];
// assert (len > (2 * (sizeof (buf) + 1)));
// assert (strlen (type) <= 8);
// language ids
if (id == 0) {
*data++ = 4; *data++ = 3; /* 4 bytes data */
*data++ = 0; *data++ = 0; /* some language id */
return 4;
// serial number
} else if (id == 1) {
sprintf (buf, "%x", serial);
// product description
} else if (id == 2) {
sprintf (buf, "USB %s Root Hub", type);
// id 3 == vendor description
// unsupported IDs --> "stall"
} else
return 0;
data [0] = 2 + ascii2utf (buf, data + 2, len - 2);
data [1] = 3;
return data [0];
}
/*-------------------------------------------------------------------------*/
/* helper macro */
#define OK(x) len = (x); break
......@@ -409,7 +457,7 @@ static int rh_submit_urb (struct urb * urb)
OK (len);
case (0x03): /* string descriptors */
len = usb_root_hub_string (wValue & 0xff, (int) (long) 0,
len = root_hub_string (wValue & 0xff, (int) (long) 0,
"SL811HS", data, wLength);
if (len > 0) {
data_buf = data;
......
......@@ -4,6 +4,9 @@
#include <linux/list.h>
#include <linux/usb.h>
#define usb_packetid(pipe) (usb_pipein(pipe) ? USB_PID_IN : USB_PID_OUT)
#define PIPE_DEVEP_MASK 0x0007ff00
/*
* Universal Host Controller Interface data structures and defines
*/
......
......@@ -115,6 +115,7 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x03f0, 0x0101) }, /* 4100C */
{ USB_DEVICE(0x03f0, 0x0105) }, /* 4200C */
{ USB_DEVICE(0x03f0, 0x0305) }, /* 4300C */
{ USB_DEVICE(0x03f0, 0x0705) }, /* 4400C */
{ USB_DEVICE(0x03f0, 0x0102) }, /* PhotoSmart S20 */
{ USB_DEVICE(0x03f0, 0x0401) }, /* 5200C */
// { USB_DEVICE(0x03f0, 0x0701) }, /* 5300C - NOT SUPPORTED - see http://www.neatech.nl/oss/HP5300C/ */
......@@ -187,8 +188,12 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x04b8, 0x010b) }, /* Perfection 1240U */
{ USB_DEVICE(0x04b8, 0x010c) }, /* Perfection 640U */
{ USB_DEVICE(0x04b8, 0x010e) }, /* Expression 1680 */
{ USB_DEVICE(0x04a9, 0x2204) }, /* FB630U */
{ USB_DEVICE(0x04b8, 0x0110) }, /* Perfection 1650 */
{ USB_DEVICE(0x04b8, 0x0112) }, /* Perfection 2450 - GT-9700 for the Japanese mkt */
{ USB_DEVICE(0x04b8, 0x0114) }, /* Perfection 660 */
{ USB_DEVICE(0x04b8, 0x011b) }, /* Perfection 2400 Photo */
{ USB_DEVICE(0x04b8, 0x011e) }, /* Perfection 1660 Photo */
/* Umax */
{ USB_DEVICE(0x1606, 0x0010) }, /* Astra 1220U */
{ USB_DEVICE(0x1606, 0x0030) }, /* Astra 2000U */
......
This diff is collapsed.
This diff is collapsed.
......@@ -103,7 +103,7 @@ MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)
* 02-Nov-2000 First (mostly dummy) version.
* 06-Nov-2000 Rewrote to dump all data into frame.
*/
void ultracam_ProcessIsocData(uvd_t *uvd, usbvideo_frame_t *frame)
void ultracam_ProcessIsocData(struct uvd *uvd, usbvideo_frame_t *frame)
{
int n;
......@@ -140,7 +140,7 @@ void ultracam_ProcessIsocData(uvd_t *uvd, usbvideo_frame_t *frame)
* 1/27/00 Added check for dev == NULL; this happens if camera is unplugged.
*/
static int ultracam_veio(
uvd_t *uvd,
struct uvd *uvd,
unsigned char req,
unsigned short value,
unsigned short index,
......@@ -193,7 +193,7 @@ static int ultracam_veio(
/*
* ultracam_calculate_fps()
*/
static int ultracam_calculate_fps(uvd_t *uvd)
static int ultracam_calculate_fps(struct uvd *uvd)
{
return 3 + framerate*4 + framerate/2;
}
......@@ -201,14 +201,14 @@ static int ultracam_calculate_fps(uvd_t *uvd)
/*
* ultracam_adjust_contrast()
*/
static void ultracam_adjust_contrast(uvd_t *uvd)
static void ultracam_adjust_contrast(struct uvd *uvd)
{
}
/*
* ultracam_change_lighting_conditions()
*/
static void ultracam_change_lighting_conditions(uvd_t *uvd)
static void ultracam_change_lighting_conditions(struct uvd *uvd)
{
}
......@@ -219,7 +219,7 @@ static void ultracam_change_lighting_conditions(uvd_t *uvd)
* range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess).
* Recommended value is 4. Cameras model 2 do not have this feature at all.
*/
static void ultracam_set_sharpness(uvd_t *uvd)
static void ultracam_set_sharpness(struct uvd *uvd)
{
}
......@@ -228,11 +228,11 @@ static void ultracam_set_sharpness(uvd_t *uvd)
*
* This procedure changes brightness of the picture.
*/
static void ultracam_set_brightness(uvd_t *uvd)
static void ultracam_set_brightness(struct uvd *uvd)
{
}
static void ultracam_set_hue(uvd_t *uvd)
static void ultracam_set_hue(struct uvd *uvd)
{
}
......@@ -242,7 +242,7 @@ static void ultracam_set_hue(uvd_t *uvd)
* This procedure gets called from V4L interface to update picture settings.
* Here we change brightness and contrast.
*/
static void ultracam_adjust_picture(uvd_t *uvd)
static void ultracam_adjust_picture(struct uvd *uvd)
{
ultracam_adjust_contrast(uvd);
ultracam_set_brightness(uvd);
......@@ -255,7 +255,7 @@ static void ultracam_adjust_picture(uvd_t *uvd)
* This code tells camera to stop streaming. The interface remains
* configured and bandwidth - claimed.
*/
static void ultracam_video_stop(uvd_t *uvd)
static void ultracam_video_stop(struct uvd *uvd)
{
}
......@@ -266,24 +266,24 @@ static void ultracam_video_stop(uvd_t *uvd)
* resets the video pipe. This sequence was observed to reinit the
* camera or, at least, to initiate ISO data stream.
*/
static void ultracam_reinit_iso(uvd_t *uvd, int do_stop)
static void ultracam_reinit_iso(struct uvd *uvd, int do_stop)
{
}
static void ultracam_video_start(uvd_t *uvd)
static void ultracam_video_start(struct uvd *uvd)
{
ultracam_change_lighting_conditions(uvd);
ultracam_set_sharpness(uvd);
ultracam_reinit_iso(uvd, 0);
}
static int ultracam_resetPipe(uvd_t *uvd)
static int ultracam_resetPipe(struct uvd *uvd)
{
usb_clear_halt(uvd->dev, uvd->video_endp);
return 0;
}
static int ultracam_alternateSetting(uvd_t *uvd, int setting)
static int ultracam_alternateSetting(struct uvd *uvd, int setting)
{
static const char proc[] = "ultracam_alternateSetting";
int i;
......@@ -299,7 +299,7 @@ static int ultracam_alternateSetting(uvd_t *uvd, int setting)
/*
* Return negative code on failure, 0 on success.
*/
static int ultracam_setup_on_open(uvd_t *uvd)
static int ultracam_setup_on_open(struct uvd *uvd)
{
int setup_ok = 0; /* Success by default */
/* Send init sequence only once, it's large! */
......@@ -487,7 +487,7 @@ static int ultracam_setup_on_open(uvd_t *uvd)
return setup_ok;
}
static void ultracam_configure_video(uvd_t *uvd)
static void ultracam_configure_video(struct uvd *uvd)
{
if (uvd == NULL)
return;
......@@ -539,7 +539,7 @@ static void ultracam_configure_video(uvd_t *uvd)
*/
static void *ultracam_probe(struct usb_device *dev, unsigned int ifnum ,const struct usb_device_id *devid)
{
uvd_t *uvd = NULL;
struct uvd *uvd = NULL;
int i, nas;
int actInterface=-1, inactInterface=-1, maxPS=0;
unsigned char video_ep = 0;
......@@ -628,7 +628,7 @@ static void *ultracam_probe(struct usb_device *dev, unsigned int ifnum ,const st
MOD_INC_USE_COUNT;
uvd = usbvideo_AllocateDevice(cams);
if (uvd != NULL) {
/* Here uvd is a fully allocated uvd_t object */
/* Here uvd is a fully allocated uvd object */
uvd->flags = flags;
uvd->debug = debug;
uvd->dev = dev;
......
This diff is collapsed.
......@@ -113,9 +113,10 @@ typedef unsigned long videosize_t;
mr = LIMIT_RGB(mm_r); \
}
#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) % (rq)->length
#define RING_QUEUE_SIZE (128*1024) /* Must be a power of 2 */
#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) & ((rq)->length-1)
#define RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n)
#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) % (rq)->length])
#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) & ((rq)->length-1)])
typedef struct {
unsigned char *queue; /* Data from the Isoc data pump */
......@@ -202,7 +203,7 @@ typedef struct {
struct s_usbvideo_t;
typedef struct {
struct uvd {
struct video_device vdev; /* Must be the first field! */
struct usb_device *dev;
struct s_usbvideo_t *handle; /* Points back to the usbvideo_t */
......@@ -247,7 +248,7 @@ typedef struct {
usbvideo_statistics_t stats;
struct proc_dir_entry *procfs_vEntry; /* /proc/video/MYDRIVER/video2 */
char videoName[32]; /* Holds name like "video7" */
} uvd_t;
};
/*
* usbvideo callbacks (virtual methods). They are set when usbvideo
......@@ -256,21 +257,22 @@ typedef struct {
*/
typedef struct {
void *(*probe)(struct usb_device *, unsigned int,const struct usb_device_id *);
void (*userFree)(uvd_t *);
void (*userFree)(struct uvd *);
void (*disconnect)(struct usb_device *, void *);
int (*setupOnOpen)(uvd_t *);
void (*videoStart)(uvd_t *);
void (*videoStop)(uvd_t *);
void (*processData)(uvd_t *, usbvideo_frame_t *);
void (*postProcess)(uvd_t *, usbvideo_frame_t *);
void (*adjustPicture)(uvd_t *);
int (*getFPS)(uvd_t *);
int (*overlayHook)(uvd_t *, usbvideo_frame_t *);
int (*getFrame)(uvd_t *, int);
int (*setupOnOpen)(struct uvd *);
void (*videoStart)(struct uvd *);
void (*videoStop)(struct uvd *);
void (*processData)(struct uvd *, usbvideo_frame_t *);
void (*postProcess)(struct uvd *, usbvideo_frame_t *);
void (*adjustPicture)(struct uvd *);
int (*getFPS)(struct uvd *);
int (*overlayHook)(struct uvd *, usbvideo_frame_t *);
int (*getFrame)(struct uvd *, int);
int (*procfs_read)(char *page,char **start,off_t off,int count,int *eof,void *data);
int (*procfs_write)(struct file *file,const char *buffer,unsigned long count,void *data);
int (*startDataPump)(uvd_t *uvd);
void (*stopDataPump)(uvd_t *uvd);
int (*startDataPump)(struct uvd *uvd);
void (*stopDataPump)(struct uvd *uvd);
int (*setVideoMode)(struct uvd *uvd, struct video_window *vw);
} usbvideo_cb_t;
struct s_usbvideo_t {
......@@ -280,7 +282,7 @@ struct s_usbvideo_t {
struct semaphore lock; /* Mutex protecting camera structures */
usbvideo_cb_t cb; /* Table of callbacks (virtual methods) */
struct video_device vdt; /* Video device template */
uvd_t *cam; /* Array of camera structures */
struct uvd *cam; /* Array of camera structures */
int uses_procfs; /* Non-zero if we create /proc entries */
struct proc_dir_entry *procfs_dEntry; /* /proc/video/MYDRIVER */
struct module *md_module; /* Minidriver module */
......@@ -288,7 +290,7 @@ struct s_usbvideo_t {
typedef struct s_usbvideo_t usbvideo_t;
/*
* This macro retrieves callback address from the uvd_t object.
* This macro retrieves callback address from the struct uvd object.
* No validity checks are done here, so be sure to check the
* callback beforehand with VALID_CALLBACK.
*/
......@@ -306,8 +308,18 @@ typedef struct s_usbvideo_t usbvideo_t;
int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len);
int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n);
int RingQueue_GetLength(const RingQueue_t *rq);
void RingQueue_WakeUpInterruptible(RingQueue_t *rq);
void RingQueue_Flush(RingQueue_t *rq);
static inline int RingQueue_GetLength(const RingQueue_t *rq)
{
return (rq->wi - rq->ri + rq->length) & (rq->length-1);
}
static inline int RingQueue_GetFreeSpace(const RingQueue_t *rq)
{
return rq->length - RingQueue_GetLength(rq);
}
void usbvideo_DrawLine(
usbvideo_frame_t *frame,
......@@ -316,7 +328,7 @@ void usbvideo_DrawLine(
unsigned char cr, unsigned char cg, unsigned char cb);
void usbvideo_HexDump(const unsigned char *data, int len);
void usbvideo_SayAndWait(const char *what);
void usbvideo_TestPattern(uvd_t *uvd, int fullframe, int pmode);
void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode);
/* Memory allocation routines */
unsigned long usbvideo_kvirt_to_pa(unsigned long adr);
......@@ -329,13 +341,13 @@ int usbvideo_register(
const usbvideo_cb_t *cbTable,
struct module *md,
const struct usb_device_id *id_table);
uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams);
int usbvideo_RegisterVideoDevice(uvd_t *uvd);
struct uvd *usbvideo_AllocateDevice(usbvideo_t *cams);
int usbvideo_RegisterVideoDevice(struct uvd *uvd);
void usbvideo_Deregister(usbvideo_t **uvt);
int usbvideo_v4l_initialize(struct video_device *dev);
void usbvideo_DeinterlaceFrame(uvd_t *uvd, usbvideo_frame_t *frame);
void usbvideo_DeinterlaceFrame(struct uvd *uvd, usbvideo_frame_t *frame);
/*
* This code performs bounds checking - use it when working with
......
......@@ -84,3 +84,31 @@ CONFIG_USB_USS720
inserted in and removed from the running kernel whenever you want).
The module will be called uss720.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_SPEEDTCH
This driver provides support for the Alcatel SpeedTouch ADSL USB
modem.
The driver requires the ATM interface and ATM SAR so you need to
enable ATM (under Networking options) and the ATM SAR option. You
will also need PPP over ATM (under Network device support).
This driver is a slightly revised version of Johan Verrept's 1.5
SpeedTouch Driver which has been altered to work on the 2.5 series
kernels.
To use the device you also need a user-mode daemon that downloads
the firmware and (re)initializes the modem. The offical version is
a closed source one from Alcatel that you can get at
<http://www.alcateldsl.com/support.htm>.
A piece of code has recently been sent to linux-usb-devel which
allows the open source user space driver's firmware program
modem_run to be used with this driver instead. You will still
need the Alcatel daemon package to extract the modem firmware from
it (or the windows drivers instead).
For more information, see Johan Verrept's webpages at
<http://linux-usb.sourceforge.net/SpeedTouch/>.
#
# USB Miscellaneous driver configuration
#
comment 'USB Miscellaneous drivers'
dep_tristate ' EMI 2|6 USB Audio interface support' CONFIG_USB_EMI26 $CONFIG_USB_AUDIO
dep_tristate ' Texas Instruments Graph Link USB (aka SilverLink) cable support' CONFIG_USB_TIGL $CONFIG_USB
dep_tristate ' USB Auerswald ISDN support (EXPERIMENTAL)' CONFIG_USB_AUERSWALD $CONFIG_USB $CONFIG_EXPERIMENTAL
dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL
dep_tristate ' Tieman Voyager USB Braille display support (EXPERIMENTAL)' CONFIG_USB_BRLVGER $CONFIG_USB $CONFIG_EXPERIMENTAL
dep_tristate ' USB LCD driver support' CONFIG_USB_LCD $CONFIG_USB
dep_tristate ' Alcatel Speedtouch ADSL USB Modem' CONFIG_USB_SPEEDTOUCH $CONFIG_USB
......@@ -3,10 +3,14 @@
# (the ones that don't fit into any other categories)
#
export-objs := atmsar.o
obj-$(CONFIG_USB_AUERSWALD) += auerswald.o
obj-$(CONFIG_USB_BRLVGER) += brlvger.o
obj-$(CONFIG_USB_EMI26) += emi26.o
obj-$(CONFIG_USB_LCD) += usblcd.o
obj-$(CONFIG_USB_RIO500) += rio500.o
obj-$(CONFIG_USB_SPEEDTOUCH) += speedtouch.o atmsar.o
obj-$(CONFIG_USB_TIGL) += tiglusb.o
obj-$(CONFIG_USB_USS720) += uss720.o
......
This diff is collapsed.
/*
*
* General SAR library for ATM devices.
*
* Copyright (c) 2000, Johan Verrept
*
* This code falls under the GNU General Public License, see COPYING for details.
*
*/
#ifndef _ATMSAR_H_
#define _ATMSAR_H_
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <linux/atmdev.h>
#include <linux/skbuff.h>
#include <linux/types.h>
#include <linux/atm.h>
#define ATMSAR_USE_53BYTE_CELL 0x1L
#define ATMSAR_SET_PTI 0x2L
/* types */
#define ATMSAR_TYPE_AAL0 ATM_AAL0
#define ATMSAR_TYPE_AAL1 ATM_AAL1
#define ATMSAR_TYPE_AAL2 ATM_AAL2
#define ATMSAR_TYPE_AAL34 ATM_AAL34
#define ATMSAR_TYPE_AAL5 ATM_AAL5
/* default MTU's */
#define ATMSAR_DEF_MTU_AAL0 48
#define ATMSAR_DEF_MTU_AAL1 47
#define ATMSAR_DEF_MTU_AAL2 0 /* not supported */
#define ATMSAR_DEF_MTU_AAL34 0 /* not supported */
#define ATMSAR_DEF_MTU_AAL5 65535 /* max mtu .. */
struct atmsar_vcc_data {
struct atmsar_vcc_data *next;
/* general atmsar flags, per connection */
int flags;
int type;
/* connection specific non-atmsar data */
struct sk_buff *(*alloc_tx) (struct atm_vcc * vcc, unsigned int size);
struct atm_vcc *vcc;
struct k_atm_aal_stats *stats;
unsigned short mtu; /* max is actually 65k for AAL5... */
/* cell data */
unsigned int vp;
unsigned int vc;
unsigned char gfc;
unsigned char pti;
unsigned int headerFlags;
unsigned long atmHeader;
/* raw cell reassembly */
struct sk_buff *reasBuffer;
};
extern struct atmsar_vcc_data *atmsar_open (struct atmsar_vcc_data **list, struct atm_vcc *vcc,
uint type, ushort vpi, ushort vci, unchar pti,
unchar gfc, uint flags);
extern void atmsar_close (struct atmsar_vcc_data **list, struct atmsar_vcc_data *vcc);
extern struct sk_buff *atmsar_encode_rawcell (struct atmsar_vcc_data *ctx, struct sk_buff *skb);
extern struct sk_buff *atmsar_encode_aal5 (struct atmsar_vcc_data *ctx, struct sk_buff *skb);
struct sk_buff *atmsar_decode_rawcell (struct atmsar_vcc_data *list, struct sk_buff *skb,
struct atmsar_vcc_data **ctx);
struct sk_buff *atmsar_decode_aal5 (struct atmsar_vcc_data *ctx, struct sk_buff *skb);
struct sk_buff *atmsar_alloc_tx (struct atmsar_vcc_data *vcc, unsigned int size);
#endif /* _ATMSAR_H_ */
This diff is collapsed.
/*****************************************************************************
* USBLCD Kernel Driver *
* See http://www.usblcd.de for Hardware and Documentation. *
* Version 1.01 *
* (C) 2002 Adams IT Services <info@usblcd.de> *
* *
* This file is licensed under the GPL. See COPYING in the package. *
* Based on rio500.c by Cesar Miquel (miquel@df.uba.ar) which is based on *
* hp_scanner.c by David E. Nelson (dnelson@jump.net) *
* *
* 23.7.02 RA changed minor device number to the official assigned one *
*****************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
#define DRIVER_VERSION "USBLCD Driver Version 1.01"
#define USBLCD_MINOR 144
#define IOCTL_GET_HARD_VERSION 1
#define IOCTL_GET_DRV_VERSION 2
/* stall/wait timeout for USBLCD */
#define NAK_TIMEOUT (HZ)
#define IBUF_SIZE 0x1000
#define OBUF_SIZE 0x10000
struct lcd_usb_data {
struct usb_device *lcd_dev; /* init: probe_lcd */
unsigned int ifnum; /* Interface number of the USB device */
int minor; /* minor number for this device */
int isopen; /* nz if open */
int present; /* Device is present on the bus */
char *obuf, *ibuf; /* transfer buffers */
char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */
wait_queue_head_t wait_q; /* for timeouts */
};
static struct lcd_usb_data lcd_instance;
static int open_lcd(struct inode *inode, struct file *file)
{
struct lcd_usb_data *lcd = &lcd_instance;
if (lcd->isopen || !lcd->present) {
return -EBUSY;
}
lcd->isopen = 1;
init_waitqueue_head(&lcd->wait_q);
info("USBLCD opened.");
return 0;
}
static int close_lcd(struct inode *inode, struct file *file)
{
struct lcd_usb_data *lcd = &lcd_instance;
lcd->isopen = 0;
info("USBLCD closed.");
return 0;
}
static int
ioctl_lcd(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
struct lcd_usb_data *lcd = &lcd_instance;
int i;
char buf[30];
/* Sanity check to make sure lcd is connected, powered, etc */
if (lcd == NULL ||
lcd->present == 0 ||
lcd->lcd_dev == NULL)
return -1;
switch (cmd) {
case IOCTL_GET_HARD_VERSION:
i = (lcd->lcd_dev)->descriptor.bcdDevice;
sprintf(buf,"%1d%1d.%1d%1d",(i & 0xF000)>>12,(i & 0xF00)>>8,
(i & 0xF0)>>4,(i & 0xF));
if (copy_to_user((void *)arg,buf,strlen(buf))!=0)
return -EFAULT;
break;
case IOCTL_GET_DRV_VERSION:
sprintf(buf,DRIVER_VERSION);
if (copy_to_user((void *)arg,buf,strlen(buf))!=0)
return -EFAULT;
break;
default:
return -ENOIOCTLCMD;
break;
}
return 0;
}
static ssize_t
write_lcd(struct file *file, const char *buffer,
size_t count, loff_t * ppos)
{
struct lcd_usb_data *lcd = &lcd_instance;
unsigned long copy_size;
unsigned long bytes_written = 0;
unsigned int partial;
int result = 0;
int maxretry;
/* Sanity check to make sure lcd is connected, powered, etc */
if (lcd == NULL ||
lcd->present == 0 ||
lcd->lcd_dev == NULL)
return -1;
do {
unsigned long thistime;
char *obuf = lcd->obuf;
thistime = copy_size =
(count >= OBUF_SIZE) ? OBUF_SIZE : count;
if (copy_from_user(lcd->obuf, buffer, copy_size))
return -EFAULT;
maxretry = 5;
while (thistime) {
if (!lcd->lcd_dev)
return -ENODEV;
if (signal_pending(current)) {
return bytes_written ? bytes_written : -EINTR;
}
result = usb_bulk_msg(lcd->lcd_dev,
usb_sndbulkpipe(lcd->lcd_dev, 1),
obuf, thistime, &partial, 10 * HZ);
dbg("write stats: result:%d thistime:%lu partial:%u",
result, thistime, partial);
if (result == -ETIMEDOUT) { /* NAK - so hold for a while */
if (!maxretry--) {
return -ETIME;
}
interruptible_sleep_on_timeout(&lcd-> wait_q, NAK_TIMEOUT);
continue;
} else if (!result & partial) {
obuf += partial;
thistime -= partial;
} else
break;
};
if (result) {
err("Write Whoops - %x", result);
return -EIO;
}
bytes_written += copy_size;
count -= copy_size;
buffer += copy_size;
} while (count > 0);
return bytes_written ? bytes_written : -EIO;
}
static ssize_t
read_lcd(struct file *file, char *buffer, size_t count, loff_t * ppos)
{
struct lcd_usb_data *lcd = &lcd_instance;
ssize_t read_count;
unsigned int partial;
int this_read;
int result;
int maxretry = 10;
char *ibuf = lcd->ibuf;
/* Sanity check to make sure lcd is connected, powered, etc */
if (lcd == NULL ||
lcd->present == 0 ||
lcd->lcd_dev == NULL)
return -1;
read_count = 0;
while (count > 0) {
if (signal_pending(current)) {
return read_count ? read_count : -EINTR;
}
if (!lcd->lcd_dev)
return -ENODEV;
this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
result = usb_bulk_msg(lcd->lcd_dev,
usb_rcvbulkpipe(lcd->lcd_dev, 0),
ibuf, this_read, &partial,
(int) (HZ * 8));
dbg(KERN_DEBUG "read stats: result:%d this_read:%u partial:%u",
result, this_read, partial);
if (partial) {
count = this_read = partial;
} else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */
if (!maxretry--) {
err("read_lcd: maxretry timeout");
return -ETIME;
}
interruptible_sleep_on_timeout(&lcd->wait_q,
NAK_TIMEOUT);
continue;
} else if (result != -EREMOTEIO) {
err("Read Whoops - result:%u partial:%u this_read:%u",
result, partial, this_read);
return -EIO;
} else {
return (0);
}
if (this_read) {
if (copy_to_user(buffer, ibuf, this_read))
return -EFAULT;
count -= this_read;
read_count += this_read;
buffer += this_read;
}
}
return read_count;
}
static struct
file_operations usb_lcd_fops = {
.owner = THIS_MODULE,
.read = read_lcd,
.write = write_lcd,
.ioctl = ioctl_lcd,
.open = open_lcd,
.release = close_lcd,
};
static void *probe_lcd(struct usb_device *dev, unsigned int ifnum)
{
struct lcd_usb_data *lcd = &lcd_instance;
int i;
int retval;
if (dev->descriptor.idProduct != 0x0001 ) {
warn(KERN_INFO "USBLCD model not supported.");
return NULL;
}
if (lcd->present == 1) {
warn(KERN_INFO "Multiple USBLCDs are not supported!");
return NULL;
}
i = dev->descriptor.bcdDevice;
info("USBLCD Version %1d%1d.%1d%1d found at address %d",
(i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF),
dev->devnum);
retval = usb_register_dev(&usb_lcd_fops, USBLCD_MINOR, 1, &lcd->minor);
if (retval) {
err("Not able to get a minor for this device.");
return NULL;
}
lcd->present = 1;
lcd->lcd_dev = dev;
if (!(lcd->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
err("probe_lcd: Not enough memory for the output buffer");
return NULL;
}
dbg("probe_lcd: obuf address:%p", lcd->obuf);
if (!(lcd->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) {
err("probe_lcd: Not enough memory for the input buffer");
kfree(lcd->obuf);
return NULL;
}
dbg("probe_lcd: ibuf address:%p", lcd->ibuf);
return lcd;
}
static void disconnect_lcd(struct usb_device *dev, void *ptr)
{
struct lcd_usb_data *lcd = (struct lcd_usb_data *) ptr;
usb_deregister_dev(1, lcd->minor);
if (lcd->isopen) {
lcd->isopen = 0;
/* better let it finish - the release will do whats needed */
lcd->lcd_dev = NULL;
return;
}
kfree(lcd->ibuf);
kfree(lcd->obuf);
info("USBLCD disconnected.");
lcd->present = 0;
}
static struct usb_device_id id_table [] = {
{ .idVendor = 0x1212, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, },
{},
};
MODULE_DEVICE_TABLE (usb, id_table);
static struct
usb_driver lcd_driver = {
.name = "usblcd",
.probe = (void *)probe_lcd,
.disconnect = disconnect_lcd,
.id_table = id_table,
};
int usb_lcd_init(void)
{
if (usb_register(&lcd_driver) < 0)
return -1;
info("%s (C) Adams IT Services http://www.usblcd.de", DRIVER_VERSION);
info("USBLCD support registered.");
return 0;
}
void usb_lcd_cleanup(void)
{
struct lcd_usb_data *lcd = &lcd_instance;
lcd->present = 0;
usb_deregister(&lcd_driver);
}
module_init(usb_lcd_init);
module_exit(usb_lcd_cleanup);
MODULE_AUTHOR("Adams IT Services <info@usblcd.de>");
MODULE_DESCRIPTION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
......@@ -19,7 +19,7 @@
#define COMPAQ_VENDOR_ID 0x049f
#define COMPAQ_IPAQ_ID 0x0003
#define HP_VENDOR_ID 0x003f
#define HP_VENDOR_ID 0x03f0
#define HP_JORNADA_548_ID 0x1016
#define HP_JORNADA_568_ID 0x1116
......
......@@ -434,6 +434,12 @@ static int isd200_transfer_partial( struct us_data *us,
return ISD200_TRANSPORT_GOOD;
}
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("isd200_transfer_partial(): transfer aborted\n");
return ISD200_TRANSPORT_ABORTED;
}
/* uh oh... we have an error code, so something went wrong. */
if (result) {
/* NAK - that means we've retried a few times already */
......@@ -442,12 +448,6 @@ static int isd200_transfer_partial( struct us_data *us,
return ISD200_TRANSPORT_FAILED;
}
/* -ENOENT -- we canceled this transfer */
if (result == -ENOENT) {
US_DEBUGP("isd200_transfer_partial(): transfer aborted\n");
return ISD200_TRANSPORT_ABORTED;
}
/* the catch-all case */
US_DEBUGP("isd200_transfer_partial(): unknown error\n");
return ISD200_TRANSPORT_FAILED;
......@@ -581,8 +581,11 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
&partial);
US_DEBUGP("Bulk command transfer result=%d\n", result);
if (result == -ENOENT)
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
return ISD200_TRANSPORT_ABORTED;
}
else if (result == -EPIPE) {
/* if we stall, we need to clear it before we go on */
US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
......@@ -610,8 +613,10 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
US_DEBUGP("Attempting to get CSW...\n");
result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN,
&partial);
if (result == -ENOENT)
return ISD200_TRANSPORT_ABORTED;
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
return ISD200_TRANSPORT_ABORTED;
}
/* did the attempt to read the CSW fail? */
if (result == -EPIPE) {
......@@ -624,8 +629,9 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
US_BULK_CS_WRAP_LEN, &partial);
/* if the command was aborted, indicate that */
if (result == -ENOENT)
return ISD200_TRANSPORT_ABORTED;
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
return ISD200_TRANSPORT_ABORTED;
}
/* if it fails again, we need a reset and return an error*/
if (result == -EPIPE) {
......
......@@ -3,7 +3,7 @@
* Unrelated to CF/SM - just USB stuff.
*
* This is mostly a thin layer on top of transport.c.
* It converts routines that return values like -ENOENT and -EPIPE
* It converts routines that return values like -EPIPE
* into routines that return USB_STOR_TRANSPORT_ABORTED etc.
*
* There is also some debug printing here.
......@@ -58,13 +58,14 @@ usb_storage_send_control(struct us_data *us,
request, requesttype, value, index,
xfer_data, xfer_len);
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_send_control(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
// Check the return code for the command.
if (result < 0) {
/* if the command was aborted, indicate that */
if (result == -ENOENT)
return USB_STOR_TRANSPORT_ABORTED;
/* a stall is a fatal condition from the device */
if (result == -EPIPE) {
......@@ -105,13 +106,13 @@ usb_storage_raw_bulk(struct us_data *us, int direction, unsigned char *data,
/* return US_BULK_TRANSFER_SHORT; */
}
if (result) {
/* -ENOENT -- we canceled this transfer */
if (result == -ENOENT) {
US_DEBUGP("raw_bulk(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_storage_raw_bulk(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
if (result) {
/* NAK - that means we've retried a few times already */
if (result == -ETIMEDOUT)
US_DEBUGP("raw_bulk(): device NAKed\n");
......
......@@ -380,6 +380,7 @@ Scsi_Host_Template usb_stor_host_template = {
.emulated = TRUE
};
/* For a device that is "Not Ready" */
unsigned char usb_stor_sense_notready[18] = {
[0] = 0x70, /* current error */
[2] = 0x02, /* not ready */
......@@ -388,6 +389,14 @@ unsigned char usb_stor_sense_notready[18] = {
[13] = 0x03 /* manual intervention */
};
/* To Report "Illegal Request: Invalid Field in CDB */
unsigned char usb_stor_sense_invalidCDB[18] = {
[0] = 0x70, /* current error */
[2] = ILLEGAL_REQUEST, /* Illegal Request = 0x05 */
[7] = 0x0a, /* additional length */
[12] = 0x24 /* Invalid Field in CDB */
};
#define USB_STOR_SCSI_SENSE_HDRSZ 4
#define USB_STOR_SCSI_SENSE_10_HDRSZ 8
......
......@@ -46,6 +46,7 @@
#include "hosts.h"
extern unsigned char usb_stor_sense_notready[18];
extern unsigned char usb_stor_sense_invalidCDB[18];
extern Scsi_Host_Template usb_stor_host_template;
extern int usb_stor_scsiSense10to6(Scsi_Cmnd*);
extern int usb_stor_scsiSense6to10(Scsi_Cmnd*);
......
......@@ -65,6 +65,17 @@ UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001,
US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0),
#endif
/* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
* Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
* always fails and confuses drive; without US_FL_START_STOP, drive accesses
* (read or write) all fail.
*/
UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113,
"Buffalo",
"DUB-P40G HDD",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY | US_FL_START_STOP),
#ifdef CONFIG_USB_STORAGE_DPCM
UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
"Microtech",
......
......@@ -385,11 +385,15 @@ static int usb_stor_control_thread(void * __us)
us->srb->result = DID_BAD_TARGET << 16;
}
/* handle those devices which can't do a START_STOP */
else if ((us->srb->cmnd[0] == START_STOP) &&
(us->flags & US_FL_START_STOP)) {
US_DEBUGP("Skipping START_STOP command\n");
us->srb->result = GOOD << 1;
/* handle requests for EVPD, which most USB devices do
* not support */
else if((us->srb->cmnd[0] == INQUIRY) &&
(us->srb->cmnd[1] & 0x1)) {
US_DEBUGP("Faking INQUIRY command for EVPD\n");
memcpy(us->srb->sense_buffer,
usb_stor_sense_invalidCDB,
sizeof(usb_stor_sense_invalidCDB));
us->srb->result = CHECK_CONDITION << 1;
}
/* our device has gone - pretend not ready */
......@@ -405,6 +409,7 @@ static int usb_stor_control_thread(void * __us)
sizeof(usb_stor_sense_notready));
us->srb->result = GOOD << 1;
} else if(us->srb->cmnd[0] == INQUIRY) {
/* INQUIRY should always work, per spec... */
unsigned char data_ptr[36] = {
0x20, 0x80, 0x02, 0x02,
0x1F, 0x00, 0x00, 0x00};
......@@ -412,6 +417,7 @@ static int usb_stor_control_thread(void * __us)
fill_inquiry_response(us, data_ptr, 36);
us->srb->result = GOOD << 1;
} else {
/* not ready */
memcpy(us->srb->sense_buffer,
usb_stor_sense_notready,
sizeof(usb_stor_sense_notready));
......@@ -432,6 +438,35 @@ static int usb_stor_control_thread(void * __us)
us->srb->result = GOOD << 1;
}
/* Most USB devices can't handle START_STOP. But we
* need something for media-change, so we'll use TUR
* instead.
*/
else if (us->srb->cmnd[0] == START_STOP) {
unsigned char saved_cdb[16]; /* largest SCSI-III cmd */
__u8 old_cmd_len;
US_DEBUGP("Converting START_STOP to TUR\n");
/* save old command */
memcpy(saved_cdb, us->srb->cmnd, us->srb->cmd_len);
old_cmd_len = us->srb->cmd_len;
/* set up new command -- preserve LUN */
us->srb->cmd_len = 6;
memset(us->srb->cmnd, 0, us->srb->cmd_len);
us->srb->cmnd[0] = TEST_UNIT_READY;
us->srb->cmnd[1] = saved_cdb[1] & 0xE0;
/* do command */
US_DEBUG(usb_stor_show_command(us->srb));
us->proto_handler(us->srb, us);
/* restore original command */
us->srb->cmd_len = old_cmd_len;
memcpy(us->srb->cmnd, saved_cdb, us->srb->cmd_len);
}
/* we've got a command, let's do it! */
else {
US_DEBUG(usb_stor_show_command(us->srb));
......
This diff is collapsed.
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