Commit 408120d0 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge gregkh@kernel.bkbits.net:linux/usb-2.6

into kroah.com:/home/greg/linux/BK/usb-2.6
parents 95075bdb fc39c2c3
......@@ -2546,12 +2546,7 @@ Your cooperation is appreciated.
0 = /dev/usb/lp0 First USB printer
...
15 = /dev/usb/lp15 16th USB printer
16 = /dev/usb/mouse0 First USB mouse
...
31 = /dev/usb/mouse15 16th USB mouse
32 = /dev/usb/ez0 First USB firmware loader
...
47 = /dev/usb/ez15 16th USB firmware loader
32 = /dev/usb/mdc800 MDC800 USB camera
48 = /dev/usb/scanner0 First USB scanner
...
63 = /dev/usb/scanner15 16th USB scanner
......@@ -2559,6 +2554,22 @@ Your cooperation is appreciated.
65 = /dev/usb/usblcd USBLCD Interface (info@usblcd.de)
66 = /dev/usb/cpad0 Synaptics cPad (mouse/LCD)
96 = /dev/usb/hiddev0 1st USB HID device
...
111 = /dev/usb/hiddev15 16th USB HID device
112 = /dev/usb/auer0 1st auerswald ISDN device
...
127 = /dev/usb/auer15 16th auerswald ISDN device
128 = /dev/usb/brlvgr0 First Braille Voyager device
...
131 = /dev/usb/brlvgr3 Fourth Braille Voyager device
144 = /dev/usb/lcd USB LCD device
160 = /dev/usb/legousbtower0 1st USB Legotower device
...
175 = /dev/usb/legousbtower15 16th USB Legotower device
240 = /dev/usb/dabusb0 First daubusb device
...
243 = /dev/usb/dabusb3 Fourth dabusb device
181 char Conrad Electronic parallel port radio clocks
0 = /dev/pcfclock0 First Conrad radio clock
......
-------------------------------------------------------------------------
Readme for Linux device driver for the Texas Instruments SilverLink cable
and direct USB cable provided by some TI's handhelds.
-------------------------------------------------------------------------
Author: Romain Liévin & Julien Blache
......@@ -9,7 +10,8 @@ INTRODUCTION:
This is a driver for the TI-GRAPH LINK USB (aka SilverLink) cable, a cable
designed by TI for connecting their TI8x/9x calculators to a computer
(PC or Mac usually).
(PC or Mac usually). It has been extended to support the USB port offered by
some latest TI handhelds (TI84+ and TI89 Titanium).
If you need more information, please visit the 'SilverLink drivers' homepage
at the above URL.
......@@ -73,4 +75,4 @@ this driver but he better knows the Mac OS-X driver.
CREDITS:
The code is based on dabusb.c, printer.c and scanner.c !
The driver has been developed independently of Texas Instruments.
The driver has been developed independently of Texas Instruments Inc.
......@@ -8,26 +8,30 @@
Index
=====
1. Copyright
2. License
3. Overview
4. Supported devices
5. Module dependencies
6. Module loading
7. Module paramaters
8. Contact information
9. Credits
1. Copyright
2. Disclaimer
3. License
4. Overview
5. Supported devices
6. Module dependencies
7. Module loading
8. Module paramaters
9. Contact information
10. Credits
1. Copyright
============
Copyright (C) 2002-2004 by Luca Risolia <luca.risolia@studio.unibo.it>
2. Disclaimer
=============
Winbond is a trademark of Winbond Electronics Corporation.
This driver is not sponsored or developed by Winbond.
This software is not sponsored or developed by Winbond.
2. License
3. License
==========
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
......@@ -44,7 +48,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3. Overview
4. Overview
===========
This driver supports the video streaming capabilities of the devices mounting
Winbond W9967CF and Winbond W9968CF JPEG USB Dual Mode Camera Chips. OV681
......@@ -57,7 +61,7 @@ decoding, up-scaling and colour conversions. Once the driver is installed,
every time an application tries to open a recognized device, "w9968cf" checks
the presence of the "w9968cf-vpp" module and loads it automatically by default.
Please keep in mind that official kernels do NOT include the second module for
Please keep in mind that official kernels do not include the second module for
performance purposes. However it is always recommended to download and install
the latest and complete release of the driver, replacing the existing one, if
present: it will be still even possible not to load the "w9968cf-vpp" module at
......@@ -65,7 +69,7 @@ all, if you ever want to. Another important missing feature of the version in
the official Linux 2.4 kernels is the writeable /proc filesystem interface.
The latest and full-featured version of the W996[87]CF driver can be found at:
http://go.lamarinapunto.com/ . Please refer to the documentation included in
http://www.linux-projects.org. Please refer to the documentation included in
that package, if you are going to use it.
Up to 32 cameras can be handled at the same time. They can be connected and
......@@ -83,7 +87,7 @@ will be automatically loaded by default (provided that the kernel has been
compiled with the automatic module loading option).
4. Supported devices
5. Supported devices
====================
At the moment, known W996[87]CF and OV681 based devices are:
- Aroma Digi Pen VGA Dual Mode ADG-5000 (unknown image sensor)
......@@ -99,11 +103,9 @@ At the moment, known W996[87]CF and OV681 based devices are:
If you know any other W996[87]CF or OV681 based cameras, please contact me.
The list above does NOT imply that all those devices work with this driver: up
The list above does not imply that all those devices work with this driver: up
until now only webcams that have an image sensor supported by the "ovcamchip"
module work.
For a list of supported image sensors, please visit the author's homepage on
this module: http://alpha.dyndns.org/ov511/
module work. Kernel messages will always tell you whether this is case.
Possible external microcontrollers of those webcams are not supported: this
means that still images cannot be downloaded from the device memory.
......@@ -113,7 +115,7 @@ Furthermore, it's worth to note that I was only able to run tests on my
additional testing and full support, would be much appreciated.
5. Module dependencies
6. Module dependencies
======================
For it to work properly, the driver needs kernel support for Video4Linux, USB
and I2C, and the "ovcamchip" module for the image sensor. Make sure you are not
......@@ -157,7 +159,7 @@ And finally:
CONFIG_USB_W9968CF=m
6. Module loading
7. Module loading
=================
To use the driver, it is necessary to load the "w9968cf" module into memory
after every other module required.
......@@ -166,6 +168,7 @@ Loading can be done this way, from root:
[root@localhost home]# modprobe usbcore
[root@localhost home]# modprobe i2c-core
[root@localhost home]# modprobe videodev
[root@localhost home]# modprobe w9968cf
At this point the pertinent devices should be recognized: "dmesg" can be used
......@@ -181,7 +184,7 @@ explanation about them and which syntax to use, it is recommended to run the
[root@locahost home]# modinfo w9968cf
7. Module parameters
8. Module parameters
====================
Module parameters are listed below:
-------------------------------------------------------------------------------
......@@ -452,7 +455,7 @@ Default: 0
-------------------------------------------------------------------------------
8. Contact information
9. Contact information
======================
I may be contacted by e-mail at <luca.risolia@studio.unibo.it>.
......@@ -461,7 +464,7 @@ My public 1024-bit key should be available at your keyserver; the fingerprint
is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'.
9. Credits
10. Credits
==========
The development would not have proceed much further without having looked at
the source code of other drivers and without the help of several persons; in
......
......@@ -2371,7 +2371,7 @@ USB SN9C10x DRIVER
P: Luca Risolia
M: luca.risolia@studio.unibo.it
L: linux-usb-devel@lists.sourceforge.net
W: http://go.lamarinapunto.com
W: http://www.linux-projects.org
S: Maintained
USB SUBSYSTEM
......@@ -2399,7 +2399,7 @@ USB W996[87]CF DRIVER
P: Luca Risolia
M: luca.risolia@studio.unibo.it
L: linux-usb-devel@lists.sourceforge.net
W: http://go.lamarinapunto.com
W: http://www.linux-projects.org
S: Maintained
USER-MODE LINUX
......
......@@ -3119,12 +3119,18 @@ static void prepmixch(struct consmixstate *state)
{
struct usb_device *dev = state->s->usbdev;
struct mixerchannel *ch;
unsigned char buf[2];
unsigned char *buf;
__s16 v1;
unsigned int v2, v3;
if (!state->nrmixch || state->nrmixch > SOUND_MIXER_NRDEVICES)
return;
buf = kmalloc(sizeof(*buf) * 2, GFP_KERNEL);
if (!buf) {
printk(KERN_ERR "prepmixch: out of memory\n") ;
return;
}
ch = &state->mixch[state->nrmixch-1];
switch (ch->selector) {
case 0: /* mixer unit request */
......@@ -3236,13 +3242,16 @@ static void prepmixch(struct consmixstate *state)
default:
goto err;
}
return;
freebuf:
kfree(buf);
return;
err:
printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n",
dev->devnum, state->ctrlif, ch->unitid, ch->chnum, ch->selector);
if (state->nrmixch)
state->nrmixch--;
goto freebuf;
}
......
......@@ -222,6 +222,7 @@ static int usblp_cache_device_id_string(struct usblp *usblp);
/* forward reference to make our lives easier */
static struct usb_driver usblp_driver;
static DECLARE_MUTEX(usblp_sem); /* locks the existence of usblp's */
/*
* Functions for usblp control messages.
......@@ -343,7 +344,7 @@ static int usblp_open(struct inode *inode, struct file *file)
if (minor < 0)
return -ENODEV;
lock_kernel();
down (&usblp_sem);
retval = -ENODEV;
intf = usb_find_interface(&usblp_driver, minor);
......@@ -389,7 +390,7 @@ static int usblp_open(struct inode *inode, struct file *file)
}
}
out:
unlock_kernel();
up (&usblp_sem);
return retval;
}
......@@ -415,13 +416,13 @@ static int usblp_release(struct inode *inode, struct file *file)
{
struct usblp *usblp = file->private_data;
down (&usblp->sem);
down (&usblp_sem);
usblp->used = 0;
if (usblp->present) {
usblp_unlink_urbs(usblp);
up(&usblp->sem);
} else /* finish cleanup from disconnect */
usblp_cleanup (usblp);
up (&usblp_sem);
return 0;
}
......@@ -1149,8 +1150,8 @@ static void usblp_disconnect(struct usb_interface *intf)
BUG ();
}
down (&usblp_sem);
down (&usblp->sem);
lock_kernel();
usblp->present = 0;
usb_set_intfdata (intf, NULL);
......@@ -1159,12 +1160,11 @@ static void usblp_disconnect(struct usb_interface *intf)
usblp->writebuf, usblp->writeurb->transfer_dma);
usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
usblp->readbuf, usblp->readurb->transfer_dma);
up (&usblp->sem);
if (!usblp->used)
usblp_cleanup (usblp);
else /* cleanup later, on release */
up (&usblp->sem);
unlock_kernel();
up (&usblp_sem);
}
static struct usb_device_id usblp_ids [] = {
......
......@@ -78,9 +78,17 @@ static inline struct device *hubdev (struct usb_device *hdev)
/* USB 2.0 spec Section 11.24.4.5 */
static int get_hub_descriptor(struct usb_device *hdev, void *data, int size)
{
return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
USB_DT_HUB << 8, 0, data, size, HZ * USB_CTRL_GET_TIMEOUT);
int i, ret;
for (i = 0; i < 3; i++) {
ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
USB_DT_HUB << 8, 0, data, size,
HZ * USB_CTRL_GET_TIMEOUT);
if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2))
return ret;
}
return -EINVAL;
}
/*
......
......@@ -823,9 +823,19 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
*/
int usb_get_status(struct usb_device *dev, int type, int target, void *data)
{
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2,
HZ * USB_CTRL_GET_TIMEOUT);
int ret;
u16 *status = kmalloc(sizeof(*status), GFP_KERNEL);
if (!status)
return -ENOMEM;
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status,
sizeof(*status), HZ * USB_CTRL_GET_TIMEOUT);
*(u16 *)data = *status;
kfree(status);
return ret;
}
/**
......
......@@ -550,9 +550,7 @@ static int usb_device_match (struct device *dev, struct device_driver *drv)
return 0;
intf = to_usb_interface(dev);
usb_drv = to_usb_driver(drv);
id = usb_drv->id_table;
id = usb_match_id (intf, usb_drv->id_table);
if (id)
......@@ -765,6 +763,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port)
if (dev->bus->op->allocate)
if (dev->bus->op->allocate(dev)) {
usb_bus_put(bus);
kfree(dev);
return NULL;
}
......
......@@ -2320,7 +2320,7 @@ eth_bind (struct usb_gadget *gadget)
} else if (gadget_is_lh7a40x(gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
} else if (gadget_is_n9604(gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x020a);
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
} else {
/* can't assume CDC works. don't want to default to
* anything less functional on CDC-capable hardware,
......
......@@ -3736,7 +3736,7 @@ static int __init check_parameters(struct fsg_dev *fsg)
else if (gadget_is_lh7a40x(fsg->gadget))
mod_data.release = __constant_cpu_to_le16 (0x0309);
else if (gadget_is_n9604(fsg->gadget))
mod_data.release = __constant_cpu_to_le16 (0x030a);
mod_data.release = __constant_cpu_to_le16 (0x0310);
else {
WARN(fsg, "controller '%s' not recognized\n",
fsg->gadget->name);
......
......@@ -1189,7 +1189,7 @@ zero_bind (struct usb_gadget *gadget)
} else if (gadget_is_lh7a40x(gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
} else if (gadget_is_n9604(gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x020a);
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
} else {
/* gadget zero is so simple (for now, no altsettings) that
* it SHOULD NOT have problems with bulk-capable hardware.
......
......@@ -765,8 +765,12 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
/* Low-speed transfers get a different queue, and won't hog the bus */
if (urb->dev->speed == USB_SPEED_LOW)
/* Low-speed transfers get a different queue, and won't hog the bus.
* Also, some devices enumerate better without FSBR; the easiest way
* to do that is to put URBs on the low-speed queue while the device
* is in the DEFAULT state. */
if (urb->dev->speed == USB_SPEED_LOW ||
urb->dev->state == USB_STATE_DEFAULT)
skelqh = uhci->skel_ls_control_qh;
else {
skelqh = uhci->skel_fs_control_qh;
......
......@@ -925,6 +925,7 @@ static void hid_irq_in(struct urb *urb, struct pt_regs *regs)
case -ECONNRESET: /* unlink */
case -ENOENT:
case -ESHUTDOWN:
case -EPERM:
return;
case -ETIMEDOUT: /* NAK */
break;
......@@ -1833,6 +1834,30 @@ static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id
return 0;
}
static int hid_suspend(struct usb_interface *intf, u32 state)
{
struct hid_device *hid = usb_get_intfdata (intf);
usb_kill_urb(hid->urbin);
intf->dev.power.power_state = state;
dev_dbg(&intf->dev, "suspend\n");
return 0;
}
static int hid_resume(struct usb_interface *intf)
{
struct hid_device *hid = usb_get_intfdata (intf);
int status;
intf->dev.power.power_state = PM_SUSPEND_ON;
if (hid->open)
status = usb_submit_urb(hid->urbin, GFP_NOIO);
else
status = 0;
dev_dbg(&intf->dev, "resume status %d\n", status);
return status;
}
static struct usb_device_id hid_usb_ids [] = {
{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
.bInterfaceClass = USB_INTERFACE_CLASS_HID },
......@@ -1846,6 +1871,8 @@ static struct usb_driver hid_driver = {
.name = "usbhid",
.probe = hid_probe,
.disconnect = hid_disconnect,
.suspend = hid_suspend,
.resume = hid_resume,
.id_table = hid_usb_ids,
};
......
......@@ -135,7 +135,7 @@ static const struct w9968cf_format w9968cf_formatlist[] = {
#define W9968CF_MODULE_NAME "V4L driver for W996[87]CF JPEG USB " \
"Dual Mode Camera Chip"
#define W9968CF_MODULE_VERSION "1:1.32-basic"
#define W9968CF_MODULE_VERSION "1:1.33-basic"
#define W9968CF_MODULE_AUTHOR "(C) 2002-2004 Luca Risolia"
#define W9968CF_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define W9968CF_MODULE_LICENSE "GPL"
......
......@@ -121,6 +121,16 @@ config USB_CYTHERM
To compile this driver as a module, choose M here: the
module will be called cytherm.
config USB_PHIDGETKIT
tristate "USB PhidgetKit support"
depends on USB
help
Say Y here if you want to connect a PhidgetKit USB device from
Phidgets Inc.
To compile this driver as a module, choose M here: the
module will be called phidgetkit.
config USB_PHIDGETSERVO
tristate "USB PhidgetServo support"
depends on USB
......
......@@ -10,8 +10,9 @@ obj-$(CONFIG_USB_EMI62) += emi62.o
obj-$(CONFIG_USB_LCD) += usblcd.o
obj-$(CONFIG_USB_LED) += usbled.o
obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o
obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o
obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o
obj-$(CONFIG_USB_RIO500) += rio500.o
obj-$(CONFIG_USB_TEST) += usbtest.o
obj-$(CONFIG_USB_TIGL) += tiglusb.o
obj-$(CONFIG_USB_USS720) += uss720.o
obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o
/*
* USB PhidgetInterfaceKit driver 1.0
*
* Copyright (C) 2004 Sean Young <sean@mess.org>
* Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
*
* 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 is a driver for the USB PhidgetInterfaceKit.
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/usb.h>
#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
#define DRIVER_DESC "USB PhidgetInterfaceKit Driver"
#define USB_VENDOR_ID_GLAB 0x06c2
#define USB_DEVICE_ID_INTERFACEKIT004 0x0040
#define USB_DEVICE_ID_INTERFACEKIT888 0x0045
#define USB_DEVICE_ID_INTERFACEKIT047 0x0051
#define USB_DEVICE_ID_INTERFACEKIT088 0x0053
#define USB_VENDOR_ID_WISEGROUP 0x0925
#define USB_DEVICE_ID_INTERFACEKIT884 0x8201
#define MAX_INTERFACES 8
struct driver_interfacekit {
int sensors;
int inputs;
int outputs;
int has_lcd;
};
#define ifkit(_sensors, _inputs, _outputs, _lcd) \
static struct driver_interfacekit ph_##_sensors##_inputs##_outputs = { \
.sensors = _sensors, \
.inputs = _inputs, \
.outputs = _outputs, \
.has_lcd = _lcd, \
};
ifkit(0, 0, 4, 0);
ifkit(8, 8, 8, 0);
ifkit(0, 4, 7, 1);
ifkit(8, 8, 4, 0);
ifkit(0, 8, 8, 1);
struct phidget_interfacekit {
struct usb_device *udev;
struct usb_interface *intf;
struct driver_interfacekit *ifkit;
int outputs[MAX_INTERFACES];
int inputs[MAX_INTERFACES];
int sensors[MAX_INTERFACES];
u8 lcd_files_on;
struct urb *irq;
unsigned char *data;
dma_addr_t data_dma;
};
static struct usb_device_id id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004),
.driver_info = (kernel_ulong_t)&ph_004},
{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888),
.driver_info = (kernel_ulong_t)&ph_888},
{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047),
.driver_info = (kernel_ulong_t)&ph_047},
{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088),
.driver_info = (kernel_ulong_t)&ph_088},
{USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884),
.driver_info = (kernel_ulong_t)&ph_884},
{}
};
MODULE_DEVICE_TABLE(usb, id_table);
static int change_outputs(struct phidget_interfacekit *kit, int output_num, int enable)
{
unsigned char *buffer;
int retval;
int n;
buffer = kmalloc(4, GFP_KERNEL);
if (!buffer) {
dev_err(&kit->udev->dev, "%s - out of memory\n",
__FUNCTION__);
return -ENOMEM;
}
kit->outputs[output_num] = enable;
memset(buffer, 0, 4);
for (n=0; n<8; n++) {
if (kit->outputs[n]) {
buffer[0] |= 1 << n;
}
}
dev_dbg(&kit->udev->dev, "data: %02x %02x\n", buffer[0], buffer[1]);
retval = usb_control_msg(kit->udev,
usb_sndctrlpipe(kit->udev, 0),
0x09, 0x21, 0x0200, 0x0000, buffer, 4, 2 * HZ);
if (retval != 4)
dev_err(&kit->udev->dev, "retval = %d\n", retval);
kfree(buffer);
return retval < 0 ? retval : 0;
}
static int change_string(struct phidget_interfacekit *kit, const char *display, unsigned char row)
{
unsigned char *buffer;
unsigned char *form_buffer;
int retval = -ENOMEM;
int i,j, len, buf_ptr;
buffer = kmalloc(8, GFP_KERNEL);
form_buffer = kmalloc(30, GFP_KERNEL);
if ((!buffer) || (!form_buffer)) {
dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
goto exit;
}
len = strlen(display);
if (len > 20)
len = 20;
dev_dbg(&kit->udev->dev, "Setting LCD line %d to %s\n", row, display);
form_buffer[0] = row * 0x40 + 0x80;
form_buffer[1] = 0x02;
buf_ptr = 2;
for (i = 0; i<len; i++)
form_buffer[buf_ptr++] = display[i];
for (i = 0; i < (20 - len); i++)
form_buffer[buf_ptr++] = 0x20;
form_buffer[buf_ptr++] = 0x01;
form_buffer[buf_ptr++] = row * 0x40 + 0x80 + strlen(display);
for (i = 0; i < buf_ptr; i += 7) {
if ((buf_ptr - i) > 7)
len = 7;
else
len = (buf_ptr - i);
for (j = 0; j < len; j++)
buffer[j] = form_buffer[i + j];
buffer[7] = len;
retval = usb_control_msg(kit->udev,
usb_sndctrlpipe(kit->udev, 0),
0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2 * HZ);
if (retval < 0)
goto exit;
}
retval = 0;
exit:
kfree(buffer);
kfree(form_buffer);
return retval;
}
#define set_lcd_line(number) \
static ssize_t lcd_line_##number(struct device *dev, const char *buf, size_t count) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
change_string(kit, buf, number - 1); \
return count; \
} \
static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number);
set_lcd_line(1);
set_lcd_line(2);
static ssize_t set_backlight(struct device *dev, const char *buf, size_t count)
{
struct usb_interface *intf = to_usb_interface(dev);
struct phidget_interfacekit *kit = usb_get_intfdata(intf);
int enabled;
unsigned char *buffer;
int retval = -ENOMEM;
buffer = kmalloc(8, GFP_KERNEL);
if (!buffer) {
dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
goto exit;
}
if (sscanf(buf, "%d", &enabled) < 1) {
retval = -EINVAL;
goto exit;
}
memset(buffer, 0x00, 8);
if (enabled)
buffer[0] = 0x01;
buffer[7] = 0x11;
dev_dbg(&kit->udev->dev, "Setting backlight to %s\n", enabled ? "on" : "off");
retval = usb_control_msg(kit->udev,
usb_sndctrlpipe(kit->udev, 0),
0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2 * HZ);
if (retval < 0)
goto exit;
retval = count;
exit:
kfree(buffer);
return retval;
}
static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight);
static void remove_lcd_files(struct phidget_interfacekit *kit)
{
if (kit->lcd_files_on) {
dev_dbg(&kit->udev->dev, "Removing lcd files\n");
device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_1);
device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_2);
device_remove_file(&kit->intf->dev, &dev_attr_backlight);
}
}
static ssize_t enable_lcd_files(struct device *dev, const char *buf, size_t count)
{
struct usb_interface *intf = to_usb_interface(dev);
struct phidget_interfacekit *kit = usb_get_intfdata(intf);
int enable;
if (kit->ifkit->has_lcd == 0)
return -ENODEV;
if (sscanf(buf, "%d", &enable) < 1)
return -EINVAL;
if (enable) {
if (!kit->lcd_files_on) {
dev_dbg(&kit->udev->dev, "Adding lcd files\n");
device_create_file(&kit->intf->dev, &dev_attr_lcd_line_1);
device_create_file(&kit->intf->dev, &dev_attr_lcd_line_2);
device_create_file(&kit->intf->dev, &dev_attr_backlight);
kit->lcd_files_on = 1;
}
} else {
if (kit->lcd_files_on) {
remove_lcd_files(kit);
kit->lcd_files_on = 0;
}
}
return count;
}
static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files);
static void interfacekit_irq(struct urb *urb, struct pt_regs *regs)
{
struct phidget_interfacekit *kit = urb->context;
unsigned char *buffer = kit->data;
int status;
int n;
switch (urb->status) {
case 0: /* success */
break;
case -ECONNRESET: /* unlink */
case -ENOENT:
case -ESHUTDOWN:
return;
/* -EPIPE: should clear the halt */
default: /* error */
goto resubmit;
}
for (n=0; n<8; n++) {
kit->inputs[n] = buffer[1] & (1 << n) ? 1 : 0;
}
if (buffer[0] & 1) {
kit->sensors[4] = buffer[2] + (buffer[3] & 0x0f) * 256;
kit->sensors[5] = buffer[4] + (buffer[3] & 0xf0) * 16;
kit->sensors[6] = buffer[5] + (buffer[6] & 0x0f) * 256;
kit->sensors[7] = buffer[7] + (buffer[6] & 0xf0) * 16;
} else {
kit->sensors[0] = buffer[2] + (buffer[3] & 0x0f) * 256;
kit->sensors[1] = buffer[4] + (buffer[3] & 0xf0) * 16;
kit->sensors[2] = buffer[5] + (buffer[6] & 0x0f) * 256;
kit->sensors[3] = buffer[7] + (buffer[6] & 0xf0) * 16;
}
resubmit:
status = usb_submit_urb(urb, SLAB_ATOMIC);
if (status)
err("can't resubmit intr, %s-%s/interfacekit0, status %d",
kit->udev->bus->bus_name,
kit->udev->devpath, status);
}
#define show_set_output(value) \
static ssize_t set_output##value(struct device *dev, const char *buf, \
size_t count) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
int enabled; \
int retval; \
\
if (sscanf(buf, "%d", &enabled) < 1) { \
return -EINVAL; \
} \
\
retval = change_outputs(kit, value - 1, enabled ? 1 : 0); \
\
return retval ? retval : count; \
} \
\
static ssize_t show_output##value(struct device *dev, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
\
return sprintf(buf, "%d\n", kit->outputs[value - 1 ]); \
} \
static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO, \
show_output##value, set_output##value);
show_set_output(1);
show_set_output(2);
show_set_output(3);
show_set_output(4);
show_set_output(5);
show_set_output(6);
show_set_output(7);
show_set_output(8); /* should be MAX_INTERFACES - 1 */
#define show_input(value) \
static ssize_t show_input##value(struct device *dev, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
\
return sprintf(buf, "%d\n", kit->inputs[value - 1]); \
} \
static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL);
show_input(1);
show_input(2);
show_input(3);
show_input(4);
show_input(5);
show_input(6);
show_input(7);
show_input(8); /* should be MAX_INTERFACES - 1 */
#define show_sensor(value) \
static ssize_t show_sensor##value(struct device *dev, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
\
return sprintf(buf, "%d\n", kit->sensors[value - 1]); \
} \
static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL);
show_sensor(1);
show_sensor(2);
show_sensor(3);
show_sensor(4);
show_sensor(5);
show_sensor(6);
show_sensor(7);
show_sensor(8); /* should be MAX_INTERFACES - 1 */
static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct phidget_interfacekit *kit;
struct driver_interfacekit *ifkit;
int pipe, maxp;
ifkit = (struct driver_interfacekit *)id->driver_info;
if (!ifkit)
return -ENODEV;
interface = intf->cur_altsetting;
if (interface->desc.bNumEndpoints != 1)
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
if (!(endpoint->bEndpointAddress & 0x80))
return -ENODEV;
/*
* bmAttributes
*/
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
kit = kmalloc(sizeof(*kit), GFP_KERNEL);
if (kit == NULL) {
dev_err(&intf->dev, "%s - out of memory\n", __FUNCTION__);
return -ENOMEM;
}
memset(kit, 0, sizeof(*kit));
kit->ifkit = ifkit;
kit->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kit->data_dma);
if (!kit->data) {
kfree(kit);
return -ENOMEM;
}
kit->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!kit->irq) {
usb_buffer_free(dev, 8, kit->data, kit->data_dma);
kfree(kit);
return -ENOMEM;
}
kit->udev = usb_get_dev(dev);
kit->intf = intf;
usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data,
(maxp > 8 ? 8 : maxp),
interfacekit_irq, kit, endpoint->bInterval);
kit->irq->transfer_dma = kit->data_dma;
kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
usb_set_intfdata(intf, kit);
if (usb_submit_urb(kit->irq, GFP_KERNEL)) {
return -EIO;
}
if (ifkit->outputs == 8) {
device_create_file(&intf->dev, &dev_attr_output1);
device_create_file(&intf->dev, &dev_attr_output2);
device_create_file(&intf->dev, &dev_attr_output3);
device_create_file(&intf->dev, &dev_attr_output4);
device_create_file(&intf->dev, &dev_attr_output5);
device_create_file(&intf->dev, &dev_attr_output6);
device_create_file(&intf->dev, &dev_attr_output7);
device_create_file(&intf->dev, &dev_attr_output8);
}
if (ifkit->inputs >= 4) {
device_create_file(&intf->dev, &dev_attr_input1);
device_create_file(&intf->dev, &dev_attr_input2);
device_create_file(&intf->dev, &dev_attr_input3);
device_create_file(&intf->dev, &dev_attr_input4);
}
if (ifkit->inputs == 8) {
device_create_file(&intf->dev, &dev_attr_input5);
device_create_file(&intf->dev, &dev_attr_input6);
device_create_file(&intf->dev, &dev_attr_input7);
device_create_file(&intf->dev, &dev_attr_input8);
}
if (ifkit->sensors >= 4) {
device_create_file(&intf->dev, &dev_attr_sensor1);
device_create_file(&intf->dev, &dev_attr_sensor2);
device_create_file(&intf->dev, &dev_attr_sensor3);
device_create_file(&intf->dev, &dev_attr_sensor4);
}
if (ifkit->sensors >= 7) {
device_create_file(&intf->dev, &dev_attr_sensor5);
device_create_file(&intf->dev, &dev_attr_sensor6);
device_create_file(&intf->dev, &dev_attr_sensor7);
}
if (ifkit->sensors == 8) {
device_create_file(&intf->dev, &dev_attr_sensor8);
}
if (ifkit->has_lcd)
device_create_file(&intf->dev, &dev_attr_lcd);
dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n",
ifkit->inputs, ifkit->outputs, ifkit->sensors);
return 0;
}
static void interfacekit_disconnect(struct usb_interface *interface)
{
struct phidget_interfacekit *kit;
kit = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
if (!kit)
return;
if (kit->ifkit->outputs == MAX_INTERFACES) {
device_remove_file(&interface->dev, &dev_attr_output1);
device_remove_file(&interface->dev, &dev_attr_output2);
device_remove_file(&interface->dev, &dev_attr_output3);
device_remove_file(&interface->dev, &dev_attr_output4);
device_remove_file(&interface->dev, &dev_attr_output5);
device_remove_file(&interface->dev, &dev_attr_output6);
device_remove_file(&interface->dev, &dev_attr_output7);
device_remove_file(&interface->dev, &dev_attr_output7);
}
if (kit->ifkit->inputs >= 4) {
device_remove_file(&interface->dev, &dev_attr_input1);
device_remove_file(&interface->dev, &dev_attr_input2);
device_remove_file(&interface->dev, &dev_attr_input3);
device_remove_file(&interface->dev, &dev_attr_input4);
}
if (kit->ifkit->inputs == 8) {
device_remove_file(&interface->dev, &dev_attr_input5);
device_remove_file(&interface->dev, &dev_attr_input6);
device_remove_file(&interface->dev, &dev_attr_input7);
device_remove_file(&interface->dev, &dev_attr_input8);
}
if (kit->ifkit->sensors >= 4) {
device_remove_file(&interface->dev, &dev_attr_sensor1);
device_remove_file(&interface->dev, &dev_attr_sensor2);
device_remove_file(&interface->dev, &dev_attr_sensor3);
device_remove_file(&interface->dev, &dev_attr_sensor4);
}
if (kit->ifkit->sensors >= 7) {
device_remove_file(&interface->dev, &dev_attr_sensor5);
device_remove_file(&interface->dev, &dev_attr_sensor6);
device_remove_file(&interface->dev, &dev_attr_sensor7);
}
if (kit->ifkit->sensors == 8) {
device_remove_file(&interface->dev, &dev_attr_sensor8);
}
if (kit->ifkit->has_lcd)
device_create_file(&interface->dev, &dev_attr_lcd);
dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n",
kit->ifkit->inputs, kit->ifkit->outputs, kit->ifkit->sensors);
usb_kill_urb(kit->irq);
usb_free_urb(kit->irq);
usb_buffer_free(kit->udev, 8, kit->data, kit->data_dma);
usb_put_dev(kit->udev);
kfree(kit);
}
static struct usb_driver interfacekit_driver = {
.owner = THIS_MODULE,
.name = "phidgetkit",
.probe = interfacekit_probe,
.disconnect = interfacekit_disconnect,
.id_table = id_table
};
static int __init interfacekit_init(void)
{
int retval = 0;
retval = usb_register(&interfacekit_driver);
if (retval)
err("usb_register failed. Error number %d", retval);
return retval;
}
static void __exit interfacekit_exit(void)
{
usb_deregister(&interfacekit_driver);
}
module_init(interfacekit_init);
module_exit(interfacekit_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
......@@ -4,7 +4,7 @@
* Target: Texas Instruments graphing calculators (http://lpg.ticalc.org).
*
* Copyright (C) 2001-2004:
* Romain Lievin <roms@lpg.ticalc.org>
* Romain Lievin <roms@tilp.info>
* Julien BLACHE <jb@technologeek.org>
* under the terms of the GNU General Public License.
*
......@@ -14,7 +14,7 @@
* and the website at: http://lpg.ticalc.org/prj_usb/
* for more info.
*
* History :
* History:
* 1.0x, Romain & Julien: initial submit.
* 1.03, Greg Kroah: modifications.
* 1.04, Julien: clean-up & fixes; Romain: 2.4 backport.
......@@ -22,6 +22,7 @@
* 1.06, Romain: synched with 2.5, version/firmware changed (confusing).
* 1.07, Romain: fixed bad use of usb_clear_halt (invalid argument);
* timeout argument checked in ioctl + clean-up.
* 1.08, Romain: added support of USB port embedded on some TI's handhelds.
*/
#include <linux/module.h>
......@@ -41,7 +42,7 @@
/*
* Version Information
*/
#define DRIVER_VERSION "1.07"
#define DRIVER_VERSION "1.08"
#define DRIVER_AUTHOR "Romain Lievin <roms@tilp.info> & Julien Blache <jb@jblache.org>"
#define DRIVER_DESC "TI-GRAPH LINK USB (aka SilverLink) driver"
#define DRIVER_LICENSE "GPL"
......@@ -178,11 +179,11 @@ tiglusb_read (struct file *filp, char __user *buf, size_t count, loff_t * f_pos)
if (!s->dev)
return -EIO;
buffer = kmalloc(BULK_RCV_MAX, GFP_KERNEL);
buffer = kmalloc (s->max_ps, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
bytes_to_read = (count >= BULK_RCV_MAX) ? BULK_RCV_MAX : count;
bytes_to_read = (count >= s->max_ps) ? s->max_ps : count;
pipe = usb_rcvbulkpipe (s->dev, 1);
result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_read,
......@@ -235,11 +236,11 @@ tiglusb_write (struct file *filp, const char __user *buf, size_t count, loff_t *
if (!s->dev)
return -EIO;
buffer = kmalloc(BULK_SND_MAX, GFP_KERNEL);
buffer = kmalloc (s->max_ps, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
bytes_to_write = (count >= BULK_SND_MAX) ? BULK_SND_MAX : count;
bytes_to_write = (count >= s->max_ps) ? s->max_ps : count;
if (copy_from_user (buffer, buf, bytes_to_write)) {
ret = -EFAULT;
goto out;
......@@ -309,6 +310,15 @@ tiglusb_ioctl (struct inode *inode, struct file *filp,
if (clear_pipes (s->dev))
ret = -EIO;
break;
case IOCTL_TIUSB_GET_MAXPS:
if (copy_to_user((int *) arg, &s->max_ps, sizeof(int)))
return -EFAULT;
break;
case IOCTL_TIUSB_GET_DEVID:
if (copy_to_user((int *) arg, &s->dev->descriptor.idProduct,
sizeof(int)))
return -EFAULT;
break;
default:
ret = -ENOTTY;
break;
......@@ -341,6 +351,9 @@ tiglusb_probe (struct usb_interface *intf,
int minor = -1;
int i, err = 0;
ptiglusb_t s;
struct usb_host_config *conf;
struct usb_host_interface *ifdata = NULL;
int max_ps;
dbg ("probing vendor id 0x%x, device id 0x%x",
dev->descriptor.idVendor, dev->descriptor.idProduct);
......@@ -355,19 +368,31 @@ tiglusb_probe (struct usb_interface *intf,
goto out;
}
if ((dev->descriptor.idProduct != 0xe001)
&& (dev->descriptor.idVendor != 0x451)) {
if (dev->descriptor.idVendor != 0x451) {
err = -ENODEV;
goto out;
}
// NOTE: it's already in this config, this shouldn't be needed.
// is this working around some hardware bug?
if (usb_reset_configuration (dev) < 0) {
err ("tiglusb_probe: reset_configuration failed");
err = -ENODEV;
goto out;
}
if ((dev->descriptor.idProduct != 0xe001) &&
(dev->descriptor.idProduct != 0xe004) &&
(dev->descriptor.idProduct != 0xe008)) {
err = -ENODEV;
goto out;
}
/*
* TI introduced some new handhelds with embedded USB port.
* Port advertises same config as SilverLink cable but with a
* different maximum packet size (64 rather than 32).
*/
conf = dev->actconfig;
ifdata = conf->interface[0]->cur_altsetting;
max_ps = ifdata->endpoint[0].desc.wMaxPacketSize;
info("max packet size of %d/%d bytes\n",
ifdata->endpoint[0].desc.wMaxPacketSize,
ifdata->endpoint[1].desc.wMaxPacketSize);
/*
* Find a tiglusb struct
......@@ -390,6 +415,7 @@ tiglusb_probe (struct usb_interface *intf,
down (&s->mutex);
s->remove_pending = 0;
s->dev = dev;
s->max_ps = max_ps;
up (&s->mutex);
dbg ("bound to interface");
......
......@@ -17,12 +17,6 @@
*/
#define MAXTIGL 16
/*
* Max. packetsize for IN and OUT pipes
*/
#define BULK_RCV_MAX 32
#define BULK_SND_MAX 32
/*
* The driver context...
*/
......@@ -42,6 +36,8 @@ typedef struct
driver_state_t state; /* started/stopped */
int opened; /* tru if open */
int remove_pending;
int max_ps; /* max packet size */
} tiglusb_t, *ptiglusb_t;
#endif
......@@ -651,7 +651,7 @@ static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs)
****************************************************************/
static int kaweth_open(struct net_device *net)
{
struct kaweth_device *kaweth = (struct kaweth_device *)net->priv;
struct kaweth_device *kaweth = netdev_priv(net);
int res;
kaweth_dbg("Opening network device.");
......@@ -689,7 +689,7 @@ static int kaweth_open(struct net_device *net)
****************************************************************/
static int kaweth_close(struct net_device *net)
{
struct kaweth_device *kaweth = net->priv;
struct kaweth_device *kaweth = netdev_priv(net);
netif_stop_queue(net);
......@@ -740,7 +740,7 @@ static void kaweth_usb_transmit_complete(struct urb *urb, struct pt_regs *regs)
****************************************************************/
static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
{
struct kaweth_device *kaweth = net->priv;
struct kaweth_device *kaweth = netdev_priv(net);
__le16 *private_header;
int res;
......@@ -811,7 +811,7 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
****************************************************************/
static void kaweth_set_rx_mode(struct net_device *net)
{
struct kaweth_device *kaweth = net->priv;
struct kaweth_device *kaweth = netdev_priv(net);
__u16 packet_filter_bitmap = KAWETH_PACKET_FILTER_DIRECTED |
KAWETH_PACKET_FILTER_BROADCAST |
......@@ -868,7 +868,8 @@ static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth)
****************************************************************/
static struct net_device_stats *kaweth_netdev_stats(struct net_device *dev)
{
return &((struct kaweth_device *)dev->priv)->stats;
struct kaweth_device *kaweth = netdev_priv(dev);
return &kaweth->stats;
}
/****************************************************************
......@@ -876,7 +877,7 @@ static struct net_device_stats *kaweth_netdev_stats(struct net_device *dev)
****************************************************************/
static void kaweth_tx_timeout(struct net_device *net)
{
struct kaweth_device *kaweth = net->priv;
struct kaweth_device *kaweth = netdev_priv(net);
kaweth_warn("%s: Tx timed out. Resetting.", net->name);
kaweth->stats.tx_errors++;
......@@ -911,12 +912,14 @@ static int kaweth_probe(
(int)dev->descriptor.bLength,
(int)dev->descriptor.bDescriptorType);
if(!(kaweth = kmalloc(sizeof(struct kaweth_device), GFP_KERNEL)))
netdev = alloc_etherdev(sizeof(*kaweth));
if (!netdev)
return -ENOMEM;
memset(kaweth, 0, sizeof(struct kaweth_device));
kaweth = netdev_priv(netdev);
kaweth->dev = dev;
kaweth->net = netdev;
spin_lock_init(&kaweth->device_lock);
init_waitqueue_head(&kaweth->term_wait);
......@@ -941,9 +944,7 @@ static int kaweth_probe(
100,
2)) < 0) {
kaweth_err("Error downloading firmware (%d)", result);
free_page((unsigned long)kaweth->firmware_buf);
kfree(kaweth);
return -EIO;
goto err_fw;
}
if ((result = kaweth_download_firmware(kaweth,
......@@ -952,9 +953,7 @@ static int kaweth_probe(
100,
3)) < 0) {
kaweth_err("Error downloading firmware fix (%d)", result);
free_page((unsigned long)kaweth->firmware_buf);
kfree(kaweth);
return -EIO;
goto err_fw;
}
if ((result = kaweth_download_firmware(kaweth,
......@@ -963,9 +962,8 @@ static int kaweth_probe(
126,
2)) < 0) {
kaweth_err("Error downloading trigger code (%d)", result);
free_page((unsigned long)kaweth->firmware_buf);
kfree(kaweth);
return -EIO;
goto err_fw;
}
if ((result = kaweth_download_firmware(kaweth,
......@@ -974,23 +972,20 @@ static int kaweth_probe(
126,
3)) < 0) {
kaweth_err("Error downloading trigger code fix (%d)", result);
free_page((unsigned long)kaweth->firmware_buf);
kfree(kaweth);
return -EIO;
goto err_fw;
}
if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) {
kaweth_err("Error triggering firmware (%d)", result);
free_page((unsigned long)kaweth->firmware_buf);
kfree(kaweth);
return -EIO;
goto err_fw;
}
/* Device will now disappear for a moment... */
kaweth_info("Firmware loaded. I'll be back...");
err_fw:
free_page((unsigned long)kaweth->firmware_buf);
kfree(kaweth);
free_netdev(netdev);
return -EIO;
}
......@@ -998,8 +993,7 @@ static int kaweth_probe(
if(result < 0) {
kaweth_err("Error reading configuration (%d), no net device created", result);
kfree(kaweth);
return -EIO;
goto err_free_netdev;
}
kaweth_info("Statistics collection: %x", kaweth->configuration.statistics_mask);
......@@ -1017,18 +1011,17 @@ static int kaweth_probe(
&bcast_addr,
sizeof(bcast_addr))) {
kaweth_err("Firmware not functioning properly, no net device created");
kfree(kaweth);
return -EIO;
goto err_free_netdev;
}
if(kaweth_set_urb_size(kaweth, KAWETH_BUF_SIZE) < 0) {
kaweth_dbg("Error setting URB size");
goto err_no_netdev;
goto err_free_netdev;
}
if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) {
kaweth_err("Error setting SOFS wait");
goto err_no_netdev;
goto err_free_netdev;
}
result = kaweth_set_receive_filter(kaweth,
......@@ -1038,20 +1031,14 @@ static int kaweth_probe(
if(result < 0) {
kaweth_err("Error setting receive filter");
kfree(kaweth);
return -EIO;
goto err_free_netdev;
}
kaweth_dbg("Initializing net device.");
if (!(netdev = alloc_etherdev(0))) {
kfree(kaweth);
return -ENOMEM;
}
kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!kaweth->tx_urb)
goto err_no_urb;
goto err_free_netdev;
kaweth->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!kaweth->rx_urb)
goto err_only_tx;
......@@ -1072,26 +1059,23 @@ static int kaweth_probe(
if (!kaweth->rx_buf)
goto err_all_but_rxbuf;
kaweth->net = netdev;
memcpy(kaweth->net->broadcast, &bcast_addr, sizeof(bcast_addr));
memcpy(kaweth->net->dev_addr,
&kaweth->configuration.hw_addr,
memcpy(netdev->broadcast, &bcast_addr, sizeof(bcast_addr));
memcpy(netdev->dev_addr, &kaweth->configuration.hw_addr,
sizeof(kaweth->configuration.hw_addr));
kaweth->net->priv = kaweth;
kaweth->net->open = kaweth_open;
kaweth->net->stop = kaweth_close;
netdev->open = kaweth_open;
netdev->stop = kaweth_close;
kaweth->net->watchdog_timeo = KAWETH_TX_TIMEOUT;
kaweth->net->tx_timeout = kaweth_tx_timeout;
netdev->watchdog_timeo = KAWETH_TX_TIMEOUT;
netdev->tx_timeout = kaweth_tx_timeout;
kaweth->net->hard_start_xmit = kaweth_start_xmit;
kaweth->net->set_multicast_list = kaweth_set_rx_mode;
kaweth->net->get_stats = kaweth_netdev_stats;
kaweth->net->mtu = le16_to_cpu(kaweth->configuration.segment_size);
SET_ETHTOOL_OPS(kaweth->net, &ops);
netdev->hard_start_xmit = kaweth_start_xmit;
netdev->set_multicast_list = kaweth_set_rx_mode;
netdev->get_stats = kaweth_netdev_stats;
netdev->mtu = le16_to_cpu(kaweth->configuration.segment_size);
SET_ETHTOOL_OPS(netdev, &ops);
memset(&kaweth->stats, 0, sizeof(kaweth->stats));
/* kaweth is zeroed as part of alloc_netdev */
INIT_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl, (void *)kaweth);
......@@ -1128,10 +1112,9 @@ static int kaweth_probe(
usb_free_urb(kaweth->rx_urb);
err_only_tx:
usb_free_urb(kaweth->tx_urb);
err_no_urb:
err_free_netdev:
free_netdev(netdev);
err_no_netdev:
kfree(kaweth);
return -EIO;
}
......@@ -1141,6 +1124,7 @@ static int kaweth_probe(
static void kaweth_disconnect(struct usb_interface *intf)
{
struct kaweth_device *kaweth = usb_get_intfdata(intf);
struct net_device *netdev;
kaweth_info("Unregistering");
......@@ -1149,7 +1133,7 @@ static void kaweth_disconnect(struct usb_interface *intf)
kaweth_warn("unregistering non-existant device");
return;
}
netdev = kaweth->net;
kaweth->removed = 1;
usb_kill_urb(kaweth->irq_urb);
usb_kill_urb(kaweth->rx_urb);
......@@ -1163,26 +1147,17 @@ static void kaweth_disconnect(struct usb_interface *intf)
spin_unlock(&kaweth->device_lock);
}
if(kaweth->net) {
if(kaweth->net->flags & IFF_UP) {
kaweth_dbg("Closing net device");
dev_close(kaweth->net);
}
kaweth_dbg("Unregistering net device");
unregister_netdev(kaweth->net);
free_netdev(kaweth->net);
}
kaweth_dbg("Unregistering net device");
unregister_netdev(netdev);
usb_free_urb(kaweth->rx_urb);
usb_free_urb(kaweth->tx_urb);
usb_free_urb(kaweth->irq_urb);
usb_buffer_free(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle);
usb_buffer_free(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle);
kfree(kaweth);
free_netdev(netdev);
}
......
......@@ -567,7 +567,7 @@ static void ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 i
static void ax8817x_set_multicast(struct net_device *net)
{
struct usbnet *dev = (struct usbnet *) net->priv;
struct usbnet *dev = netdev_priv(net);
struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
u8 rx_ctl = 0x8c;
......@@ -610,7 +610,7 @@ static void ax8817x_set_multicast(struct net_device *net)
static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc)
{
struct usbnet *dev = netdev->priv;
struct usbnet *dev = netdev_priv(netdev);
u16 res;
u8 buf[1];
......@@ -623,7 +623,7 @@ static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc)
static void ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
{
struct usbnet *dev = netdev->priv;
struct usbnet *dev = netdev_priv(netdev);
u16 res = val;
u8 buf[1];
......@@ -634,7 +634,7 @@ static void ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, i
static void ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
{
struct usbnet *dev = (struct usbnet *)net->priv;
struct usbnet *dev = netdev_priv(net);
u8 opt;
if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
......@@ -654,7 +654,7 @@ static void ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *woli
static int ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
{
struct usbnet *dev = (struct usbnet *)net->priv;
struct usbnet *dev = netdev_priv(net);
u8 opt = 0;
u8 buf[1];
......@@ -675,7 +675,7 @@ static int ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolin
static int ax8817x_get_eeprom(struct net_device *net,
struct ethtool_eeprom *eeprom, u8 *data)
{
struct usbnet *dev = (struct usbnet *)net->priv;
struct usbnet *dev = netdev_priv(net);
u16 *ebuf = (u16 *)data;
int i;
......@@ -704,14 +704,14 @@ static void ax8817x_get_drvinfo (struct net_device *net,
static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
{
struct usbnet *dev = (struct usbnet *)net->priv;
struct usbnet *dev = netdev_priv(net);
return mii_ethtool_gset(&dev->mii,cmd);
}
static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
{
struct usbnet *dev = (struct usbnet *)net->priv;
struct usbnet *dev = netdev_priv(net);
return mii_ethtool_sset(&dev->mii,cmd);
}
......@@ -2276,7 +2276,7 @@ static const struct driver_info zaurus_pxa_info = {
static int usbnet_change_mtu (struct net_device *net, int new_mtu)
{
struct usbnet *dev = (struct usbnet *) net->priv;
struct usbnet *dev = netdev_priv(net);
if (new_mtu <= MIN_PACKET || new_mtu > MAX_PACKET)
return -EINVAL;
......@@ -2302,7 +2302,8 @@ static int usbnet_change_mtu (struct net_device *net, int new_mtu)
static struct net_device_stats *usbnet_get_stats (struct net_device *net)
{
return &((struct usbnet *) net->priv)->stats;
struct usbnet *dev = netdev_priv(net);
return &dev->stats;
}
/*-------------------------------------------------------------------------*/
......@@ -2569,7 +2570,7 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
static int usbnet_stop (struct net_device *net)
{
struct usbnet *dev = (struct usbnet *) net->priv;
struct usbnet *dev = netdev_priv(net);
int temp;
DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup);
DECLARE_WAITQUEUE (wait, current);
......@@ -2616,7 +2617,7 @@ static int usbnet_stop (struct net_device *net)
static int usbnet_open (struct net_device *net)
{
struct usbnet *dev = (struct usbnet *) net->priv;
struct usbnet *dev = netdev_priv(net);
int retval = 0;
struct driver_info *info = dev->driver_info;
......@@ -2666,7 +2667,7 @@ static int usbnet_open (struct net_device *net)
static void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
{
struct usbnet *dev = net->priv;
struct usbnet *dev = netdev_priv(net);
strncpy (info->driver, driver_name, sizeof info->driver);
strncpy (info->version, DRIVER_VERSION, sizeof info->version);
......@@ -2677,7 +2678,7 @@ static void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *
static u32 usbnet_get_link (struct net_device *net)
{
struct usbnet *dev = net->priv;
struct usbnet *dev = netdev_priv(net);
/* If a check_connect is defined, return it's results */
if (dev->driver_info->check_connect)
......@@ -2689,14 +2690,14 @@ static u32 usbnet_get_link (struct net_device *net)
static u32 usbnet_get_msglevel (struct net_device *net)
{
struct usbnet *dev = net->priv;
struct usbnet *dev = netdev_priv(net);
return dev->msg_level;
}
static void usbnet_set_msglevel (struct net_device *net, u32 level)
{
struct usbnet *dev = net->priv;
struct usbnet *dev = netdev_priv(net);
dev->msg_level = level;
}
......@@ -2705,7 +2706,7 @@ static int usbnet_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
{
#ifdef NEED_MII
{
struct usbnet *dev = (struct usbnet *)net->priv;
struct usbnet *dev = netdev_priv(net);
if (dev->mii.mdio_read != NULL && dev->mii.mdio_write != NULL)
return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
......@@ -2817,7 +2818,7 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs)
static void usbnet_tx_timeout (struct net_device *net)
{
struct usbnet *dev = (struct usbnet *) net->priv;
struct usbnet *dev = netdev_priv(net);
unlink_urbs (dev, &dev->txq);
tasklet_schedule (&dev->bh);
......@@ -2829,7 +2830,7 @@ static void usbnet_tx_timeout (struct net_device *net)
static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
{
struct usbnet *dev = (struct usbnet *) net->priv;
struct usbnet *dev = netdev_priv(net);
int length;
int retval = NET_XMIT_SUCCESS;
struct urb *urb = NULL;
......@@ -3014,6 +3015,7 @@ static void usbnet_disconnect (struct usb_interface *intf)
{
struct usbnet *dev;
struct usb_device *xdev;
struct net_device *net;
dev = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
......@@ -3026,7 +3028,8 @@ static void usbnet_disconnect (struct usb_interface *intf)
xdev->bus->bus_name, xdev->devpath,
dev->driver_info->description);
unregister_netdev (dev->net);
net = dev->net;
unregister_netdev (net);
/* we don't hold rtnl here ... */
flush_scheduled_work ();
......@@ -3034,8 +3037,7 @@ static void usbnet_disconnect (struct usb_interface *intf)
if (dev->driver_info->unbind)
dev->driver_info->unbind (dev, intf);
free_netdev(dev->net);
kfree (dev);
free_netdev(net);
usb_put_dev (xdev);
}
......@@ -3069,12 +3071,13 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
status = -ENOMEM;
// set up our own records
if (!(dev = kmalloc (sizeof *dev, GFP_KERNEL))) {
net = alloc_etherdev(sizeof(*dev));
if (!net) {
dbg ("can't kmalloc dev");
goto out;
}
memset (dev, 0, sizeof *dev);
dev = netdev_priv(net);
dev->udev = xdev;
dev->driver_info = info;
dev->msg_level = msg_level;
......@@ -3088,14 +3091,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
dev->delay.data = (unsigned long) dev;
init_timer (&dev->delay);
// set up network interface records
net = alloc_etherdev(0);
if (!net)
goto out1;
SET_MODULE_OWNER (net);
dev->net = net;
net->priv = dev;
strcpy (net->name, "usb%d");
memcpy (net->dev_addr, node_id, sizeof node_id);
......@@ -3144,8 +3141,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
SET_NETDEV_DEV(dev->net, &udev->dev);
status = register_netdev (dev->net);
SET_NETDEV_DEV(net, &udev->dev);
status = register_netdev (net);
if (status)
goto out3;
devinfo (dev, "register usbnet at usb-%s-%s, %s",
......@@ -3156,16 +3153,15 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
usb_set_intfdata (udev, dev);
// start as if the link is up
netif_device_attach (dev->net);
netif_device_attach (net);
return 0;
out3:
if (info->unbind)
info->unbind (dev, udev);
free_netdev(net);
out1:
kfree(dev);
free_netdev(net);
out:
usb_put_dev(xdev);
return status;
......@@ -3252,6 +3248,10 @@ static const struct usb_device_id products [] = {
// Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter"
USB_DEVICE (0x6189, 0x182d),
.driver_info = (unsigned long) &ax8817x_info,
}, {
// corega FEther USB2-TX
USB_DEVICE (0x07aa, 0x0017),
.driver_info = (unsigned long) &ax8817x_info,
}, {
// Surecom EP-1427X-2
USB_DEVICE (0x1189, 0x0893),
......
......@@ -607,6 +607,7 @@ module_exit (belkin_sa_exit);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_VERSION( DRIVER_VERSION );
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
......
......@@ -502,6 +502,7 @@ module_exit(cyberjack_exit);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_VERSION( DRIVER_VERSION );
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
......
......@@ -90,6 +90,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) },
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) },
{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
{ USB_DEVICE(PHAROS_VENDOR_ID, PHAROS_PRODUCT_ID) },
{ } /* Terminating entry */
};
......@@ -1188,6 +1189,7 @@ module_init(pl2303_init);
module_exit(pl2303_exit);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
......
......@@ -50,3 +50,6 @@
#define SAMSUNG_VENDOR_ID 0x04e8
#define SAMSUNG_PRODUCT_ID 0x8001
/* Pharos / Microsoft GPS puck */
#define PHAROS_VENDOR_ID 0x067b
#define PHAROS_PRODUCT_ID 0xaaa0
......@@ -452,18 +452,12 @@ static void destroy_serial(struct kref *kref)
port = serial->port[i];
if (!port)
continue;
if (port->read_urb) {
usb_kill_urb(port->read_urb);
usb_free_urb(port->read_urb);
}
if (port->write_urb) {
usb_kill_urb(port->write_urb);
usb_free_urb(port->write_urb);
}
if (port->interrupt_in_urb) {
usb_kill_urb(port->interrupt_in_urb);
usb_free_urb(port->interrupt_in_urb);
}
usb_kill_urb(port->read_urb);
usb_free_urb(port->read_urb);
usb_kill_urb(port->write_urb);
usb_free_urb(port->write_urb);
usb_kill_urb(port->interrupt_in_urb);
usb_free_urb(port->interrupt_in_urb);
kfree(port->bulk_in_buffer);
kfree(port->bulk_out_buffer);
kfree(port->interrupt_in_buffer);
......@@ -799,18 +793,12 @@ static void port_release(struct device *dev)
struct usb_serial_port *port = to_usb_serial_port(dev);
dbg ("%s - %s", __FUNCTION__, dev->bus_id);
if (port->read_urb) {
usb_kill_urb(port->read_urb);
usb_free_urb(port->read_urb);
}
if (port->write_urb) {
usb_kill_urb(port->write_urb);
usb_free_urb(port->write_urb);
}
if (port->interrupt_in_urb) {
usb_kill_urb(port->interrupt_in_urb);
usb_free_urb(port->interrupt_in_urb);
}
usb_kill_urb(port->read_urb);
usb_free_urb(port->read_urb);
usb_kill_urb(port->write_urb);
usb_free_urb(port->write_urb);
usb_kill_urb(port->interrupt_in_urb);
usb_free_urb(port->interrupt_in_urb);
kfree(port->bulk_in_buffer);
kfree(port->bulk_out_buffer);
kfree(port->interrupt_in_buffer);
......
......@@ -381,10 +381,17 @@ static struct usb_serial_device_type clie_3_5_device = {
.read_bulk_callback = visor_read_bulk_callback,
};
struct visor_private {
spinlock_t lock;
int bytes_in;
int bytes_out;
int outstanding_urbs;
};
static int bytes_in;
static int bytes_out;
/* number of outstanding urbs to prevent userspace DoS from happening */
#define URB_UPPER_LIMIT 42
static int stats;
/******************************************************************************
* Handspring Visor specific driver functions
......@@ -392,6 +399,8 @@ static int bytes_out;
static int visor_open (struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int result = 0;
dbg("%s - port %d", __FUNCTION__, port->number);
......@@ -402,8 +411,11 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
return -ENODEV;
}
bytes_in = 0;
bytes_out = 0;
spin_lock_irqsave(&priv->lock, flags);
priv->bytes_in = 0;
priv->bytes_out = 0;
priv->outstanding_urbs = 0;
spin_unlock_irqrestore(&priv->lock, flags);
/*
* Force low_latency on so that our tty_push actually forces the data
......@@ -441,6 +453,7 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
static void visor_close (struct usb_serial_port *port, struct file * filp)
{
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned char *transfer_buffer;
dbg("%s - port %d", __FUNCTION__, port->number);
......@@ -461,20 +474,32 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
kfree (transfer_buffer);
}
/* Uncomment the following line if you want to see some statistics in your syslog */
/* dev_info (&port->dev, "Bytes In = %d Bytes Out = %d\n", bytes_in, bytes_out); */
if (stats)
dev_info(&port->dev, "Bytes In = %d Bytes Out = %d\n",
priv->bytes_in, priv->bytes_out);
}
static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct visor_private *priv = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
struct urb *urb;
unsigned char *buffer;
unsigned long flags;
int status;
dbg("%s - port %d", __FUNCTION__, port->number);
spin_lock_irqsave(&priv->lock, flags);
if (priv->outstanding_urbs > URB_UPPER_LIMIT) {
spin_unlock_irqrestore(&priv->lock, flags);
dev_dbg(&port->dev, "write limit hit\n");
return 0;
}
++priv->outstanding_urbs;
spin_unlock_irqrestore(&priv->lock, flags);
buffer = kmalloc (count, GFP_ATOMIC);
if (!buffer) {
dev_err(&port->dev, "out of memory\n");
......@@ -506,7 +531,10 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
count = status;
kfree (buffer);
} else {
bytes_out += count;
spin_lock_irqsave(&priv->lock, flags);
++priv->outstanding_urbs;
priv->bytes_out += count;
spin_unlock_irqrestore(&priv->lock, flags);
}
/* we are done with this urb, so let the host driver
......@@ -547,6 +575,8 @@ static int visor_chars_in_buffer (struct usb_serial_port *port)
static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree (urb->transfer_buffer);
......@@ -557,6 +587,10 @@ static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
dbg("%s - nonzero write bulk status received: %d",
__FUNCTION__, urb->status);
spin_lock_irqsave(&priv->lock, flags);
--priv->outstanding_urbs;
spin_unlock_irqrestore(&priv->lock, flags);
schedule_work(&port->work);
}
......@@ -564,8 +598,10 @@ static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct tty_struct *tty;
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
struct tty_struct *tty;
unsigned long flags;
int i;
int result;
......@@ -590,7 +626,9 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
}
tty_flip_buffer_push(tty);
}
bytes_in += urb->actual_length;
spin_lock_irqsave(&priv->lock, flags);
priv->bytes_in += urb->actual_length;
spin_unlock_irqrestore(&priv->lock, flags);
/* Continue trying to always read */
usb_fill_bulk_urb (port->read_urb, port->serial->dev,
......@@ -825,6 +863,22 @@ static int visor_calc_num_ports (struct usb_serial *serial)
return num_ports;
}
static int generic_startup(struct usb_serial *serial)
{
struct visor_private *priv;
int i;
for (i = 0; i < serial->num_ports; ++i) {
priv = kmalloc (sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
memset (priv, 0x00, sizeof(*priv));
spin_lock_init(&priv->lock);
usb_set_serial_port_data(serial->port[i], priv);
}
return 0;
}
static int clie_3_5_startup (struct usb_serial *serial)
{
struct device *dev = &serial->dev->dev;
......@@ -864,7 +918,7 @@ static int clie_3_5_startup (struct usb_serial *serial)
return -EIO;
}
return 0;
return generic_startup(serial);
}
static int treo_attach (struct usb_serial *serial)
......@@ -903,7 +957,7 @@ static int treo_attach (struct usb_serial *serial)
COPY_PORT(serial->port[1], swap_port);
kfree(swap_port);
return 0;
return generic_startup(serial);
}
static int clie_5_attach (struct usb_serial *serial)
......@@ -924,7 +978,7 @@ static int clie_5_attach (struct usb_serial *serial)
/* port 0 now uses the modified endpoint Address */
serial->port[0]->bulk_out_endpointAddress = serial->port[1]->bulk_out_endpointAddress;
return 0;
return generic_startup(serial);
}
static void visor_shutdown (struct usb_serial *serial)
......@@ -1080,8 +1134,11 @@ MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
module_param(stats, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(stats, "Enables statistics or not");
module_param(vendor, ushort, 0);
MODULE_PARM_DESC(vendor, "User specified vendor ID");
module_param(product, ushort, 0);
MODULE_PARM_DESC(product, "User specified product ID");
......@@ -175,7 +175,7 @@ static int queuecommand(struct scsi_cmnd *srb,
US_DEBUGP("%s called\n", __FUNCTION__);
srb->host_scribble = (unsigned char *)us;
/* enqueue the command */
/* check for state-transition errors */
if (us->sm_state != US_STATE_IDLE || us->srb != NULL) {
printk(KERN_ERR USB_STORAGE "Error in %s: "
"state = %d, us->srb = %p\n",
......@@ -183,10 +183,17 @@ static int queuecommand(struct scsi_cmnd *srb,
return SCSI_MLQUEUE_HOST_BUSY;
}
/* fail the command if we are disconnecting */
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
US_DEBUGP("Fail command during disconnect\n");
srb->result = DID_NO_CONNECT << 16;
done(srb);
return 0;
}
/* enqueue the command and wake up the control thread */
srb->scsi_done = done;
us->srb = srb;
/* wake up the process task */
up(&(us->sema));
return 0;
......
......@@ -193,6 +193,7 @@ static inline void proc_net_remove(const char *name)
#define proc_root_driver NULL
#define proc_net NULL
#define proc_bus NULL
#define proc_net_fops_create(name, mode, fops) ({ (void)(mode), NULL; })
#define proc_net_create(name, mode, info) ({ (void)(mode), NULL; })
......
......@@ -38,5 +38,7 @@
#define IOCTL_TIUSB_TIMEOUT _IOW('N', 0x20, int) /* set timeout */
#define IOCTL_TIUSB_RESET_DEVICE _IOW('N', 0x21, int) /* reset device */
#define IOCTL_TIUSB_RESET_PIPES _IOW('N', 0x22, int) /* reset both pipes*/
#define IOCTL_TIUSB_GET_MAXPS _IOR('N', 0x23, int) /* max packet size */
#define IOCTL_TIUSB_GET_DEVID _IOR('N', 0x24, int) /* get device type */
#endif /* TICABLE_H */
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