📄 usbserial.c
字号:
/*
* USB Serial Converter driver
*
* Copyright (C) 1999, 2000 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (c) 2000 Peter Berger (pberger@brimson.com)
* Copyright (c) 2000 Al Borchers (borchers@steinerpoint.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 driver was originally based on the ACM driver by Armin Fuerst (which was
* based on a driver by Brad Keryan)
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
* 2001_02_05 gkh
* Fixed buffer overflows bug with the generic serial driver. Thanks to
* Todd Squires <squirest@ct0.com> for fixing this.
*
* (01/10/2001) gkh
* Fixed bug where the generic serial adaptor grabbed _any_ device that was
* offered to it.
*
* (12/12/2000) gkh
* Removed MOD_INC and MOD_DEC from poll and disconnect functions, and
* moved them to the serial_open and serial_close functions.
* Also fixed bug with there not being a MOD_DEC for the generic driver
* (thanks to Gary Brubaker for finding this.)
*
* (11/29/2000) gkh
* Small NULL pointer initialization cleanup which saves a bit of disk image
*
* (11/01/2000) Adam J. Richter
* instead of using idVendor/idProduct pairs, usb serial drivers
* now identify their hardware interest with usb_device_id tables,
* which they usually have anyhow for use with MODULE_DEVICE_TABLE.
*
* (10/05/2000) gkh
* Fixed bug with urb->dev not being set properly, now that the usb
* core needs it.
*
* (09/11/2000) gkh
* Removed DEBUG #ifdefs with call to usb_serial_debug_data
*
* (08/28/2000) gkh
* Added port_lock to port structure.
* Added locks for SMP safeness to generic driver
* Fixed the ability to open a generic device's port more than once.
*
* (07/23/2000) gkh
* Added bulk_out_endpointAddress to port structure.
*
* (07/19/2000) gkh, pberger, and borchers
* Modifications to allow usb-serial drivers to be modules.
*
* (07/03/2000) gkh
* Added more debugging to serial_ioctl call
*
* (06/25/2000) gkh
* Changed generic_write_bulk_callback to not call wake_up_interruptible
* directly, but to have port_softint do it at a safer time.
*
* (06/23/2000) gkh
* Cleaned up debugging statements in a quest to find UHCI timeout bug.
*
* (05/22/2000) gkh
* Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be
* removed from the individual device source files.
*
* (05/03/2000) gkh
* Added the Digi Acceleport driver from Al Borchers and Peter Berger.
*
* (05/02/2000) gkh
* Changed devfs and tty register code to work properly now. This was based on
* the ACM driver changes by Vojtech Pavlik.
*
* (04/27/2000) Ryan VanderBijl
* Put calls to *_paranoia_checks into one function.
*
* (04/23/2000) gkh
* Fixed bug that Randy Dunlap found for Generic devices with no bulk out ports.
* Moved when the startup code printed out the devices that are supported.
*
* (04/19/2000) gkh
* Added driver for ZyXEL omni.net lcd plus ISDN TA
* Made startup info message specify which drivers were compiled in.
*
* (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.
*
* (03/19/2000) gkh
* Fixed oops that could happen when device was removed while a program
* was talking to the device.
* Removed the static urbs and now all urbs are created and destroyed
* dynamically.
* Reworked the internal interface. Now everything is based on the
* usb_serial_port structure instead of the larger usb_serial structure.
* This fixes the bug that a multiport device could not have more than
* one port open at one time.
*
* (03/17/2000) gkh
* Added config option for debugging messages.
* Added patch for keyspan pda from Brian Warner.
*
* (03/06/2000) gkh
* Added the keyspan pda code from Brian Warner <warner@lothar.com>
* Moved a bunch of the port specific stuff into its own structure. This
* is in anticipation of the true multiport devices (there's a bug if you
* try to access more than one port of any multiport device right now)
*
* (02/21/2000) gkh
* Made it so that any serial devices only have to specify which functions
* they want to overload from the generic function calls (great,
* inheritance in C, in a driver, just what I wanted...)
* Added support for set_termios and ioctl function calls. No drivers take
* advantage of this yet.
* Removed the #ifdef MODULE, now there is no module specific code.
* Cleaned up a few comments in usb-serial.h that were wrong (thanks again
* to Miles Lott).
* Small fix to get_free_serial.
*
* (02/14/2000) gkh
* Removed the Belkin and Peracom functionality from the driver due to
* the lack of support from the vendor, and me not wanting people to
* accidenatly buy the device, expecting it to work with Linux.
* Added read_bulk_callback and write_bulk_callback to the type structure
* for the needs of the FTDI and WhiteHEAT driver.
* Changed all reverences to FTDI to FTDI_SIO at the request of Bill
* Ryder.
* Changed the output urb size back to the max endpoint size to make
* the ftdi_sio driver have it easier, and due to the fact that it didn't
* really increase the speed any.
*
* (02/11/2000) gkh
* Added VISOR_FUNCTION_CONSOLE to the visor startup function. This was a
* patch from Miles Lott (milos@insync.net).
* Fixed bug with not restoring the minor range that a device grabs, if
* the startup function fails (thanks Miles for finding this).
*
* (02/05/2000) gkh
* Added initial framework for the Keyspan PDA serial converter so that
* Brian Warner has a place to put his code.
* Made the ezusb specific functions generic enough that different
* devices can use them (whiteheat and keyspan_pda both need them).
* Split out a whole bunch of structure and other stuff to a seperate
* usb-serial.h file.
* Made the Visor connection messages a little more understandable, now
* that Miles Lott (milos@insync.net) has gotten the Generic channel to
* work. Also made them always show up in the log file.
*
* (01/25/2000) gkh
* Added initial framework for FTDI serial converter so that Bill Ryder
* has a place to put his code.
* Added the vendor specific info from Handspring. Now we can print out
* informational debug messages as well as understand what is happening.
*
* (01/23/2000) gkh
* Fixed problem of crash when trying to open a port that didn't have a
* device assigned to it. Made the minor node finding a little smarter,
* now it looks to find a continous space for the new device.
*
* (01/21/2000) gkh
* Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net)
* Fixed get_serial_by_minor which was all messed up for multi port
* devices. Fixed multi port problem for generic devices. Now the number
* of ports is determined by the number of bulk out endpoints for the
* generic device.
*
* (01/19/2000) gkh
* Removed lots of cruft that was around from the old (pre urb) driver
* interface.
* Made the serial_table dynamic. This should save lots of memory when
* the number of minor nodes goes up to 256.
* Added initial support for devices that have more than one port.
* Added more debugging comments for the Visor, and added a needed
* set_configuration call.
*
* (01/17/2000) gkh
* Fixed the WhiteHEAT firmware (my processing tool had a bug)
* and added new debug loader firmware for it.
* Removed the put_char function as it isn't really needed.
* Added visor startup commands as found by the Win98 dump.
*
* (01/13/2000) gkh
* Fixed the vendor id for the generic driver to the one I meant it to be.
*
* (01/12/2000) gkh
* Forget the version numbering...that's pretty useless...
* Made the driver able to be compiled so that the user can select which
* converter they want to use. This allows people who only want the Visor
* support to not pay the memory size price of the WhiteHEAT.
* Fixed bug where the generic driver (idVendor=0000 and idProduct=0000)
* grabbed the root hub. Not good.
*
* version 0.4.0 (01/10/2000) gkh
* Added whiteheat.h containing the firmware for the ConnectTech WhiteHEAT
* device. Added startup function to allow firmware to be downloaded to
* a device if it needs to be.
* Added firmware download logic to the WhiteHEAT device.
* Started to add #defines to split up the different drivers for potential
* configuration option.
*
* version 0.3.1 (12/30/99) gkh
* Fixed problems with urb for bulk out.
* Added initial support for multiple sets of endpoints. This enables
* the Handspring Visor to be attached successfully. Only the first
* bulk in / bulk out endpoint pair is being used right now.
*
* version 0.3.0 (12/27/99) gkh
* Added initial support for the Handspring Visor based on a patch from
* Miles Lott (milos@sneety.insync.net)
* Cleaned up the code a bunch and converted over to using urbs only.
*
* version 0.2.3 (12/21/99) gkh
* Added initial support for the Connect Tech WhiteHEAT converter.
* Incremented the number of ports in expectation of getting the
* WhiteHEAT to work properly (4 ports per connection).
* Added notification on insertion and removal of what port the
* device is/was connected to (and what kind of device it was).
*
* version 0.2.2 (12/16/99) gkh
* Changed major number to the new allocated number. We're legal now!
*
* version 0.2.1 (12/14/99) gkh
* Fixed bug that happens when device node is opened when there isn't a
* device attached to it. Thanks to marek@webdesign.no for noticing this.
*
* version 0.2.0 (11/10/99) gkh
* Split up internals to make it easier to add different types of serial
* converters to the code.
* Added a "generic" driver that gets it's vendor and product id
* from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net)
* for the idea and sample code (from the usb scanner driver.)
* Cleared up any licensing questions by releasing it under the GNU GPL.
*
* version 0.1.2 (10/25/99) gkh
* Fixed bug in detecting device.
*
* version 0.1.1 (10/05/99) gkh
* Changed the major number to not conflict with anything else.
*
* version 0.1 (09/28/99) gkh
* Can recognize the two different devices and start up a read from
* device when asked to. Writes also work. No control signals yet, this
* all is vendor specific data (i.e. no spec), also no control for
* different baud rates or other bit settings.
* Currently we are using the same devid as the acm driver. This needs
* to change.
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/smp_lock.h>
#ifdef USB_SERIAL_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/usb.h>
/* Module information */
MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/");
MODULE_DESCRIPTION("USB Serial Driver");
#include "usb-serial.h"
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
/* need to always compile these in, as some of the other devices use these functions as their own. */
/* if a driver does not provide a function pointer, the generic function will be called. */
static int generic_open(struct usb_serial_port *port, struct file *filp);
static void generic_close(struct usb_serial_port *port, struct file *filp);
static int generic_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
static int generic_write_room(struct usb_serial_port *port);
static int generic_chars_in_buffer(struct usb_serial_port *port);
static void generic_read_bulk_callback(struct urb *urb);
static void generic_write_bulk_callback(struct urb *urb);
#ifdef CONFIG_USB_SERIAL_GENERIC
static void generic_shutdown(struct usb_serial *serial);
static __u16 vendor = 0x05f9;
static __u16 product = 0xffff;
MODULE_PARM(vendor, "i");
MODULE_PARM_DESC(vendor, "User specified USB idVendor");
MODULE_PARM(product, "i");
MODULE_PARM_DESC(product, "User specified USB idProduct");
static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
/* All of the device info needed for the Generic Serial Converter */
static struct usb_serial_device_type generic_device =
{
name:
"Generic",
id_table : generic_device_ids,
needs_interrupt_in : DONT_CARE, /* don't have to have an interrupt in endpoint */
needs_bulk_in : DONT_CARE, /* don't have to have a bulk in endpoint */
needs_bulk_out : DONT_CARE, /* don't have to have a bulk out endpoint */
num_interrupt_in : NUM_DONT_CARE,
num_bulk_in : NUM_DONT_CARE,
num_bulk_out : NUM_DONT_CARE,
num_ports : 1,
shutdown : generic_shutdown,
};
#endif
/* local function prototypes */
static int serial_open(struct tty_struct *tty, struct file *filp);
static void serial_close(struct tty_struct *tty, struct file *filp);
static int serial_write(struct tty_struct *tty, int from_user,
const unsigned char *buf, int count);
static int serial_write_room(struct tty_struct *tty);
static int serial_chars_in_buffer(struct tty_struct *tty);
static void serial_throttle(struct tty_struct *tty);
static void serial_unthrottle(struct tty_struct *tty);
static int serial_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd,
unsigned long arg);
static void serial_set_termios(struct tty_struct *tty, struct termios *old);
static void *usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id);
static void usb_serial_disconnect(struct usb_device *dev, void *ptr);
static struct usb_driver usb_serial_driver =
{
name:
"serial",
probe : usb_serial_probe,
disconnect : usb_serial_disconnect,
id_table : NULL, /* check all devices */
};
/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
the MODULE_DEVICE_TABLE declarations in each serial driver
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -