Commit 1d3f1e5e authored by Linus Torvalds's avatar Linus Torvalds

Import 2.3.99pre4-5

parent 96d333c6
......@@ -1570,6 +1570,15 @@ S: 2200 Mission College Blvd
S: Santa Clara, CA 95052
S: USA
N: Petko Manolov
E: petkan@spct.net
D: USB ethernet (pegasus) driver
D: optimizing i[45]86 string routines
D: i386 task swithing hacks
S: 5, Vrah Mancho str.
S: 1324 Sofia
S: Bulgaria
N: Martin Mares
E: mj@suse.cz
E: mj@ucw.cz
......
......@@ -9680,11 +9680,18 @@ CONFIG_USB_OV511
USB ADMtek Pegasus-based ethernet device support
CONFIG_USB_PEGASUS
Say Y if you want to use your USB ethernet device. Note that
the code is still experimental. If you have devices with vendor
IDs other than ADMtek's, you should change/add them in the
driver code and send a message to me (petkan@spct.net) for
update.
Say Y if you want to use your USB ethernet device. Supported
cards until now are:
Accton 10/100
Billington USB-100
Corega FEter USB-TX
MELCO/BUFFALO LUA-TX
D-Link DSB-650TX, DSB-650TX-PNA
Linksys USB100TX
SNC 202
If you have devices with vendor IDs other than noted above
you should add them in the driver code and send a message
to me (petkan@spct.net) for update.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
......
The ACM driver works with modems and ISDN TAs that use the USB Abstract
Control Model standard.
****************************
Test it:
Watch out, the driver is not stable and tested. Sync often, make backups,
most importand: don't blame me...
Create device files:
mknod /dev/ttyACM0 c 166 0
mknod /dev/ttyACM1 c 166 1
mknod /dev/ttyACM2 c 166 2
mknod /dev/ttyACM3 c 166 3
Compile a kernel with support for your host controller (uhci only for now!)
and support for ACM. Boot this kernel. If you connect your device to the
USB bus you should see messages like the following:
Jul 19 20:14:29 office kernel: USB new device connect, assigned device number 1
Jul 19 20:14:29 office kernel: Found 02:09
Jul 19 20:14:29 office kernel: Found 04:09
Jul 19 20:14:29 office kernel: Found 05:07
Jul 19 20:14:29 office last message repeated 2 times
Jul 19 20:14:29 office kernel: parsed = 39 len = 67
Jul 19 20:14:29 office kernel: Expected descriptor 04/09, got 02/09 - skipping
Jul 19 20:14:29 office kernel: 0 09
Jul 19 20:14:29 office kernel: 1 02
Jul 19 20:14:29 office kernel: 2 43
Jul 19 20:14:29 office kernel: 3 00
Jul 19 20:14:29 office kernel: 4 02
Jul 19 20:14:29 office kernel: 5 02
Jul 19 20:14:29 office kernel: 6 04
Jul 19 20:14:29 office kernel: 7 60
Jul 19 20:14:29 office kernel: 8 00
Jul 19 20:14:29 office kernel: Found 04:09
Jul 19 20:14:29 office kernel: Found 02:09
Jul 19 20:14:29 office kernel: Found 04:09
Jul 19 20:14:29 office kernel: Found 05:07
Jul 19 20:14:29 office kernel: Found 04:09
Jul 19 20:14:29 office kernel: Found 05:07
Jul 19 20:14:29 office kernel: Found 05:07
Jul 19 20:14:29 office kernel: parsed = 67 len = 0
Jul 19 20:14:29 office kernel: getstringtable
Jul 19 20:14:29 office kernel: acm_probe
Jul 19 20:14:29 office kernel: USB ACM found
Watch out for the line:
Jul 19 20:14:29 office kernel: USB new device connect, assigned device number 1
and the line:
Jul 19 20:14:29 office kernel: USB ACM found
These two lines show that the device was seen by the usb host controller and
then recognized by the acm driver as a valid device.
If you use a terminal emulation software like minicom with /dev/ttyACM0 you
should be able to send AT commands to your device and get responses. I've
been able to do zmodem downloads to another pc. However downloads from one
ISDN TA to another ISDN TA connected to the same PC didn't work. Don't
know why. Flow control is not finised after all and i'd guess there might
be problems on heavily loades PCs. I also did some tests with ppp but i'm
not finised with this. There might be a chance to get it working. However
i'd like to know if your device is recognized as an ACM device. I'm also
interested if the thing is stable or if it crashes.
(should i say how it crases?)
You should be able to add and remove devices from the bus. The driver will
always try to fill up unused ttys. This means if you hotplug devices their
order may have changed after reboot. This is not the behaviour Linus liked
to see but it's ok for now. (I hope ;-)
Please report your experiences to me:
fuerst@in.tum.de
***************************
I've tested it with:
3Com ISDN Pro TA.
It should work with (That means i know these devices conform to ACM):
3Com Office Connect Modem
3Com Sportster USB (I think that's what it's called)
***************************
Many thanks to 3Com which did not only support me with hardware but also
with technical support in USB questions. They also allowed me to do tests in
their lab. Great!
***************************
Known bugs:
Flow control not tested (likely not to work)
Some tty function calls not implemented (putchar, etc...)
Huge amounts of debug output (compile in [*] Magic SysRq key and press ALT+PRTSCR+0 )
Not all mem is freed at close (need terminate irq in hcd)
***************************
Have fun,
Armin Fuerst
Linux ACM driver v0.16
(c) 1999 Vojtech Pavlik <vojtech@suse.cz>
Sponsored by SuSE
----------------------------------------------------------------------------
0. Disclaimer
~~~~~~~~~~~~~
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place, Suite 330, Boston, MA 02111-1307 USA
Should you need to contact me, the author, you can do so either by e-mail
- mail your message to <vojtech@suse.cz>, or by paper mail: Vojtech Pavlik,
Ucitelska 1576, Prague 8, 182 00 Czech Republic
For your convenience, the GNU General Public License version 2 is included
in the package: See the file COPYING.
1. Usage
~~~~~~~~
The drivers/usb/acm.c drivers works with USB modems and USB ISDN terminal
adapters that conform to the Universal Serial Bus Communication Device Class
Abstract Control Model (USB CDC ACM) specification.
Many modems do, here is a list of those I know of:
3Com OfficeConnect 56k
3Com Voice FaxModem Pro
3Com Sportster
MultiTech MultiModem 56k
Zoom 2986L FaxModem
Compaq 56k FaxModem
ELSA Microlink 56k
I know of one ISDN TA that does work with the acm driver:
3Com USR ISDN Pro TA
Unfortunately many modems and most ISDN TAs use proprietary interfaces and
thus won't work with this drivers. Check for ACM compliance before buying.
The driver (with devfs) creates these devices in /dev/usb/acm:
crw-r--r-- 1 root root 166, 0 Apr 1 10:49 0
crw-r--r-- 1 root root 166, 1 Apr 1 10:49 1
crw-r--r-- 1 root root 166, 2 Apr 1 10:49 2
And so on, up to 31, with the limit being possible to change in acm.c to up
to 256, so you can use up to 256 USB modems with one computer (you'll need
three USB cards for that, though).
If you don't use devfs, then you can create device nodes with the same
minor/major numbers anywhere you want, but either the above location or
/dev/usb/ttyACM0 is preferred.
To use the modems you need these modules loaded:
usbcore.o
usb-[uo]hci.o or uhci.o
acm.o
After that, the modem[s] should be accessible. You should be able to use
minicom, ppp and mgetty with them.
2. Verifying that it works
~~~~~~~~~~~~~~~~~~~~~~~~~~
The first step would be to check /proc/bus/usb/devices, it should look
like this:
T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
B: Alloc= 0/900 us ( 0%), #Int= 0, #Iso= 0
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0000 ProdID=0000 Rev= 0.00
S: Product=USB UHCI Root Hub
S: SerialNumber=6800
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
D: Ver= 1.00 Cls=02(comm.) Sub=00 Prot=00 MxPS= 8 #Cfgs= 2
P: Vendor=04c1 ProdID=008f Rev= 2.07
S: Manufacturer=3Com Inc.
S: Product=3Com U.S. Robotics Pro ISDN TA
S: SerialNumber=UFT53A49BVT7
C: #Ifs= 1 Cfg#= 1 Atr=60 MxPwr= 0mA
I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=acm
E: Ad=85(I) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=128ms
C:* #Ifs= 2 Cfg#= 2 Atr=60 MxPwr= 0mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=01 Driver=acm
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=128ms
I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=acm
E: Ad=85(I) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
The presence of these three lines (and the Cls= 'comm' and 'data' classes)
is important, it means it's an ACM device. The Driver=acm means the acm
driver is used for the device. If you see only Cls=ff(vend.) then you're out
of luck, you have a device with vendor specific-interface.
D: Ver= 1.00 Cls=02(comm.) Sub=00 Prot=00 MxPS= 8 #Cfgs= 2
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=01 Driver=acm
I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=acm
In the system log you should see:
usb.c: USB new device connect, assigned device number 2
usb.c: kmalloc IF c7691fa0, numif 1
usb.c: kmalloc IF c7b5f3e0, numif 2
usb.c: skipped 4 class/vendor specific interface descriptors
usb.c: new device strings: Mfr=1, Product=2, SerialNumber=3
usb.c: USB device number 2 default language ID 0x409
Manufacturer: 3Com Inc.
Product: 3Com U.S. Robotics Pro ISDN TA
SerialNumber: UFT53A49BVT7
acm.c: probing config 1
acm.c: probing config 2
ttyACM0: USB ACM device
acm.c: acm_control_msg: rq: 0x22 val: 0x0 len: 0x0 result: 0
acm.c: acm_control_msg: rq: 0x20 val: 0x0 len: 0x7 result: 7
usb.c: acm driver claimed interface c7b5f3e0
usb.c: acm driver claimed interface c7b5f3f8
usb.c: acm driver claimed interface c7691fa0
If all this seems to be OK, fire up minicom and set it to talk to the ttyACM
device and try typing 'at'. If it responds with 'OK', then everything is
working.
Linux HID driver v0.8
(c) 1999 Vojtech Pavlik <vojtech@suse.cz>
(c) 1999 Andreas Gal <agal@uwsp.edu>
Sponsored by SuSE
----------------------------------------------------------------------------
0. Disclaimer
~~~~~~~~~~~~~
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place, Suite 330, Boston, MA 02111-1307 USA
Should you need to contact me, the author, you can do so either by e-mail
- mail your message to <vojtech@suse.cz>, or by paper mail: Vojtech Pavlik,
Ucitelska 1576, Prague 8, 182 00 Czech Republic
For your convenience, the GNU General Public License version 2 is included
in the package: See the file COPYING.
1. Introduction
~~~~~~~~~~~~~~~
This is a driver for USB devices conforming to the USB HID (Human Input
Device) standard. These devices include namely keyboards, mice and
joysticks.
However many other devices (monitors, speakers, UPSs ...) also communicate
through the same protocol, which makes its specification somewhat bloated.
This isn't a problem, though, because the driver doesn't need to know about
all the possible devices it can control, and can just parse the protocol and
leave the rest of the job (for example understanding what the UPS wants to
say) to the userland.
Because of this, the USB HID driver has two interfaces. One is via the
proc filesystem, allowing userland applications send and read arbitrary
reports to and from a connected USB device. The other is via a very simple
yet generic input device driver, which dispatches input events (keystrokes,
mouse or joystick movements) to specific, backward compatible userland
interfaces. This way a PS/2 mouse, an AT keyboard or a Linux joystick driver
interface are emulated, and allow applications to immediately work with USB
mice, USB keyboards and USB joysticks without any changes.
The input driver is aimed for a little more than USB device handling in
the future, though. It's generic enough so that it can be used for any
mouse, keyboard or joystick (and more, of course). A PS/2 mouse driver, a
serial mouse, Sun mouse, and most of the busmouse drivers were rewritten to
use this as well as the AT keyboard and Sun keyboard drivers. This will
hopefully allow conversion of all Linux keyboard and mouse and joystick
drivers to this scheme.
This effort has it's home page at:
http://www.suse.cz/development/input/
You'll find both the latest HID driver and the complete Input driver there.
There is also a mailing list for this:
listproc@atrey.karlin.mff.cuni.cz
Send "subscribe linux-joystick Your Name" to subscribe to it.
2. Usage
~~~~~~~~
Since the driver comes with recent 2.3 kernels, all that's needed to use
it is to enable it either as a module or compiled-in into the kernel.
After that, after reboot (and possibly also inserting the USB and HID
modules) the following will happen:
* If you selected keyboard support, all USB keystrokes will be also routed
to the Linux keyboard driver as if being input through the ordinary system
keyboard.
* If you selected mouse support, there will be (one or more) simulated PS/2
mouse devices on major 10, minor 32, 33 and more. These simulated mice can
in addition to a standard 3-button PS/2 mouse behave like MS Intellimice,
with a wheel. If you want to use the wheel, just specify '-t imps2' to gpm
and 'Protocol "ImPS/2"' to X, and it will work. A single emulated mouse
device can be open by any number of processes (unlike the /dev/psaux), and
for each of them the emulation is separate, each can use a different mode.
The mousedev driver, which emulates the mice, can also emulate a Genius
NewScroll 5 buttons-and-a-wheel mouse, if you set it to a Genius PS/2
mode ('-t netmouse' 'Protocol "NetMousePS/2"'). However, not gpm, nor X
can decode the 5 buttons yet, so this isn't very useful right now.
* If you selected joystick support, the driver will take over major 15, the
joystick major number, and will emulate joysticks on it. This means the
normal joystick driver can't be used together with it (now, after the
normal joystick drivers are converted to the input scheme, all will work
nicely together). Also, you'll probably need to calibrate your joystick
manually ('man jscal') to be able to use it, because the USB
autocalibration is far from perfect yet.
* If you selected event device support, there will be devices on major 10,
minors 64, 65 and more for each input device connected through this
driver. These devices output raw events the input driver dispatches. Each
has a timestamp. This hopefully will be THE way X will talk to keyboard
and mice, because it's hardware independent, and not limited by existing
de-facto standards.
3. Verifying if it works
~~~~~~~~~~~~~~~~~~~~~~~~
Typing a couple keys on the keyboard should be enough to check that a USB
keyboard works and is correctly connected to the kernel keyboard driver.
Doing a cat /dev/hidmouse (c, 10, 32) will verify that a mouse is also
emulated, characters should appear if you move it.
You can test the joystick emulation with the 'jstest' utility, available
in the joystick package (see Documentation/joystick.txt).
You can test the event devics with the 'evtest' utitily available on the
input driver homepage (see the URL above).
4. FAQ
~~~~~~
Q: Why aren't any questions here yet?
A: Because none were frequent enough yet.
5. Event interface
~~~~~~~~~~~~~~~~~~
Should you want to add event device support into any application (X, gpm,
svgalib ...) I (vojtech@suse.cz) will be happy to provide you any help I
can. Here goes a description of the current state of things, which is going
to be extended, but not changed incompatibly as time goes:
You can use blocking and nonblocking reads, also select() on the
/dev/inputX devices, and you'll always get a whole number of input events on
a read. Their layout is:
struct input_event {
struct timeval time;
unsigned short type;
unsigned short code;
unsigned int value;
};
'time' is the timestamp, it returns the time at which the event happened.
Type is for example EV_REL for relative momement, REL_KEY for a keypress or
release. More types are defined in include/linux/input.h.
'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete
list is in include/linux/input.h.
'value' is the value the event carries. Either a relative change for
EV_REL, absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for
release, 1 for keypress and 2 for autorepeat.
6. Proc interface
~~~~~~~~~~~~~~~~~
For HID-specific devices there is also the /proc interface. It isn't
present in this release yet, though, so it's description will appear here
together with the code in the driver.
This diff is collapsed.
......@@ -5,44 +5,17 @@ Readme for Linux device driver for the OmniVision OV511 USB to camera bridge IC
Author: Mark McClelland
Homepage: http://alpha.dyndns.org/ov511
NEW IN THIS VERSION:
o Support for OV511+
o Support for OV7620
INTRODUCTION:
This is a preliminary version of my OV511 Linux device driver. Currently, it can
grab a frame in color (YUV420) at 640x480 or 320x240 using either vidcat or
xawtv. Other utilities may work but have not yet been tested.
NEW IN THIS VERSION:
o Autoadjust disable works, but is not perfect yet
o Partial support for OV511+
o Detection and support for OV7610, OV7620, and OV7620AE sensors
o Various code cleanups and improvements
KNOWN CAMERAS:
____________________________________________________________________
Manufacturer | Model | ID | Bridge | Sensor | Status
--------------+-----------------+-----+--------+----------+-----------
MediaForte | MV300 | 0 | OV511 | OV7610 * | Working
Aiptek | HyperVCam ? | 0 | OV511 | OV7610 * | Working
NetView | NV300M | 0 | OV511 | OV7610 * | Working
D-Link | DSB-C300 | 3 | OV511 | OV7620AE | Working
Hawking Tech. | ??? | 3 | OV511 | OV7610 * | Working
??? | Generic | 4 | OV511 | OV7610 * | Untested
Puretek | PT-6007 | 5 | OV511 | OV7610 * | Working
Creative Labs | WebCam 3 | 21 | OV511 | OV7610 * | Working
??? | Koala-Cam | 36 | OV511 | OV7610 * | Untested
Lifeview | USB Life TV | 38 | OV511 | N/A | Unsupported
Lifeview | RoboCam | 100 | OV511 | OV7610 * | Untested
AverMedia | InterCam Elite | 102 | OV511 | OV7610 * | Working
MediaForte | MV300 | 112 | OV511 | OV7610 * | Working
Omnivision | OV7110 EV board | 112 | OV511 | OV7110 | Working
---------------------------------------------------------------------
(*) These have not been verified. If you have one of these, please report
the sensor type to me.
NOTE - the OV511+ is not yet supported
Any camera using the OV511 and the OV7610 or OV7620AE CCD should work. The
Any camera using the OV511/OV511+ and the OV7610/20/20AE CCD should work. The
driver only detects known cameras though, based on their custom id number. If
you have a currently unsupported camera, the ID number should be reported to you
in the kernel logs. Please send me the model, manufacturer and ID number and I
......@@ -183,7 +156,6 @@ EXPERIMENTAL FEATURES:
o fix_rgb_offset: Sometimes works, but other times causes errors with xawtv and
corrupted frames.
o Snapshot mode (only works with some read() based apps; see below for more)
o OV511+ support; not complete yet.
TODO:
o Fix the noise / grainy image problem.
......@@ -201,7 +173,6 @@ TODO:
o Get hue (red/blue channel balance) adjustment working (in ov511_get_picture()
and ov511_set_picture())
o Get autoadjust disable working
o OV7620 support
o V4L2 support (Probably not until it goes into the kernel)
o Fix I2C initialization. Some people are reporting problems with reading the
7610 registers. This could be due to timing differences, an excessive I2C
......
......@@ -822,8 +822,8 @@ W: http://www-jcr.lmh.ox.ac.uk/~pnp/
S: Maintained
PPP PROTOCOL DRIVERS AND COMPRESSORS
P: Al Longyear
M: longyear@pobox.com
P: Paul Mackerras
M: paulus@linuxcare.com
L: linux-ppp@vger.rutgers.edu
S: Maintained
......
......@@ -44,11 +44,17 @@ if [ "$CONFIG_M486" = "y" -o "$CONFIG_M586" = "y" ]; then
define_bool CONFIG_X86_USE_STRING_486 y
define_bool CONFIG_X86_ALIGNMENT_16 y
fi
if [ "$CONFIG_M586TSC" = "y" -o "$CONFIG_MK6" = "y" ]; then
if [ "$CONFIG_M586TSC" = "y" ]; then
define_bool CONFIG_X86_USE_STRING_486 y
define_bool CONFIG_X86_ALIGNMENT_16 y
define_bool CONFIG_X86_TSC y
fi
if [ "$CONFIG_MK6" = "y" ]; then
define_bool CONFIG_X86_ALIGNMENT_16 y
define_bool CONFIG_X86_TSC y
define_bool CONFIG_X86_USE_3DNOW y
define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
fi
if [ "$CONFIG_M686" = "y" ]; then
define_bool CONFIG_X86_TSC y
define_bool CONFIG_X86_GOOD_APIC y
......
This diff is collapsed.
......@@ -311,21 +311,19 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
if (!acm || !acm->used) return;
MOD_DEC_USE_COUNT;
if (--acm->used) return;
if (acm->dev) {
acm_set_control(acm, acm->ctrlout = 0);
usb_unlink_urb(&acm->ctrlurb);
usb_unlink_urb(&acm->writeurb);
usb_unlink_urb(&acm->readurb);
return;
if (!--acm->used) {
if (acm->dev) {
acm_set_control(acm, acm->ctrlout = 0);
usb_unlink_urb(&acm->ctrlurb);
usb_unlink_urb(&acm->writeurb);
usb_unlink_urb(&acm->readurb);
} else {
tty_unregister_devfs(&acm_tty_driver, acm->minor);
acm_table[acm->minor] = NULL;
kfree(acm);
}
}
tty_unregister_devfs(&acm_tty_driver, acm->minor);
acm_table[acm->minor] = NULL;
kfree(acm);
MOD_DEC_USE_COUNT;
}
static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
......
......@@ -56,7 +56,7 @@ struct evdev_list {
struct evdev_list *next;
};
static struct evdev *evdev_table[BITS_PER_LONG] = { NULL, /* ... */ };
static struct evdev *evdev_table[EVDEV_MINORS] = { NULL, /* ... */ };
static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
{
......@@ -119,9 +119,12 @@ static int evdev_open(struct inode * inode, struct file * file)
if (i > EVDEV_MINORS || !evdev_table[i])
return -ENODEV;
if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
return -ENOMEM;
MOD_INC_USE_COUNT;
if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL))) {
MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(list, 0, sizeof(struct evdev_list));
list->evdev = evdev_table[i];
......@@ -132,7 +135,6 @@ static int evdev_open(struct inode * inode, struct file * file)
list->evdev->used++;
MOD_INC_USE_COUNT;
return 0;
}
......
......@@ -1288,7 +1288,7 @@ static void hid_init_input(struct hid_device *hid)
hid_configure_usage(hid, report->field[i], report->field[i]->usage + j);
if (k == HID_INPUT_REPORT) {
usb_set_idle(hid->dev, hid->ifnum, report->id, 0);
usb_set_idle(hid->dev, hid->ifnum, 0, report->id);
hid_read_report(hid, report);
}
}
......
......@@ -78,7 +78,7 @@ struct joydev_list {
struct joydev_list *next;
};
static struct joydev *joydev_table[BITS_PER_LONG];
static struct joydev *joydev_table[JOYDEV_MINORS];
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_SUPPORTED_DEVICE("input/js");
......@@ -186,8 +186,12 @@ static int joydev_open(struct inode *inode, struct file *file)
if (i > JOYDEV_MINORS || !joydev_table[i])
return -ENODEV;
if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL)))
MOD_INC_USE_COUNT;
if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL))) {
MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(list, 0, sizeof(struct joydev_list));
list->joydev = joydev_table[i];
......@@ -198,7 +202,6 @@ static int joydev_open(struct inode *inode, struct file *file)
list->joydev->used++;
MOD_INC_USE_COUNT;
return 0;
}
......
......@@ -31,6 +31,10 @@
* The driver supports only one camera.
*
* version 0.7.1
* MOD_INC and MOD_DEC are changed in usb_probe to prevent load/unload
* problems when compiled as Module.
* (04/04/2000)
*
* The mdc800 driver gets assigned the USB Minor 32-47. The Registration
* was updated to use these values.
* (26/03/2000)
......@@ -77,12 +81,12 @@
#define MDC800_PRODUCT_ID 0xa800
/* Timeouts (msec) */
#define TO_READ_FROM_IRQ 4000
#define TO_READ_FROM_IRQ 4000
#define TO_GET_READY 2000
#define TO_DOWNLOAD_GET_READY 1500
#define TO_DOWNLOAD_GET_BUSY 1500
#define TO_WRITE_GET_READY 3000
#define TO_DEFAULT_COMMAND 5000
#define TO_DOWNLOAD_GET_READY 1500
#define TO_DOWNLOAD_GET_BUSY 1500
#define TO_WRITE_GET_READY 3000
#define TO_DEFAULT_COMMAND 5000
/* Minor Number of the device (create with mknod /dev/mustek c 180 32) */
#define MDC800_DEVICE_MINOR_BASE 32
......@@ -517,11 +521,20 @@ static int mdc800_getAnswerSize (char command)
static int mdc800_device_open (struct inode* inode, struct file *file)
{
int retval=0;
MOD_INC_USE_COUNT;
if (mdc800->state == NOT_CONNECTED)
{
MOD_DEC_USE_COUNT;
return -EBUSY;
}
if (mdc800->open)
{
MOD_DEC_USE_COUNT;
return -EBUSY;
}
mdc800->rw_lock=0;
mdc800->in_count=0;
......@@ -538,10 +551,10 @@ static int mdc800_device_open (struct inode* inode, struct file *file)
if (usb_submit_urb (mdc800->irq_urb))
{
err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, mdc800->irq_urb->status);
MOD_DEC_USE_COUNT;
return -EIO;
}
MOD_INC_USE_COUNT;
mdc800->open=1;
dbg ("Mustek MDC800 device opened.");
......
......@@ -70,7 +70,7 @@ struct mousedev_list {
static unsigned char mousedev_genius_seq[] = { 0xe8, 3, 0xe6, 0xe6, 0xe6 };
static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
static struct mousedev *mousedev_table[BITS_PER_LONG];
static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
{
......@@ -177,9 +177,12 @@ static int mousedev_open(struct inode * inode, struct file * file)
if (i > MOUSEDEV_MINORS || !mousedev_table[i])
return -ENODEV;
if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL)))
return -ENOMEM;
MOD_INC_USE_COUNT;
if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL))) {
MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(list, 0, sizeof(struct mousedev_list));
list->mousedev = mousedev_table[i];
......@@ -189,7 +192,6 @@ static int mousedev_open(struct inode * inode, struct file * file)
file->private_data = list;
MOD_INC_USE_COUNT;
return 0;
}
......@@ -360,19 +362,15 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev
printk(KERN_ERR "mousedev: no more free mousedev devices\n");
return -1;
}
#else
if (!mousedev_table[minor]) {
#endif
if (!(mousedev = kmalloc(sizeof(struct mousedev), GFP_KERNEL)))
return -1;
memset(mousedev, 0, sizeof(struct mousedev));
init_waitqueue_head(&mousedev->wait);
mousedev->devfs = input_register_minor("mouse%d", minor, MOUSEDEV_MINOR_BASE);
if (!(mousedev = kmalloc(sizeof(struct mousedev), GFP_KERNEL)))
return -1;
memset(mousedev, 0, sizeof(struct mousedev));
init_waitqueue_head(&mousedev->wait);
#ifdef CONFIG_INPUT_MOUSEDEV_MIX
} else mousedev = mousedev_table[minor];
mousedev->devfs = input_register_minor("mouse%d", minor, MOUSEDEV_MINOR_BASE);
#else
mousedev = mousedev_table[0];
#endif
if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) {
......@@ -419,11 +417,24 @@ static struct input_handler mousedev_handler = {
static int __init mousedev_init(void)
{
input_register_handler(&mousedev_handler);
#ifdef CONFIG_INPUT_MOUSEDEV_MIX
if (!(mousedev_table[0] = kmalloc(sizeof(struct mousedev), GFP_KERNEL)))
return -1;
memset(mousedev_table[0], 0, sizeof(struct mousedev));
init_waitqueue_head(&mousedev_table[0]->wait);
mousedev_table[0]->devfs = input_register_minor("mouse%d", 0, MOUSEDEV_MINOR_BASE);
mousedev_table[0]->used = 1;
#endif
return 0;
}
static void __exit mousedev_exit(void)
{
#ifdef CONFIG_INPUT_MOUSEDEV_MIX
input_unregister_minor(mousedev_table[0]->devfs);
kfree(mousedev_table[0]);
#endif
input_unregister_handler(&mousedev_handler);
}
......
This diff is collapsed.
......@@ -16,11 +16,11 @@
#include <linux/usb.h>
static const char *version = __FILE__ ": v0.3.7 2000/03/23 Written by Petko Manolov (petkan@spct.net)\n";
static const char *version = __FILE__ ": v0.3.8 2000/04/04 Written by Petko Manolov (petkan@spct.net)\n";
#define PEGASUS_MTU 1500
#define PEGASUS_MAX_MTU 1536
#define PEGASUS_MAX_MTU 1536
#define SROM_WRITE 0x01
#define SROM_READ 0x02
#define PEGASUS_TX_TIMEOUT (HZ*5)
......@@ -55,14 +55,16 @@ MODULE_PARM(loopback, "i");
static struct usb_eth_dev usb_dev_id[] = {
{"Billionton USB-100", 0x08dd, 0x0986, NULL},
{"Corega FEter USB-TX", 0x7aa, 0x0004, NULL},
{"MELCO LUA-TX", 0x0411, 0x0001, NULL},
{ "D-Link DSB-650TX", 0x2001, 0x4002, NULL },
{ "D-Link DSB-650TX(PNA)", 0x2001, 0x4003, NULL },
{ "Linksys USB100TX", 0x066b, 0x2203, NULL },
{ "SMC 202 USB Ethernet", 0x0707, 0x0200, NULL },
{ "ADMtek AN986 \"Pegasus\" USB Ethernet (eval board)", 0x07a6, 0x0986, NULL },
{ "Accton USB 10/100 Ethernet Adapter", 0x083a, 0x1046, NULL },
{ NULL, 0, 0, NULL }
{"MELCO/BUFFALO LUA-TX", 0x0411, 0x0001, NULL},
{"D-Link DSB-650TX", 0x2001, 0x4001, NULL},
{"D-Link DSB-650TX", 0x2001, 0x4002, NULL},
{"D-Link DSB-650TX(PNA)", 0x2001, 0x4003, NULL},
{"Linksys USB100TX", 0x066b, 0x2203, NULL},
{"Linksys USB100TX", 0x066b, 0x2204, NULL},
{"SMC 202 USB Ethernet", 0x0707, 0x0200, NULL},
{"ADMtek AN986 \"Pegasus\" USB Ethernet (eval board)", 0x07a6, 0x0986, NULL},
{"Accton USB 10/100 Ethernet Adapter", 0x083a, 0x1046, NULL},
{NULL, 0, 0, NULL}
};
......@@ -387,7 +389,7 @@ static void pegasus_set_rx_mode(struct net_device *net)
(net->flags & IFF_ALLMULTI)) {
pegasus_set_register(pegasus->usb, 0, 0xfa);
pegasus_set_register(pegasus->usb, 2, 0);
info("%s: set allmulti", net->name);
info("%s set allmulti", net->name);
} else {
info("%s: set Rx mode", net->name);
}
......
......@@ -160,10 +160,13 @@ static int usblp_open(struct inode *inode, struct file *file)
if (usblp->used)
return -EBUSY;
if ((retval = usblp_check_status(usblp)))
MOD_INC_USE_COUNT;
if ((retval = usblp_check_status(usblp))) {
MOD_DEC_USE_COUNT;
return retval;
}
MOD_INC_USE_COUNT;
usblp->used = 1;
file->private_data = usblp;
......@@ -179,17 +182,18 @@ static int usblp_release(struct inode *inode, struct file *file)
{
struct usblp *usblp = file->private_data;
MOD_DEC_USE_COUNT;
usblp->used = 0;
if (usblp->dev) {
usb_unlink_urb(&usblp->readurb);
usb_unlink_urb(&usblp->writeurb);
MOD_DEC_USE_COUNT;
return 0;
}
usblp_table[usblp->minor] = NULL;
kfree(usblp);
MOD_DEC_USE_COUNT;
return 0;
}
......
......@@ -3,6 +3,7 @@
*
* (C) Copyright (C) 1999, 2000
* Greg Kroah-Hartman (greg@kroah.com)
* Bill Ryder (bryder@sgi.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
......@@ -11,6 +12,10 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
* (04/04/2000) Bill Ryder
* Fixed bugs in TCGET/TCSET ioctls (by removing them - they are
* handled elsewhere in the serial driver chain).
*
* (03/30/2000) Bill Ryder
* Implemented lots of ioctls
* Fixed a race condition in write
......@@ -284,7 +289,7 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
unsigned char *first_byte = port->write_urb->transfer_buffer;
/* Was seeing a race here, got a read callback, then write callback before
hitting interuuptible_sleep_on - so wrapping in add_wait_queue stuff */
hitting interuptible_sleep_on - so wrapping in add_wait_queue stuff */
add_wait_queue(&serial->write_wait, &wait);
set_current_state (TASK_INTERRUPTIBLE);
......@@ -418,7 +423,8 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb)
if (urb->status) {
err("nonzero read bulk status received: %d", urb->status);
/* This will happen at close every time so it is a dbg not an err */
dbg("nonzero read bulk status received: %d", urb->status);
return;
}
......@@ -585,59 +591,9 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *
return;
} /* ftdi_sio_set_termios */
/*
* set_termios - Taken from tty_ioctl.c with some mods
*
* Used to correctly handle various options (ie TERMIOS_FLUSH etc)
*
*/
/*
* Internal flag options for termios setting behavior
*/
#define TERMIOS_FLUSH 1
#define TERMIOS_WAIT 2
#define TERMIOS_TERMIO 4
/*
* set_termios - assumes old_termios is in kernel space not user space
* sets current to port->tty->termios, might check diffs against old_termios one day
*/
static int set_termios(struct usb_serial_port *port, struct termios *old_termios, int opt)
{ /* set_termios */
struct tty_struct *tty = port->tty;
int retval;
#ifdef NOT_IMPLEMENTED_YET
retval = tty_check_change(tty);
if (retval)
return retval;
#endif
if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);
if (opt & TERMIOS_WAIT) {
tty_wait_until_sent(tty, 0);
if (signal_pending(current))
return -EINTR;
}
/* remember port->tty->termios has the new settings */
ftdi_sio_set_termios(port, old_termios);
return 0;
} /* set_termios */
static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
{
struct usb_serial *serial = port->serial;
struct tty_struct *tty = port->tty;
struct termios old_termios;
__u16 urb_value=0; /* Will hold the new flags */
char buf[1];
int ret, mask;
......@@ -746,50 +702,20 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns
}
break;
/* Code for the following is based on code from tty_ioctl.c */
case TCGETS:
if (kernel_termios_to_user_termios((struct termios *)arg, tty->termios)) {
return -EFAULT;
} else {
return 0;
}
case TCSETSF:
memcpy(&old_termios, tty->termios, sizeof (struct termios));
if ((ret = user_termios_to_kernel_termios(tty->termios,
(struct termios *)arg)))
return -EFAULT;
return set_termios(port, &old_termios, TERMIOS_FLUSH);
case TCSETSW:
memcpy(&old_termios, tty->termios, sizeof (struct termios));
if ((ret = user_termios_to_kernel_termios(tty->termios,
(struct termios *)arg)))
return -EFAULT;
return set_termios(port, &old_termios, TERMIOS_WAIT);
case TCSETS:
memcpy(&old_termios, tty->termios, sizeof (struct termios));
if ((ret = user_termios_to_kernel_termios(tty->termios,
(struct termios *)arg)))
return -EFAULT;
return set_termios(port, &old_termios, 0);
#ifdef NOT_COMPLETED_YET_NEED_TO_CONVERT_TERMIO_TO_TERMIOS
/* the 'A' flavours work on termio not termios */
case TCGETA:
if (kernel_termios_to_user_termio((struct termios *)arg, tty->termios)) {
return -EFAULT;
} else {
return 0;
}
break;
case TCSETAF:
return set_termios(port, arg, TERMIOS_FLUSH | TERMIOS_TERMIO);
case TCSETAW:
return set_termios(port, arg, TERMIOS_WAIT | TERMIOS_TERMIO);
case TCSETA:
return set_termios(port, arg, TERMIOS_TERMIO);
#endif
/*
* I had originally implemented TCSET{A,S}{,F,W} and
* TCGET{A,S} here separately, however when testing I
* found that the higher layers actually do the termios
* conversions themselves and pass the call onto
* ftdi_sio_set_termios.
*
*/
default:
err("ftdi_sio ioctl arg not supported - it was 0x%04x",cmd);
/* This is not an error - turns out the higher layers will do
* some ioctls itself (see comment above)
*/
dbg("ftdi_sio ioctl arg not supported - it was 0x%04x",cmd);
return(-ENOIOCTLCMD);
break;
}
......
......@@ -34,7 +34,7 @@
struct usb_serial_port {
int magic;
struct usb_serial *serial; /* pointer back to the owner of this port */
struct tty_struct * tty; /* the coresponding tty for this device */
struct tty_struct * tty; /* the coresponding tty for this port */
unsigned char minor;
unsigned char number;
char active; /* someone has this device open */
......@@ -56,8 +56,9 @@ struct usb_serial_port {
struct usb_serial {
int magic;
struct usb_device * dev;
struct usb_serial_device_type * type;
unsigned char minor;
struct usb_serial_device_type * type; /* the type of usb serial device this is */
struct tty_driver * tty_driver; /* the tty_driver for this device */
unsigned char minor; /* the starting minor number for this device */
unsigned char num_ports; /* the number of ports this device has */
char num_interrupt_in; /* number of interrupt in endpoints we have */
char num_bulk_in; /* number of bulk in endpoints we have */
......
......@@ -14,6 +14,11 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
* (04/03/2000) gkh
* Changed the probe process to remove the module unload races.
* Changed where the tty layer gets initialized to have devfs work nicer.
* Added initial devfs support.
*
* (03/26/2000) gkh
* Split driver up into device specific pieces.
*
......@@ -269,6 +274,10 @@ static struct usb_serial_device_type *usb_serial_devices[] = {
};
/* variables needed for the tty_driver structure */
static char *driver_name = "usb";
static char *tty_driver_name = "usb/tty/%d";
/* local function prototypes */
static int serial_open (struct tty_struct *tty, struct file * filp);
......@@ -924,6 +933,48 @@ static void generic_write_bulk_callback (struct urb *urb)
}
static struct tty_driver * usb_serial_tty_driver_init (struct usb_serial *serial)
{
struct tty_driver *serial_tty_driver;
if (!(serial_tty_driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL))) {
err("Out of memory");
return NULL;
}
memset (serial_tty_driver, 0x00, sizeof(struct tty_driver));
/* initialize the entries that we don't want to be NULL */
serial_tty_driver->magic = TTY_DRIVER_MAGIC;
serial_tty_driver->driver_name = driver_name;
serial_tty_driver->name = tty_driver_name;
serial_tty_driver->major = SERIAL_TTY_MAJOR;
serial_tty_driver->minor_start = serial->minor;
serial_tty_driver->num = serial->num_ports;
serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
serial_tty_driver->flags = TTY_DRIVER_REAL_RAW;
serial_tty_driver->refcount = &serial_refcount;
serial_tty_driver->table = serial_tty;
serial_tty_driver->termios = serial_termios;
serial_tty_driver->termios_locked = serial_termios_locked;
serial_tty_driver->open = serial_open;
serial_tty_driver->close = serial_close;
serial_tty_driver->write = serial_write;
serial_tty_driver->write_room = serial_write_room;
serial_tty_driver->ioctl = serial_ioctl;
serial_tty_driver->set_termios = serial_set_termios;
serial_tty_driver->throttle = serial_throttle;
serial_tty_driver->unthrottle = serial_unthrottle;
serial_tty_driver->break_ctl = serial_break;
serial_tty_driver->chars_in_buffer = serial_chars_in_buffer;
serial_tty_driver->init_termios = tty_std_termios;
serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
return serial_tty_driver;
}
static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
{
struct usb_serial *serial = NULL;
......@@ -1000,6 +1051,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
(bulk_in_pipe & type->needs_bulk_in) &&
(bulk_out_pipe & type->needs_bulk_out)) {
/* found all that we need */
MOD_INC_USE_COUNT;
info("%s converter detected", type->name);
#ifdef CONFIG_USB_SERIAL_GENERIC
......@@ -1012,6 +1064,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
serial = get_free_serial (num_ports, &minor);
if (serial == NULL) {
err("No more free serial devices");
MOD_DEC_USE_COUNT;
return NULL;
}
......@@ -1023,6 +1076,18 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
serial->num_bulk_out = num_bulk_out;
serial->num_interrupt_in = num_interrupt_in;
/* initialize a tty_driver for this device */
serial->tty_driver = usb_serial_tty_driver_init (serial);
if (serial->tty_driver == NULL) {
err("Can't create a tty_serial_driver");
goto probe_error;
}
if (tty_register_driver (serial->tty_driver)) {
err("failed to register tty driver");
goto probe_error;
}
/* collect interrupt_in endpoints now, because
the keyspan_pda startup function needs
to know about them */
......@@ -1040,8 +1105,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
/* if this device type has a startup function, call it */
if (type->startup) {
if (type->startup (serial)) {
return_serial (serial);
return NULL;
goto probe_error;
}
}
......@@ -1114,8 +1178,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
info("%s converter now attached to ttyUSB%d", type->name, serial->minor + i);
}
MOD_INC_USE_COUNT;
return serial;
} else {
info("descriptors matched, but endpoints did not");
......@@ -1153,8 +1215,16 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
/* return the minor range that this device had */
return_serial (serial);
/* if this device has a tty_driver, then unregister it and free it */
if (serial->tty_driver) {
tty_unregister_driver (serial->tty_driver);
kfree (serial->tty_driver);
serial->tty_driver = NULL;
}
/* free up any memory that we allocated */
kfree (serial);
MOD_DEC_USE_COUNT;
}
return NULL;
}
......@@ -1205,6 +1275,12 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
/* return the minor range that this device had */
return_serial (serial);
/* if this device has a tty_driver, then unregister it and free it */
if (serial->tty_driver) {
tty_unregister_driver (serial->tty_driver);
kfree (serial->tty_driver);
serial->tty_driver = NULL;
}
/* free up any memory that we allocated */
kfree (serial);
......@@ -1216,46 +1292,6 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
}
static struct tty_driver serial_tty_driver = {
magic: TTY_DRIVER_MAGIC,
driver_name: "usb",
name: "ttyUSB%d",
major: SERIAL_TTY_MAJOR,
minor_start: 0,
num: SERIAL_TTY_MINORS,
type: TTY_DRIVER_TYPE_SERIAL,
subtype: SERIAL_TYPE_NORMAL,
flags: TTY_DRIVER_REAL_RAW,
refcount: &serial_refcount,
table: serial_tty,
proc_entry: NULL,
other: NULL,
termios: serial_termios,
termios_locked: serial_termios_locked,
open: serial_open,
close: serial_close,
write: serial_write,
put_char: NULL,
flush_chars: NULL,
write_room: serial_write_room,
ioctl: serial_ioctl,
set_termios: serial_set_termios,
set_ldisc: NULL,
throttle: serial_throttle,
unthrottle: serial_unthrottle,
stop: NULL,
start: NULL,
hangup: NULL,
break_ctl: serial_break,
wait_until_sent: NULL,
send_xchar: NULL,
read_proc: NULL,
chars_in_buffer: serial_chars_in_buffer,
flush_buffer: NULL
};
int usb_serial_init(void)
{
int i;
......@@ -1265,17 +1301,8 @@ int usb_serial_init(void)
serial_table[i] = NULL;
}
/* register the tty driver */
serial_tty_driver.init_termios = tty_std_termios;
serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
if (tty_register_driver (&serial_tty_driver)) {
err("failed to register tty driver");
return -EPERM;
}
/* register the USB driver */
if (usb_register(&usb_serial_driver) < 0) {
tty_unregister_driver(&serial_tty_driver);
return -1;
}
......@@ -1286,7 +1313,6 @@ int usb_serial_init(void)
void usb_serial_exit(void)
{
tty_unregister_driver(&serial_tty_driver);
usb_deregister(&usb_serial_driver);
}
......
......@@ -448,7 +448,7 @@ static void uhci_inc_fsbr(struct uhci *uhci, struct urb *urb)
if (!urbp->fsbr) {
urbp->fsbr = 1;
if (!uhci->fsbr++)
uhci->skel_term_td.link = virt_to_bus(&uhci->skel_hs_control_qh) | UHCI_PTR_QH;
uhci->skel_term_qh.link = virt_to_bus(&uhci->skel_hs_control_qh) | UHCI_PTR_QH;
}
spin_unlock_irqrestore(&uhci->framelist_lock, flags);
......@@ -467,7 +467,7 @@ static void uhci_dec_fsbr(struct uhci *uhci, struct urb *urb)
if (urbp->fsbr) {
urbp->fsbr = 0;
if (!--uhci->fsbr)
uhci->skel_term_td.link = UHCI_PTR_TERM;
uhci->skel_term_qh.link = UHCI_PTR_TERM;
}
spin_unlock_irqrestore(&uhci->framelist_lock, flags);
......@@ -712,6 +712,10 @@ static int usb_control_retrigger_status(urb_t *urb)
urbp->short_control_packet = 1;
/* Create a new QH to avoid pointer overwriting problems */
uhci_remove_qh(uhci, urbp->qh);
urbp->qh = uhci_alloc_qh(urb->dev);
/* Delete all of the TD's except for the status TD at the end */
td = urbp->list.begin;
while (td && td->list.next) {
......@@ -726,10 +730,6 @@ static int usb_control_retrigger_status(urb_t *urb)
td = nexttd;
}
/* Create a new QH to avoid pointer overwriting problems */
uhci_remove_qh(uhci, urbp->qh);
urbp->qh = uhci_alloc_qh(urb->dev);
if (!urbp->qh)
return -ENOMEM;
......@@ -1403,7 +1403,7 @@ static int rh_init_int_timer(urb_t *urb);
static void rh_int_timer_do(unsigned long ptr)
{
urb_t *urb = (urb_t *)ptr, *u;
struct urb *urb = (struct urb *)ptr;
struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
struct list_head *tmp, *head = &uhci->urb_list;
struct urb_priv *urbp;
......@@ -1422,15 +1422,22 @@ static void rh_int_timer_do(unsigned long ptr)
nested_lock(&uhci->urblist_lock, flags);
tmp = head->next;
while (tmp != head) {
u = list_entry(tmp, urb_t, urb_list);
struct urb *u = list_entry(tmp, urb_t, urb_list);
tmp = tmp->next;
urbp = (struct urb_priv *)u->hcpriv;
if (urbp) {
if (urbp->fsbr && time_after(jiffies, urbp->inserttime + IDLE_TIMEOUT))
/* Check if the FSBR timed out */
if (urbp->fsbr && time_after(urbp->inserttime + IDLE_TIMEOUT, jiffies))
uhci_dec_fsbr(uhci, u);
}
tmp = tmp->next;
/* Check if the URB timed out */
if (u->timeout && time_after(u->timeout, jiffies)) {
u->transfer_flags |= USB_ASYNC_UNLINK;
uhci_unlink_urb(u);
}
}
}
nested_unlock(&uhci->urblist_lock, flags);
......
This diff is collapsed.
This diff is collapsed.
......@@ -129,8 +129,8 @@ static inline void make_guid( __u32 *pg, __u16 vendor, __u16 product, char *seri
}
/* Flag definitions */
#define US_FL_IP_STATUS 0x00000001 /* status uses interrupt */
#define US_FL_FIXED_COMMAND 0x00000002 /* expand commands to fixed size */
#define US_FL_IP_STATUS 0x00000001 /* status uses interrupt */
#define US_FL_FIXED_COMMAND 0x00000002 /* expand commands to fixed size */
#define US_FL_MODE_XLATE 0x00000004 /* translate _6 to _10 comands for
Win/MacOS compatibility */
Win/MacOS compatibility */
#define US_FL_CBI_AS_CB 0x00000008 /* treat a CBI dev as a CB dev */
......@@ -12,7 +12,7 @@
* (C) Copyright 1999 Johannes Erdfelt
* (C) Copyright 1999 Randy Dunlap
*
* $Id: usb-uhci.c,v 1.222 2000/03/13 21:18:02 fliegl Exp $
* $Id: usb-uhci.c,v 1.228 2000/04/02 19:55:51 acher Exp $
*/
#include <linux/config.h>
......@@ -50,6 +50,8 @@
/* This enables an extra UHCI slab for memory debugging */
#define DEBUG_SLAB
#define VERSTR "$Revision: 1.228 $ time " __TIME__ " " __DATE__
#include <linux/usb.h>
#include "usb-uhci.h"
#include "usb-uhci-debug.h"
......@@ -116,6 +118,26 @@ void clean_descs(uhci_t *s, int force)
}
}
/*-------------------------------------------------------------------*/
_static void uhci_switch_timer_int(uhci_t *s)
{
if (!list_empty(&s->urb_unlinked)) {
s->td1ms->hw.td.status |= TD_CTRL_IOC;
}
else {
s->td1ms->hw.td.status &= ~TD_CTRL_IOC;
}
if (s->timeout_urbs) {
s->td32ms->hw.td.status |= TD_CTRL_IOC;
}
else {
s->td32ms->hw.td.status &= ~TD_CTRL_IOC;
}
wmb();
}
/*-------------------------------------------------------------------*/
#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
_static void enable_desc_loop(uhci_t *s, urb_t *urb)
{
......@@ -162,6 +184,9 @@ _static void queue_urb_unlocked (uhci_t *s, urb_t *urb)
#endif
((urb_priv_t*)urb->hcpriv)->started=jiffies;
list_add (p, &s->urb_list);
if (urb->timeout)
s->timeout_urbs++;
uhci_switch_timer_int(s);
}
/*-------------------------------------------------------------------*/
_static void queue_urb (uhci_t *s, urb_t *urb)
......@@ -185,6 +210,9 @@ _static void dequeue_urb (uhci_t *s, urb_t *urb)
#endif
list_del (&urb->urb_list);
if (urb->timeout && s->timeout_urbs)
s->timeout_urbs--;
}
/*-------------------------------------------------------------------*/
_static int alloc_td (uhci_desc_t ** new, int flags)
......@@ -439,6 +467,13 @@ _static void cleanup_skel (uhci_t *s)
clean_descs(s,1);
if (s->td32ms) {
unlink_td(s,s->td32ms,1);
delete_desc(s->td32ms);
}
for (n = 0; n < 8; n++) {
td = s->int_chain[n];
clean_td_chain (td);
......@@ -531,8 +566,9 @@ _static int init_skel (uhci_t *s)
if (ret)
goto init_skel_cleanup;
fill_td (td, TD_CTRL_IOC, 0, 0); // generate 1ms interrupt
fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on demand)
insert_td (s, qh, td, 0);
s->td1ms=td;
dbg("allocating qh: bulk_chain");
ret = alloc_qh (&qh);
......@@ -597,6 +633,16 @@ _static int init_skel (uhci_t *s)
((uhci_desc_t*) s->iso_td[n])->hw.td.link = virt_to_bus (s->int_chain[o]);
}
ret = alloc_td (&td, 0);
if (ret)
goto init_skel_cleanup;
fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 32ms interrupt
s->td32ms=td;
insert_td_horizontal (s, s->int_chain[5], td);
mb();
//uhci_show_queue(s->control_chain);
dbg("init_skel exit");
......@@ -995,6 +1041,7 @@ _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb)
if (urb->status == -EINPROGRESS) {
// URB probably still in work
dequeue_urb (s, urb);
uhci_switch_timer_int(s);
s->unlink_urb_done=1;
spin_unlock_irqrestore (&s->urb_list_lock, flags);
......@@ -1125,9 +1172,11 @@ _static int uhci_unlink_urb_async (uhci_t *s,urb_t *urb)
if (urb->status == -EINPROGRESS) {
((urb_priv_t*)urb->hcpriv)->started = ~0;
dequeue_urb (s, urb);
list_add_tail (&urb->urb_list, &s->urb_unlinked); // store urb
uhci_switch_timer_int(s);
s->unlink_urb_done = 1;
urb->status = -ECONNABORTED; // mark urb as "waiting to be killed"
......@@ -1495,7 +1544,7 @@ _static int uhci_submit_urb (urb_t *urb)
(!(urb->transfer_flags & USB_QUEUE_BULK) || !(bulk_urb->transfer_flags & USB_QUEUE_BULK)))) {
spin_unlock_irqrestore (&s->urb_list_lock, flags);
usb_dec_dev_use (urb->dev);
err("ENXIO1 %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,bulk_urb);
err("ENXIO %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,bulk_urb);
return -ENXIO; // urb already queued
}
}
......@@ -1599,6 +1648,7 @@ _static void uhci_check_timeouts(uhci_t *s)
#endif
}
s->timeout_check=jiffies;
}
/*-------------------------------------------------------------------
......@@ -1922,7 +1972,7 @@ _static int rh_submit_urb (urb_t *urb)
OK (len);
case (0x03): /* string descriptors */
len = usb_root_hub_string (wValue & 0xff,
uhci->io_addr, "UHCI",
uhci->io_addr, "UHCI",
data, wLength);
if (len > 0) {
OK (min (leni, len));
......@@ -2481,15 +2531,15 @@ _static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs)
goto restart;
}
}
if ((s->frame_counter & 63) == 0)
if ((jiffies - s->timeout_check) > (HZ/30))
uhci_check_timeouts(s);
clean_descs(s,0);
uhci_cleanup_unlink(s, 0);
uhci_switch_timer_int(s);
spin_unlock (&s->urb_list_lock);
s->frame_counter++;
outw (status, io_addr + USBSTS);
//dbg("uhci_interrupt: done");
......@@ -2630,12 +2680,14 @@ _static int __init alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_add
spin_lock_init (&s->qh_lock);
spin_lock_init (&s->td_lock);
atomic_set(&s->avoid_bulk, 0);
s->timeout_urbs = 0;
s->irq = -1;
s->io_addr = io_addr;
s->io_size = io_size;
s->next = devs; //chain new uhci device into global list
s->frame_counter = 0;
s->timeout_check = 0;
s->uhci_pci=dev;
bus = usb_alloc_bus (&uhci_device_operations);
if (!bus) {
kfree (s);
......@@ -2739,6 +2791,7 @@ _static int __init start_uhci (struct pci_dev *dev)
info("Intel USB controller: setting latency timer to %d", UHCI_LATENCY_TIMER);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, UHCI_LATENCY_TIMER);
}
return alloc_uhci(dev, dev->irq, io_addr, io_size);
}
return -1;
......
......@@ -2,10 +2,9 @@
#define __LINUX_UHCI_H
/*
$Id: usb-uhci.h,v 1.50 2000/03/13 21:18:04 fliegl Exp $
$Id: usb-uhci.h,v 1.54 2000/04/02 19:55:53 acher Exp $
*/
#define MODNAME "usb-uhci"
#define VERSTR "$Revision: 1.50 $ time " __TIME__ " " __DATE__
#define UHCI_LATENCY_TIMER 0
static __inline__ void uhci_wait_ms(unsigned int ms)
......@@ -202,6 +201,8 @@ typedef struct uhci {
uhci_desc_t *control_chain;
uhci_desc_t *bulk_chain;
uhci_desc_t *chain_end;
uhci_desc_t *td1ms;
uhci_desc_t *td32ms;
struct list_head free_desc;
spinlock_t qh_lock;
spinlock_t td_lock;
......@@ -209,7 +210,9 @@ typedef struct uhci {
int loop_usage; // URBs using bandwidth reclamation
struct list_head urb_unlinked; // list of all unlinked urbs
int frame_counter;
long timeout_check;
int timeout_urbs;
struct pci_dev *uhci_pci;
} uhci_t, *puhci_t;
......
......@@ -71,7 +71,7 @@ if [ "$CONFIG_NET" = "y" ]; then
dep_tristate 'Coda file system support (advanced network fs)' CONFIG_CODA_FS $CONFIG_INET
dep_tristate 'NFS file system support' CONFIG_NFS_FS $CONFIG_INET
dep_bool ' Provide NFSv3 client support (EXPERIMENTAL)' CONFIG_NFS_V3 $CONFIG_NFS_FS
dep_mbool ' Provide NFSv3 client support (EXPERIMENTAL)' CONFIG_NFS_V3 $CONFIG_NFS_FS
dep_bool ' Root file system on NFS' CONFIG_ROOT_NFS $CONFIG_NFS_FS $CONFIG_IP_PNP
dep_tristate 'NFS server support' CONFIG_NFSD $CONFIG_INET
......@@ -89,7 +89,7 @@ if [ "$CONFIG_NET" = "y" ]; then
define_tristate CONFIG_LOCKD n
fi
fi
if [ "$CONFIG_NFSD_V3" = "y" ]; then
if [ "$CONFIG_NFSD_V3" = "y" -o "$CONFIG_NFS_V3" = "y" ]; then
define_bool CONFIG_LOCKD_V4 y
fi
......
......@@ -18,10 +18,10 @@ static int autofs_readlink(struct dentry *dentry, char *buffer, int buflen)
return vfs_readlink(dentry, buffer, buflen, s);
}
static struct dentry *autofs_follow_link(struct dentry *dentry, struct dentry *base, struct vfsmount **mnt, unsigned flags)
static int autofs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data;
return vfs_follow_link(dentry, base, mnt, flags, s);
return vfs_follow_link(nd, s);
}
struct inode_operations autofs_symlink_inode_operations = {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -2,7 +2,7 @@ struct proc_inode_info {
struct task_struct *task;
int type;
union {
struct dentry *(*proc_get_link)(struct inode *, struct vfsmount **);
int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **);
int (*proc_read)(struct task_struct *task, char *page);
} op;
struct file *file;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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