aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/ChangeLog.history730
-rw-r--r--drivers/usb/serial/Kconfig164
-rw-r--r--drivers/usb/serial/Makefile16
-rw-r--r--drivers/usb/serial/aircable.c86
-rw-r--r--drivers/usb/serial/ark3116.c228
-rw-r--r--drivers/usb/serial/belkin_sa.c190
-rw-r--r--drivers/usb/serial/bus.c71
-rw-r--r--drivers/usb/serial/ch341.c288
-rw-r--r--drivers/usb/serial/console.c56
-rw-r--r--drivers/usb/serial/cp210x.c495
-rw-r--r--drivers/usb/serial/cyberjack.c246
-rw-r--r--drivers/usb/serial/cypress_m8.c543
-rw-r--r--drivers/usb/serial/cypress_m8.h34
-rw-r--r--drivers/usb/serial/digi_acceleport.c631
-rw-r--r--drivers/usb/serial/empeg.c57
-rw-r--r--drivers/usb/serial/ezusb.c61
-rw-r--r--drivers/usb/serial/f81232.c334
-rw-r--r--drivers/usb/serial/ftdi_sio.c830
-rw-r--r--drivers/usb/serial/ftdi_sio.h4
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h294
-rw-r--r--drivers/usb/serial/funsoft.c69
-rw-r--r--drivers/usb/serial/garmin_gps.c295
-rw-r--r--drivers/usb/serial/generic.c469
-rw-r--r--drivers/usb/serial/hp4x.c86
-rw-r--r--drivers/usb/serial/io_edgeport.c954
-rw-r--r--drivers/usb/serial/io_edgeport.h2
-rw-r--r--drivers/usb/serial/io_tables.h36
-rw-r--r--drivers/usb/serial/io_ti.c982
-rw-r--r--drivers/usb/serial/io_usbvend.h2
-rw-r--r--drivers/usb/serial/ipaq.c112
-rw-r--r--drivers/usb/serial/ipw.c150
-rw-r--r--drivers/usb/serial/ir-usb.c158
-rw-r--r--drivers/usb/serial/iuu_phoenix.c351
-rw-r--r--drivers/usb/serial/keyspan.c1056
-rw-r--r--drivers/usb/serial/keyspan.h43
-rw-r--r--drivers/usb/serial/keyspan_pda.c311
-rw-r--r--drivers/usb/serial/keyspan_usa26msg.h2
-rw-r--r--drivers/usb/serial/kl5kusb105.c241
-rw-r--r--drivers/usb/serial/kobil_sct.c344
-rw-r--r--drivers/usb/serial/mct_u232.c344
-rw-r--r--drivers/usb/serial/metro-usb.c399
-rw-r--r--drivers/usb/serial/mos7720.c623
-rw-r--r--drivers/usb/serial/mos7840.c1642
-rw-r--r--drivers/usb/serial/moto_modem.c71
-rw-r--r--drivers/usb/serial/mxuport.c1393
-rw-r--r--drivers/usb/serial/navman.c67
-rw-r--r--drivers/usb/serial/omninet.c266
-rw-r--r--drivers/usb/serial/opticon.c532
-rw-r--r--drivers/usb/serial/option.c1558
-rw-r--r--drivers/usb/serial/oti6858.c366
-rw-r--r--drivers/usb/serial/pl2303.c832
-rw-r--r--drivers/usb/serial/pl2303.h11
-rw-r--r--drivers/usb/serial/qcaux.c39
-rw-r--r--drivers/usb/serial/qcserial.c380
-rw-r--r--drivers/usb/serial/quatech2.c1036
-rw-r--r--drivers/usb/serial/safe_serial.c106
-rw-r--r--drivers/usb/serial/sam-ba.c206
-rw-r--r--drivers/usb/serial/siemens_mpi.c77
-rw-r--r--drivers/usb/serial/sierra.c503
-rw-r--r--drivers/usb/serial/spcp8x5.c445
-rw-r--r--drivers/usb/serial/ssu100.c349
-rw-r--r--drivers/usb/serial/symbolserial.c204
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c691
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h7
-rw-r--r--drivers/usb/serial/usb-serial-simple.c110
-rw-r--r--drivers/usb/serial/usb-serial.c857
-rw-r--r--drivers/usb/serial/usb-wwan.h17
-rw-r--r--drivers/usb/serial/usb_debug.c44
-rw-r--r--drivers/usb/serial/usb_wwan.c583
-rw-r--r--drivers/usb/serial/visor.c194
-rw-r--r--drivers/usb/serial/visor.h2
-rw-r--r--drivers/usb/serial/vivopay-serial.c76
-rw-r--r--drivers/usb/serial/whiteheat.c906
-rw-r--r--drivers/usb/serial/wishbone-serial.c94
-rw-r--r--drivers/usb/serial/xsens_mt.c85
-rw-r--r--drivers/usb/serial/zio.c64
-rw-r--r--drivers/usb/serial/zte_ev.c317
77 files changed, 12563 insertions, 13954 deletions
diff --git a/drivers/usb/serial/ChangeLog.history b/drivers/usb/serial/ChangeLog.history
deleted file mode 100644
index f13fd488ebe..00000000000
--- a/drivers/usb/serial/ChangeLog.history
+++ /dev/null
@@ -1,730 +0,0 @@
-This is the contents of some of the drivers/usb/serial/ files that had old
-changelog comments. They were quite old, and out of date, and we don't keep
-them anymore, so I've put them here, away from the source files, in case
-people still care to see them.
-
-- Greg Kroah-Hartman <greg@kroah.com> October 20, 2005
-
------------------------------------------------------------------------
-usb-serial.h Change Log comments:
-
- (03/26/2002) gkh
- removed the port->tty check from port_paranoia_check() due to serial
- consoles not having a tty device assigned to them.
-
- (12/03/2001) gkh
- removed active from the port structure.
- added documentation to the usb_serial_device_type structure
-
- (10/10/2001) gkh
- added vendor and product to serial structure. Needed to determine device
- owner when the device is disconnected.
-
- (05/30/2001) gkh
- added sem to port structure and removed port_lock
-
- (10/05/2000) gkh
- Added interrupt_in_endpointAddress and bulk_in_endpointAddress to help
- fix bug with urb->dev not being set properly, now that the usb core
- needs it.
-
- (09/11/2000) gkh
- Added usb_serial_debug_data function to help get rid of #DEBUG in the
- drivers.
-
- (08/28/2000) gkh
- Added port_lock to port structure.
-
- (08/08/2000) gkh
- Added open_count to port structure.
-
- (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.
-
------------------------------------------------------------------------
-usb-serial.c Change Log comments:
-
- (12/10/2002) gkh
- Split the ports off into their own struct device, and added a
- usb-serial bus driver.
-
- (11/19/2002) gkh
- removed a few #ifdefs for the generic code and cleaned up the failure
- logic in initialization.
-
- (10/02/2002) gkh
- moved the console code to console.c and out of this file.
-
- (06/05/2002) gkh
- moved location of startup() call in serial_probe() until after all
- of the port information and endpoints are initialized. This makes
- things easier for some drivers.
-
- (04/10/2002) gkh
- added serial_read_proc function which creates a
- /proc/tty/driver/usb-serial file.
-
- (03/27/2002) gkh
- Got USB serial console code working properly and merged into the main
- version of the tree. Thanks to Randy Dunlap for the initial version
- of this code, and for pushing me to finish it up.
- The USB serial console works with any usb serial driver device.
-
- (03/21/2002) gkh
- Moved all manipulation of port->open_count into the core. Now the
- individual driver's open and close functions are called only when the
- first open() and last close() is called. Making the drivers a bit
- smaller and simpler.
- Fixed a bug if a driver didn't have the owner field set.
-
- (02/26/2002) gkh
- Moved all locking into the main serial_* functions, instead of having
- the individual drivers have to grab the port semaphore. This should
- reduce races.
- Reworked the MOD_INC logic a bit to always increment and decrement, even
- if the generic driver is being used.
-
- (10/10/2001) gkh
- usb_serial_disconnect() now sets the serial->dev pointer is to NULL to
- help prevent child drivers from accessing the device since it is now
- gone.
-
- (09/13/2001) gkh
- Moved generic driver initialize after we have registered with the USB
- core. Thanks to Randy Dunlap for pointing this problem out.
-
- (07/03/2001) gkh
- Fixed module paramater size. Thanks to John Brockmeyer for the pointer.
- Fixed vendor and product getting defined through the MODULE_PARM macro
- if the Generic driver wasn't compiled in.
- Fixed problem with generic_shutdown() not being called for drivers that
- don't have a shutdown() function.
-
- (06/06/2001) gkh
- added evil hack that is needed for the prolific pl2303 device due to the
- crazy way its endpoints are set up.
-
- (05/30/2001) gkh
- switched from using spinlock to a semaphore, which fixes lots of problems.
-
- (04/08/2001) gb
- Identify version on module load.
-
- 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 separate
- 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 continuous 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.
-
------------------------------------------------------------------------
-visor.c Change Log comments:
-
- (06/03/2003) Judd Montgomery <judd at jpilot.org>
- Added support for module parameter options for untested/unknown
- devices.
-
- (03/09/2003) gkh
- Added support for the Sony Clie NZ90V device. Thanks to Martin Brachtl
- <brachtl@redgrep.cz> for the information.
-
- (03/05/2003) gkh
- Think Treo support is now working.
-
- (04/03/2002) gkh
- Added support for the Sony OS 4.1 devices. Thanks to Hiroyuki ARAKI
- <hiro@zob.ne.jp> for the information.
-
- (03/27/2002) gkh
- Removed assumptions that port->tty was always valid (is not true
- for usb serial console devices.)
-
- (03/23/2002) gkh
- Added support for the Palm i705 device, thanks to Thomas Riemer
- <tom@netmech.com> for the information.
-
- (03/21/2002) gkh
- Added support for the Palm m130 device, thanks to Udo Eisenbarth
- <udo.eisenbarth@web.de> for the information.
-
- (02/27/2002) gkh
- Reworked the urb handling logic. We have no more pool, but dynamically
- allocate the urb and the transfer buffer on the fly. In testing this
- does not incure any measurable overhead. This also relies on the fact
- that we have proper reference counting logic for urbs.
-
- (02/21/2002) SilaS
- Added initial support for the Palm m515 devices.
-
- (02/14/2002) gkh
- Added support for the Clie S-360 device.
-
- (12/18/2001) gkh
- Added better Clie support for 3.5 devices. Thanks to Geoffrey Levand
- for the patch.
-
- (11/11/2001) gkh
- Added support for the m125 devices, and added check to prevent oopses
- for CliƩ devices that lie about the number of ports they have.
-
- (08/30/2001) gkh
- Added support for the Clie devices, both the 3.5 and 4.0 os versions.
- Many thanks to Daniel Burke, and Bryan Payne for helping with this.
-
- (08/23/2001) gkh
- fixed a few potential bugs pointed out by Oliver Neukum.
-
- (05/30/2001) gkh
- switched from using spinlock to a semaphore, which fixes lots of problems.
-
- (05/28/2000) gkh
- Added initial support for the Palm m500 and Palm m505 devices.
-
- (04/08/2001) gb
- Identify version on module load.
-
- (01/21/2000) gkh
- Added write_room and chars_in_buffer, as they were previously using the
- generic driver versions which is all wrong now that we are using an urb
- pool. Thanks to Wolfgang Grandegger for pointing this out to me.
- Removed count assignment in the write function, which was not needed anymore
- either. Thanks to Al Borchers for pointing this out.
-
- (12/12/2000) gkh
- Moved MOD_DEC to end of visor_close to be nicer, as the final write
- message can sleep.
-
- (11/12/2000) gkh
- Fixed bug with data being dropped on the floor by forcing tty->low_latency
- to be on. Hopefully this fixes the OHCI issue!
-
- (11/01/2000) Adam J. Richter
- usb_device_id table support
-
- (10/05/2000) gkh
- Fixed bug with urb->dev not being set properly, now that the usb
- core needs it.
-
- (09/11/2000) gkh
- Got rid of always calling kmalloc for every urb we wrote out to the
- device.
- Added visor_read_callback so we can keep track of bytes in and out for
- those people who like to know the speed of their device.
- Removed DEBUG #ifdefs with call to usb_serial_debug_data
-
- (09/06/2000) gkh
- Fixed oops in visor_exit. Need to uncomment usb_unlink_urb call _after_
- the host controller drivers set urb->dev = NULL when the urb is finished.
-
- (08/28/2000) gkh
- Added locks for SMP safeness.
-
- (08/08/2000) gkh
- Fixed endian problem in visor_startup.
- Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
- than once.
-
- (07/23/2000) gkh
- Added pool of write urbs to speed up transfers to the visor.
-
- (07/19/2000) gkh
- Added module_init and module_exit functions to handle the fact that this
- driver is a loadable module now.
-
- (07/03/2000) gkh
- Added visor_set_ioctl and visor_set_termios functions (they don't do much
- of anything, but are good for debugging.)
-
- (06/25/2000) gkh
- Fixed bug in visor_unthrottle that should help with the disconnect in PPP
- bug that people have been reporting.
-
- (06/23/2000) gkh
- Cleaned up debugging statements in a quest to find UHCI timeout bug.
-
- (04/27/2000) Ryan VanderBijl
- Fixed memory leak in visor_close
-
- (03/26/2000) gkh
- Split driver up into device specific pieces.
-
------------------------------------------------------------------------
-pl2303.c Change Log comments:
-
- 2002_Mar_26 gkh
- allowed driver to work properly if there is no tty assigned to a port
- (this happens for serial console devices.)
-
- 2001_Oct_06 gkh
- Added RTS and DTR line control. Thanks to joe@bndlg.de for parts of it.
-
- 2001_Sep_19 gkh
- Added break support.
-
- 2001_Aug_30 gkh
- fixed oops in write_bulk_callback.
-
- 2001_Aug_28 gkh
- reworked buffer logic to be like other usb-serial drivers. Hopefully
- removing some reported problems.
-
- 2001_Jun_06 gkh
- finished porting to 2.4 format.
-
-
------------------------------------------------------------------------
-io_edgeport.c Change Log comments:
-
- 2003_04_03 al borchers
- - fixed a bug (that shows up with dosemu) where the tty struct is
- used in a callback after it has been freed
-
- 2.3 2002_03_08 greg kroah-hartman
- - fixed bug when multiple devices were attached at the same time.
-
- 2.2 2001_11_14 greg kroah-hartman
- - fixed bug in edge_close that kept the port from being used more
- than once.
- - fixed memory leak on device removal.
- - fixed potential double free of memory when command urb submitting
- failed.
- - other small cleanups when the device is removed
-
- 2.1 2001_07_09 greg kroah-hartman
- - added support for TIOCMBIS and TIOCMBIC.
-
- (04/08/2001) gb
- - Identify version on module load.
-
- 2.0 2001_03_05 greg kroah-hartman
- - reworked entire driver to fit properly in with the other usb-serial
- drivers. Occasional oopses still happen, but it's a good start.
-
- 1.2.3 (02/23/2001) greg kroah-hartman
- - changed device table to work properly for 2.4.x final format.
- - fixed problem with dropping data at high data rates.
-
- 1.2.2 (11/27/2000) greg kroah-hartman
- - cleaned up more NTisms.
- - Added device table for 2.4.0-test11
-
- 1.2.1 (11/08/2000) greg kroah-hartman
- - Started to clean up NTisms.
- - Fixed problem with dev field of urb for kernels >= 2.4.0-test9
-
- 1.2 (10/17/2000) David Iacovelli
- Remove all EPIC code and GPL source
- Fix RELEVANT_IFLAG macro to include flow control
- changes port configuration changes.
- Fix redefinition of SERIAL_MAGIC
- Change all timeout values to 5 seconds
- Tried to fix the UHCI multiple urb submission, but failed miserably.
- it seems to work fine with OHCI.
- ( Greg take a look at the #if 0 at end of WriteCmdUsb() we must
- find a way to work arount this UHCI bug )
-
- 1.1 (10/11/2000) David Iacovelli
- Fix XON/XOFF flow control to support both IXON and IXOFF
-
- 0.9.27 (06/30/2000) David Iacovelli
- Added transmit queue and now allocate urb for command writes.
-
- 0.9.26 (06/29/2000) David Iacovelli
- Add support for 80251 based edgeport
-
- 0.9.25 (06/27/2000) David Iacovelli
- Do not close the port if it has multiple opens.
-
- 0.9.24 (05/26/2000) David Iacovelli
- Add IOCTLs to support RXTX and JAVA POS
- and first cut at running BlackBox Demo
-
- 0.9.23 (05/24/2000) David Iacovelli
- Add IOCTLs to support RXTX and JAVA POS
-
- 0.9.22 (05/23/2000) David Iacovelli
- fixed bug in enumeration. If epconfig turns on mapping by
- path after a device is already plugged in, we now update
- the mapping correctly
-
- 0.9.21 (05/16/2000) David Iacovelli
- Added BlockUntilChaseResp() to also wait for txcredits
- Updated the way we allocate and handle write URBs
- Add debug code to dump buffers
-
- 0.9.20 (05/01/2000) David Iacovelli
- change driver to use usb/tts/
-
- 0.9.19 (05/01/2000) David Iacovelli
- Update code to compile if DEBUG is off
-
- 0.9.18 (04/28/2000) David Iacovelli
- cleanup and test tty_register with devfs
-
- 0.9.17 (04/27/2000) greg kroah-hartman
- changed tty_register around to be like the way it
- was before, but now it works properly with devfs.
-
- 0.9.16 (04/26/2000) david iacovelli
- Fixed bug in GetProductInfo()
-
- 0.9.15 (04/25/2000) david iacovelli
- Updated enumeration
-
- 0.9.14 (04/24/2000) david iacovelli
- Removed all config/status IOCTLS and
- converted to using /proc/edgeport
- still playing with devfs
-
- 0.9.13 (04/24/2000) david iacovelli
- Removed configuration based on ttyUSB0
- Added support for configuration using /prod/edgeport
- first attempt at using devfs (not working yet!)
- Added IOCTL to GetProductInfo()
- Added support for custom baud rates
- Add support for random port numbers
-
- 0.9.12 (04/18/2000) david iacovelli
- added additional configuration IOCTLs
- use ttyUSB0 for configuration
-
- 0.9.11 (04/17/2000) greg kroah-hartman
- fixed module initialization race conditions.
- made all urbs dynamically allocated.
- made driver devfs compatible. now it only registers the tty device
- when the device is actually plugged in.
-
- 0.9.10 (04/13/2000) greg kroah-hartman
- added proc interface framework.
-
- 0.9.9 (04/13/2000) david iacovelli
- added enumeration code and ioctls to configure the device
-
- 0.9.8 (04/12/2000) david iacovelli
- Change interrupt read start when device is plugged in
- and stop when device is removed
- process interrupt reads when all ports are closed
- (keep value of rxBytesAvail consistent with the edgeport)
- set the USB_BULK_QUEUE flag so that we can shove a bunch
- of urbs at once down the pipe
-
- 0.9.7 (04/10/2000) david iacovelli
- start to add enumeration code.
- generate serial number for epic devices
- add support for kdb
-
- 0.9.6 (03/30/2000) david iacovelli
- add IOCTL to get string, manufacture, and boot descriptors
-
- 0.9.5 (03/14/2000) greg kroah-hartman
- more error checking added to SerialOpen to try to fix UHCI open problem
-
- 0.9.4 (03/09/2000) greg kroah-hartman
- added more error checking to handle oops when data is hanging
- around and tty is abruptly closed.
-
- 0.9.3 (03/09/2000) david iacovelli
- Add epic support for xon/xoff chars
- play with performance
-
- 0.9.2 (03/08/2000) greg kroah-hartman
- changed most "info" calls to "dbg"
- implemented flow control properly in the termios call
-
- 0.9.1 (03/08/2000) david iacovelli
- added EPIC support
- enabled bootloader update
-
- 0.9 (03/08/2000) greg kroah-hartman
- Release to IO networks.
- Integrated changes that David made
- made getting urbs for writing SMP safe
-
- 0.8 (03/07/2000) greg kroah-hartman
- Release to IO networks.
- Fixed problems that were seen in code by David.
- Now both Edgeport/4 and Edgeport/2 works properly.
- Changed most of the functions to use port instead of serial.
-
- 0.7 (02/27/2000) greg kroah-hartman
- Milestone 3 release.
- Release to IO Networks
- ioctl for waiting on line change implemented.
- ioctl for getting statistics implemented.
- multiport support working.
- lsr and msr registers are now handled properly.
- change break now hooked up and working.
- support for all known Edgeport devices.
-
- 0.6 (02/22/2000) greg kroah-hartman
- Release to IO networks.
- CHASE is implemented correctly when port is closed.
- SerialOpen now blocks correctly until port is fully opened.
-
- 0.5 (02/20/2000) greg kroah-hartman
- Release to IO networks.
- Known problems:
- modem status register changes are not sent on to the user
- CHASE is not implemented when the port is closed.
-
- 0.4 (02/16/2000) greg kroah-hartman
- Second cut at the CeBit demo.
- Doesn't leak memory on every write to the port
- Still small leaks on startup.
- Added support for Edgeport/2 and Edgeport/8
-
- 0.3 (02/15/2000) greg kroah-hartman
- CeBit demo release.
- Force the line settings to 4800, 8, 1, e for the demo.
- Warning! This version leaks memory like crazy!
-
- 0.2 (01/30/2000) greg kroah-hartman
- Milestone 1 release.
- Device is found by USB subsystem, enumerated, firmware is downloaded
- and the descriptors are printed to the debug log, config is set, and
- green light starts to blink. Open port works, and data can be sent
- and received at the default settings of the UART. Loopback connector
- and debug log confirms this.
-
- 0.1 (01/23/2000) greg kroah-hartman
- Initial release to help IO Networks try to set up their test system.
- Edgeport4 is recognized, firmware is downloaded, config is set so
- device blinks green light every 3 sec. Port is bound, but opening,
- closing, and sending data do not work properly.
-
-
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index c2b29761fa9..3ce5c74b29e 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -4,7 +4,7 @@
menuconfig USB_SERIAL
tristate "USB Serial Converter support"
- depends on USB
+ depends on TTY
---help---
Say Y here if you have a USB device that provides normal serial
ports, or acts like a serial device, and you want to connect it to
@@ -42,11 +42,6 @@ config USB_SERIAL_CONSOLE
If unsure, say N.
-config USB_EZUSB
- bool "Functions for loading firmware on EZUSB chips"
- help
- Say Y here if you need EZUSB device support.
-
config USB_SERIAL_GENERIC
bool "USB Generic Serial Driver"
help
@@ -56,6 +51,24 @@ config USB_SERIAL_GENERIC
support" be compiled as a module for this driver to be used
properly.
+config USB_SERIAL_SIMPLE
+ tristate "USB Serial Simple Driver"
+ help
+ Say Y here to use the USB serial "simple" driver. This driver
+ handles a wide range of very simple devices, all in one
+ driver. Specifically, it supports:
+ - Suunto ANT+ USB device.
+ - Fundamental Software dongle.
+ - HP4x calculators
+ - a number of Motorola phones
+ - Siemens USB/MPI adapter.
+ - ViVOtech ViVOpay USB device.
+ - Infineon Modem Flashloader USB interface
+ - ZIO Motherboard USB serial interface
+
+ To compile this driver as a module, choose M here: the module
+ will be called usb-serial-simple.
+
config USB_SERIAL_AIRCABLE
tristate "USB AIRcable Bluetooth Dongle Driver"
help
@@ -94,7 +107,7 @@ config USB_SERIAL_CH341
config USB_SERIAL_WHITEHEAT
tristate "USB ConnectTech WhiteHEAT Serial Driver"
- select USB_EZUSB
+ select USB_EZUSB_FX2
help
Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
USB to serial converter device.
@@ -163,14 +176,6 @@ config USB_SERIAL_FTDI_SIO
To compile this driver as a module, choose M here: the
module will be called ftdi_sio.
-config USB_SERIAL_FUNSOFT
- tristate "USB Fundamental Software Dongle Driver"
- ---help---
- Say Y here if you want to use the Fundamental Software dongle.
-
- To compile this driver as a module, choose M here: the
- module will be called funsoft.
-
config USB_SERIAL_VISOR
tristate "USB Handspring Visor / Palm m50x / Sony Clie Driver"
help
@@ -238,6 +243,15 @@ config USB_SERIAL_EDGEPORT_TI
To compile this driver as a module, choose M here: the
module will be called io_ti.
+config USB_SERIAL_F81232
+ tristate "USB Fintek F81232 Single Port Serial Driver"
+ help
+ Say Y here if you want to use the Fintek F81232 single
+ port usb to serial adapter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called f81232.
+
config USB_SERIAL_GARMIN
tristate "USB Garmin GPS driver"
help
@@ -252,6 +266,7 @@ config USB_SERIAL_GARMIN
config USB_SERIAL_IPW
tristate "USB IPWireless (3G UMTS TDD) Driver"
+ select USB_SERIAL_WWAN
help
Say Y here if you want to use a IPWireless USB modem such as
the ones supplied by Axity3G/Sentech South Africa.
@@ -271,7 +286,7 @@ config USB_SERIAL_IUU
config USB_SERIAL_KEYSPAN_PDA
tristate "USB Keyspan PDA Single Port Serial Driver"
- select USB_EZUSB
+ select USB_EZUSB_FX2
help
Say Y here if you want to use a Keyspan PDA single port USB to
serial converter device. This driver makes use of firmware
@@ -282,7 +297,7 @@ config USB_SERIAL_KEYSPAN_PDA
config USB_SERIAL_KEYSPAN
tristate "USB Keyspan USA-xxx Serial Driver"
- select USB_EZUSB
+ select USB_EZUSB_FX2
---help---
Say Y here if you want to use Keyspan USB to serial converter
devices. This driver makes use of Keyspan's official firmware
@@ -416,6 +431,14 @@ config USB_SERIAL_MCT_U232
To compile this driver as a module, choose M here: the
module will be called mct_u232.
+config USB_SERIAL_METRO
+ tristate "USB Metrologic Instruments USB-POS Barcode Scanner Driver"
+ ---help---
+ Say Y here if you want to use a USB POS Metrologic barcode scanner.
+
+ To compile this driver as a module, choose M here: the
+ module will be called metro-usb.
+
config USB_SERIAL_MOS7720
tristate "USB Moschip 7720 Serial Driver"
---help---
@@ -449,14 +472,34 @@ config USB_SERIAL_MOS7840
To compile this driver as a module, choose M here: the
module will be called mos7840. If unsure, choose N.
-config USB_SERIAL_MOTOROLA
- tristate "USB Motorola Phone modem driver"
+config USB_SERIAL_MXUPORT
+ tristate "USB Moxa UPORT Serial Driver"
---help---
- Say Y here if you want to use a Motorola phone with a USB
- connector as a modem link.
+ Say Y here if you want to use a MOXA UPort Serial hub.
+
+ This driver supports:
+
+ [2 Port]
+ - UPort 1250 : 2 Port RS-232/422/485 USB to Serial Hub
+ - UPort 1250I : 2 Port RS-232/422/485 USB to Serial Hub with
+ Isolation
+
+ [4 Port]
+ - UPort 1410 : 4 Port RS-232 USB to Serial Hub
+ - UPort 1450 : 4 Port RS-232/422/485 USB to Serial Hub
+ - UPort 1450I : 4 Port RS-232/422/485 USB to Serial Hub with
+ Isolation
+
+ [8 Port]
+ - UPort 1610-8 : 8 Port RS-232 USB to Serial Hub
+ - UPort 1650-8 : 8 Port RS-232/422/485 USB to Serial Hub
+
+ [16 Port]
+ - UPort 1610-16 : 16 Port RS-232 USB to Serial Hub
+ - UPort 1650-16 : 16 Port RS-232/422/485 USB to Serial Hub
To compile this driver as a module, choose M here: the
- module will be called moto_modem. If unsure, choose N.
+ module will be called mxuport.
config USB_SERIAL_NAVMAN
tristate "USB Navman GPS device"
@@ -512,14 +555,6 @@ config USB_SERIAL_SPCP8X5
To compile this driver as a module, choose M here: the
module will be called spcp8x5.
-config USB_SERIAL_HP4X
- tristate "USB HP4x Calculators support"
- help
- Say Y here if you want to use an Hewlett-Packard 4x Calculator.
-
- To compile this driver as a module, choose M here: the
- module will be called hp4x.
-
config USB_SERIAL_SAFE
tristate "USB Safe Serial (Encapsulated) Driver"
@@ -527,23 +562,6 @@ config USB_SERIAL_SAFE_PADDED
bool "USB Secure Encapsulated Driver - Padded"
depends on USB_SERIAL_SAFE
-config USB_SERIAL_SAMBA
- tristate "USB Atmel SAM Boot Assistant (SAM-BA) driver"
- help
- Say Y here if you want to access the SAM-BA boot application of an
- Atmel AT91SAM device.
-
- To compile this driver as a module, choose M here: the
- module will be called sam-ba.
-
-config USB_SERIAL_SIEMENS_MPI
- tristate "USB Siemens MPI driver"
- help
- Say M here if you want to use a Siemens USB/MPI adapter.
-
- To compile this driver as a module, choose M here: the
- module will be called siemens_mpi.
-
config USB_SERIAL_SIERRAWIRELESS
tristate "USB Sierra Wireless Driver"
help
@@ -587,7 +605,7 @@ config USB_SERIAL_CYBERJACK
config USB_SERIAL_XIRCOM
tristate "USB Xircom / Entregra Single Port Serial Driver"
- select USB_EZUSB
+ select USB_EZUSB_FX2
help
Say Y here if you want to use a Xircom or Entregra single port USB to
serial converter device. This driver makes use of firmware
@@ -635,21 +653,42 @@ config USB_SERIAL_OPTICON
To compile this driver as a module, choose M here: the
module will be called opticon.
-config USB_SERIAL_VIVOPAY_SERIAL
- tristate "USB ViVOpay serial interface driver"
- help
- Say Y here if you want to use a ViVOtech ViVOpay USB device.
+config USB_SERIAL_XSENS_MT
+ tristate "Xsens motion tracker serial interface driver"
+ help
+ Say Y here if you want to use Xsens motion trackers.
- To compile this driver as a module, choose M here: the
- module will be called vivopay-serial.
+ This driver supports the new generation of motion trackers
+ by Xsens. Older devices can be accessed using the FTDI_SIO
+ driver.
-config USB_SERIAL_ZIO
- tristate "ZIO Motherboard USB serial interface driver"
+ To compile this driver as a module, choose M here: the
+ module will be called xsens_mt.
+
+config USB_SERIAL_WISHBONE
+ tristate "USB-Wishbone adapter interface driver"
+ help
+ Say Y here if you want to use a USB attached Wishbone bus.
+
+ Wishbone is an open hardware SoC bus commonly used in FPGA
+ designs. Bus access can be serialized using the Etherbone
+ protocol <http://www.ohwr.org/projects/etherbone-core>.
+
+ This driver is intended to be used with devices which attach
+ their internal Wishbone bus to a USB serial interface using
+ the Etherbone protocol. A userspace library is required to
+ speak the protocol made available by this driver as ttyUSBx.
+
+ To compile this driver as a module, choose M here: the
+ module will be called wishbone-serial.
+
+config USB_SERIAL_ZTE
+ tristate "ZTE USB serial driver"
help
- Say Y here if you want to use ZIO Motherboard.
+ Say Y here if you want to use a ZTE USB to serial device.
To compile this driver as a module, choose M here: the
- module will be called zio.
+ module will be called zte.
config USB_SERIAL_SSU100
tristate "USB Quatech SSU-100 Single Port Serial Driver"
@@ -660,6 +699,15 @@ config USB_SERIAL_SSU100
To compile this driver as a module, choose M here: the
module will be called ssu100.
+config USB_SERIAL_QT2
+ tristate "USB Quatech Serial Driver for USB 2 devices"
+ help
+ Say Y here if you want to use the Quatech USB 2
+ serial adapters.
+
+ To compile this driver as a module, choose M here: the
+ module will be called quatech-serial.
+
config USB_SERIAL_DEBUG
tristate "USB Debugging Device"
help
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 9a2117f2b06..bfdafd34944 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_USB_SERIAL) += usbserial.o
usbserial-y := usb-serial.o generic.o bus.o
usbserial-$(CONFIG_USB_SERIAL_CONSOLE) += console.o
-usbserial-$(CONFIG_USB_EZUSB) += ezusb.o
obj-$(CONFIG_USB_SERIAL_AIRCABLE) += aircable.o
obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o
@@ -23,10 +22,9 @@ obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o
obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o
+obj-$(CONFIG_USB_SERIAL_F81232) += f81232.o
obj-$(CONFIG_USB_SERIAL_FTDI_SIO) += ftdi_sio.o
-obj-$(CONFIG_USB_SERIAL_FUNSOFT) += funsoft.o
obj-$(CONFIG_USB_SERIAL_GARMIN) += garmin_gps.o
-obj-$(CONFIG_USB_SERIAL_HP4X) += hp4x.o
obj-$(CONFIG_USB_SERIAL_IPAQ) += ipaq.o
obj-$(CONFIG_USB_SERIAL_IPW) += ipw.o
obj-$(CONFIG_USB_SERIAL_IR) += ir-usb.o
@@ -36,9 +34,10 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o
obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o
obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o
obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o
+obj-$(CONFIG_USB_SERIAL_METRO) += metro-usb.o
obj-$(CONFIG_USB_SERIAL_MOS7720) += mos7720.o
obj-$(CONFIG_USB_SERIAL_MOS7840) += mos7840.o
-obj-$(CONFIG_USB_SERIAL_MOTOROLA) += moto_modem.o
+obj-$(CONFIG_USB_SERIAL_MXUPORT) += mxuport.o
obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o
obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o
obj-$(CONFIG_USB_SERIAL_OPTICON) += opticon.o
@@ -47,17 +46,18 @@ obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o
obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
obj-$(CONFIG_USB_SERIAL_QCAUX) += qcaux.o
obj-$(CONFIG_USB_SERIAL_QUALCOMM) += qcserial.o
+obj-$(CONFIG_USB_SERIAL_QT2) += quatech2.o
obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
-obj-$(CONFIG_USB_SERIAL_SAMBA) += sam-ba.o
-obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o
obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o
+obj-$(CONFIG_USB_SERIAL_SIMPLE) += usb-serial-simple.o
obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o
obj-$(CONFIG_USB_SERIAL_SSU100) += ssu100.o
obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o
obj-$(CONFIG_USB_SERIAL_WWAN) += usb_wwan.o
obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o
+obj-$(CONFIG_USB_SERIAL_WISHBONE) += wishbone-serial.o
obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o
obj-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda.o
-obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL) += vivopay-serial.o
-obj-$(CONFIG_USB_SERIAL_ZIO) += zio.o
+obj-$(CONFIG_USB_SERIAL_XSENS_MT) += xsens_mt.o
+obj-$(CONFIG_USB_SERIAL_ZTE) += zte_ev.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 0db6ace16f7..80a9845cd93 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -10,13 +10,13 @@
*
* The device works as an standard CDC device, it has 2 interfaces, the first
* one is for firmware access and the second is the serial one.
- * The protocol is very simply, there are two posibilities reading or writing.
+ * The protocol is very simply, there are two possibilities reading or writing.
* When writing the first urb must have a Header that starts with 0x20 0x29 the
- * next two bytes must say how much data will be sended.
+ * next two bytes must say how much data will be sent.
* When reading the process is almost equal except that the header starts with
* 0x00 0x20.
*
- * The device simply need some stuff to understand data comming from the usb
+ * The device simply need some stuff to understand data coming from the usb
* buffer: The First and Second byte is used for a Header, the Third and Fourth
* tells the device the amount of information the package holds.
* Packages are 60 bytes long Header Stuff.
@@ -30,16 +30,16 @@
* one.
*
* The driver registers himself with the USB-serial core and the USB Core. I had
- * to implement a probe function agains USB-serial, because other way, the
- * driver was attaching himself to both interfaces. I have tryed with different
+ * to implement a probe function against USB-serial, because other way, the
+ * driver was attaching himself to both interfaces. I have tried with different
* configurations of usb_serial_driver with out exit, only the probe function
* could handle this correctly.
*
* I have taken some info from a Greg Kroah-Hartman article:
* http://www.linuxjournal.com/article/6573
* And from Linux Device Driver Kit CD, which is a great work, the authors taken
- * the work to recompile lots of information an knowladge in drivers development
- * and made it all avaible inside a cd.
+ * the work to recompile lots of information an knowledge in drivers development
+ * and made it all available inside a cd.
* URL: http://kernel.org/pub/linux/kernel/people/gregkh/ddk/
*
*/
@@ -47,12 +47,11 @@
#include <asm/unaligned.h>
#include <linux/tty.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <linux/tty_flip.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-static int debug;
-
/* Vendor and Product ID */
#define AIRCABLE_VID 0x16CA
#define AIRCABLE_USB_PID 0x1502
@@ -69,10 +68,6 @@ static int debug;
#define THROTTLED 0x01
#define ACTUALLY_THROTTLED 0x02
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v2.0"
#define DRIVER_AUTHOR "Naranjo, Manuel Francisco <naranjo.manuel@gmail.com>, Johan Hovold <jhovold@gmail.com>"
#define DRIVER_DESC "AIRcable USB Driver"
@@ -110,33 +105,33 @@ static int aircable_probe(struct usb_serial *serial,
for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
endpoint = &iface_desc->endpoint[i].desc;
if (usb_endpoint_is_bulk_out(endpoint)) {
- dbg("found bulk out on endpoint %d", i);
+ dev_dbg(&serial->dev->dev,
+ "found bulk out on endpoint %d\n", i);
++num_bulk_out;
}
}
if (num_bulk_out == 0) {
- dbg("Invalid interface, discarding");
+ dev_dbg(&serial->dev->dev, "Invalid interface, discarding\n");
return -ENODEV;
}
return 0;
}
-static int aircable_process_packet(struct tty_struct *tty,
- struct usb_serial_port *port, int has_headers,
- char *packet, int len)
+static int aircable_process_packet(struct usb_serial_port *port,
+ int has_headers, char *packet, int len)
{
if (has_headers) {
len -= HCI_HEADER_LENGTH;
packet += HCI_HEADER_LENGTH;
}
if (len <= 0) {
- dbg("%s - malformed packet", __func__);
+ dev_dbg(&port->dev, "%s - malformed packet\n", __func__);
return 0;
}
- tty_insert_flip_string(tty, packet, len);
+ tty_insert_flip_string(&port->port, packet, len);
return len;
}
@@ -145,44 +140,29 @@ static void aircable_process_read_urb(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
char *data = (char *)urb->transfer_buffer;
- struct tty_struct *tty;
int has_headers;
int count;
int len;
int i;
- tty = tty_port_tty_get(&port->port);
- if (!tty)
- return;
-
has_headers = (urb->actual_length > 2 && data[0] == RX_HEADER_0);
count = 0;
for (i = 0; i < urb->actual_length; i += HCI_COMPLETE_FRAME) {
len = min_t(int, urb->actual_length - i, HCI_COMPLETE_FRAME);
- count += aircable_process_packet(tty, port, has_headers,
+ count += aircable_process_packet(port, has_headers,
&data[i], len);
}
if (count)
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
+ tty_flip_buffer_push(&port->port);
}
-static struct usb_driver aircable_driver = {
- .name = "aircable",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
static struct usb_serial_driver aircable_device = {
.driver = {
.owner = THIS_MODULE,
.name = "aircable",
},
- .usb_driver = &aircable_driver,
.id_table = id_table,
.num_ports = 1,
.bulk_out_size = HCI_COMPLETE_FRAME,
@@ -193,36 +173,12 @@ static struct usb_serial_driver aircable_device = {
.unthrottle = usb_serial_generic_unthrottle,
};
-static int __init aircable_init(void)
-{
- int retval;
- retval = usb_serial_register(&aircable_device);
- if (retval)
- goto failed_serial_register;
- retval = usb_register(&aircable_driver);
- if (retval)
- goto failed_usb_register;
- return 0;
+static struct usb_serial_driver * const serial_drivers[] = {
+ &aircable_device, NULL
+};
-failed_usb_register:
- usb_serial_deregister(&aircable_device);
-failed_serial_register:
- return retval;
-}
-
-static void __exit aircable_exit(void)
-{
- usb_deregister(&aircable_driver);
- usb_serial_deregister(&aircable_device);
-}
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
-
-module_init(aircable_init);
-module_exit(aircable_exit);
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 8f1d4fb19d2..1532cde8a43 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -23,7 +23,6 @@
*/
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/ioctl.h>
#include <linux/tty.h>
#include <linux/slab.h>
@@ -37,19 +36,13 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
-static int debug;
-/*
- * Version information
- */
-
-#define DRIVER_VERSION "v0.6"
#define DRIVER_AUTHOR "Bart Hartgers <bart.hartgers+ark3116@gmail.com>"
#define DRIVER_DESC "USB ARK3116 serial/IrDA driver"
#define DRIVER_DEV_DESC "ARK3116 RS232/IrDA"
#define DRIVER_NAME "ark3116"
/* usb timeout of 1 second */
-#define ARK_TIMEOUT (1*HZ)
+#define ARK_TIMEOUT 1000
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x6547, 0x0232) },
@@ -68,8 +61,6 @@ static int is_irda(struct usb_serial *serial)
}
struct ark3116_private {
- wait_queue_head_t delta_msr_wait;
- struct async_icount icount;
int irda; /* 1 for irda device */
/* protects hw register updates */
@@ -79,7 +70,7 @@ struct ark3116_private {
__u32 lcr; /* line control register value */
__u32 hcr; /* handshake control register (0x8)
* value */
- __u32 mcr; /* modem contol register value */
+ __u32 mcr; /* modem control register value */
/* protects the status values below */
spinlock_t status_lock;
@@ -126,9 +117,6 @@ static inline int calc_divisor(int bps)
static int ark3116_attach(struct usb_serial *serial)
{
- struct usb_serial_port *port = serial->port[0];
- struct ark3116_private *priv;
-
/* make sure we have our end-points */
if ((serial->num_bulk_in == 0) ||
(serial->num_bulk_out == 0) ||
@@ -143,12 +131,18 @@ static int ark3116_attach(struct usb_serial *serial)
return -EINVAL;
}
- priv = kzalloc(sizeof(struct ark3116_private),
- GFP_KERNEL);
+ return 0;
+}
+
+static int ark3116_port_probe(struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+ struct ark3116_private *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
- init_waitqueue_head(&priv->delta_msr_wait);
mutex_init(&priv->hw_lock);
spin_lock_init(&priv->status_lock);
@@ -199,23 +193,20 @@ static int ark3116_attach(struct usb_serial *serial)
return 0;
}
-static void ark3116_release(struct usb_serial *serial)
+static int ark3116_port_remove(struct usb_serial_port *port)
{
- struct usb_serial_port *port = serial->port[0];
struct ark3116_private *priv = usb_get_serial_port_data(port);
/* device is closed, so URBs and DMA should be down */
-
- usb_set_serial_port_data(port, NULL);
-
mutex_destroy(&priv->hw_lock);
-
kfree(priv);
+
+ return 0;
}
static void ark3116_init_termios(struct tty_struct *tty)
{
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
*termios = tty_std_termios;
termios->c_cflag = B9600 | CS8
| CREAD | HUPCL | CLOCAL;
@@ -229,7 +220,7 @@ static void ark3116_set_termios(struct tty_struct *tty,
{
struct usb_serial *serial = port->serial;
struct ark3116_private *priv = usb_get_serial_port_data(port);
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
unsigned int cflag = termios->c_cflag;
int bps = tty_get_baud_rate(tty);
int quot;
@@ -265,7 +256,7 @@ static void ark3116_set_termios(struct tty_struct *tty,
hcr = (cflag & CRTSCTS) ? 0x03 : 0x00;
/* calc baudrate */
- dbg("%s - setting bps to %d", __func__, bps);
+ dev_dbg(&port->dev, "%s - setting bps to %d\n", __func__, bps);
eval = 0;
switch (bps) {
case 0:
@@ -292,8 +283,8 @@ static void ark3116_set_termios(struct tty_struct *tty,
/* keep old LCR_SBC bit */
lcr |= (priv->lcr & UART_LCR_SBC);
- dbg("%s - setting hcr:0x%02x,lcr:0x%02x,quot:%d",
- __func__, hcr, lcr, quot);
+ dev_dbg(&port->dev, "%s - setting hcr:0x%02x,lcr:0x%02x,quot:%d\n",
+ __func__, hcr, lcr, quot);
/* handshake control */
if (priv->hcr != hcr) {
@@ -348,18 +339,15 @@ static void ark3116_close(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
- if (serial->dev) {
- /* disable DMA */
- ark3116_write_reg(serial, UART_FCR, 0);
-
- /* deactivate interrupts */
- ark3116_write_reg(serial, UART_IER, 0);
+ /* disable DMA */
+ ark3116_write_reg(serial, UART_FCR, 0);
- usb_serial_generic_close(port);
- if (serial->num_interrupt_in)
- usb_kill_urb(port->interrupt_in_urb);
- }
+ /* deactivate interrupts */
+ ark3116_write_reg(serial, UART_IER, 0);
+ usb_serial_generic_close(port);
+ if (serial->num_interrupt_in)
+ usb_kill_urb(port->interrupt_in_urb);
}
static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -375,15 +363,12 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
result = usb_serial_generic_open(tty, port);
if (result) {
- dbg("%s - usb_serial_generic_open failed: %d",
- __func__, result);
+ dev_dbg(&port->dev,
+ "%s - usb_serial_generic_open failed: %d\n",
+ __func__, result);
goto err_out;
}
- /* setup termios */
- if (tty)
- ark3116_set_termios(tty, port, NULL);
-
/* remove any data still left: also clears error state */
ark3116_read_reg(serial, UART_RX, buf);
@@ -406,36 +391,19 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
/* enable DMA */
ark3116_write_reg(port->serial, UART_FCR, UART_FCR_DMA_SELECT);
+ /* setup termios */
+ if (tty)
+ ark3116_set_termios(tty, port, NULL);
+
err_out:
kfree(buf);
return result;
}
-static int ark3116_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct ark3116_private *priv = usb_get_serial_port_data(port);
- struct async_icount cnow = priv->icount;
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
- return 0;
-}
-
-static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
+static int ark3116_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
- struct ark3116_private *priv = usb_get_serial_port_data(port);
struct serial_struct serstruct;
void __user *user_arg = (void __user *)arg;
@@ -444,8 +412,8 @@ static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
/* XXX: Some of these values are probably wrong. */
memset(&serstruct, 0, sizeof(serstruct));
serstruct.type = PORT_16654;
- serstruct.line = port->serial->minor;
- serstruct.port = port->number;
+ serstruct.line = port->minor;
+ serstruct.port = port->port_number;
serstruct.custom_divisor = 0;
serstruct.baud_base = 460800;
@@ -457,35 +425,12 @@ static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
if (copy_from_user(&serstruct, user_arg, sizeof(serstruct)))
return -EFAULT;
return 0;
- case TIOCMIWAIT:
- for (;;) {
- struct async_icount prev = priv->icount;
- interruptible_sleep_on(&priv->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- if ((prev.rng == priv->icount.rng) &&
- (prev.dsr == priv->icount.dsr) &&
- (prev.dcd == priv->icount.dcd) &&
- (prev.cts == priv->icount.cts))
- return -EIO;
- if ((arg & TIOCM_RNG &&
- (prev.rng != priv->icount.rng)) ||
- (arg & TIOCM_DSR &&
- (prev.dsr != priv->icount.dsr)) ||
- (arg & TIOCM_CD &&
- (prev.dcd != priv->icount.dcd)) ||
- (arg & TIOCM_CTS &&
- (prev.cts != priv->icount.cts)))
- return 0;
- }
- break;
}
return -ENOIOCTLCMD;
}
-static int ark3116_tiocmget(struct tty_struct *tty, struct file *file)
+static int ark3116_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct ark3116_private *priv = usb_get_serial_port_data(port);
@@ -511,7 +456,7 @@ static int ark3116_tiocmget(struct tty_struct *tty, struct file *file)
(ctrl & UART_MCR_OUT2 ? TIOCM_OUT2 : 0);
}
-static int ark3116_tiocmset(struct tty_struct *tty, struct file *file,
+static int ark3116_tiocmset(struct tty_struct *tty,
unsigned set, unsigned clr)
{
struct usb_serial_port *port = tty->driver_data;
@@ -577,14 +522,14 @@ static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr)
if (msr & UART_MSR_ANY_DELTA) {
/* update input line counters */
if (msr & UART_MSR_DCTS)
- priv->icount.cts++;
+ port->icount.cts++;
if (msr & UART_MSR_DDSR)
- priv->icount.dsr++;
+ port->icount.dsr++;
if (msr & UART_MSR_DDCD)
- priv->icount.dcd++;
+ port->icount.dcd++;
if (msr & UART_MSR_TERI)
- priv->icount.rng++;
- wake_up_interruptible(&priv->delta_msr_wait);
+ port->icount.rng++;
+ wake_up_interruptible(&port->port.delta_msr_wait);
}
}
@@ -600,13 +545,13 @@ static void ark3116_update_lsr(struct usb_serial_port *port, __u8 lsr)
if (lsr&UART_LSR_BRK_ERROR_BITS) {
if (lsr & UART_LSR_BI)
- priv->icount.brk++;
+ port->icount.brk++;
if (lsr & UART_LSR_FE)
- priv->icount.frame++;
+ port->icount.frame++;
if (lsr & UART_LSR_PE)
- priv->icount.parity++;
+ port->icount.parity++;
if (lsr & UART_LSR_OE)
- priv->icount.overrun++;
+ port->icount.overrun++;
}
}
@@ -622,24 +567,26 @@ static void ark3116_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
break;
case 0: /* success */
/* discovered this by trail and error... */
if ((urb->actual_length == 4) && (data[0] == 0xe8)) {
const __u8 id = data[1]&UART_IIR_ID;
- dbg("%s: iir=%02x", __func__, data[1]);
+ dev_dbg(&port->dev, "%s: iir=%02x\n", __func__, data[1]);
if (id == UART_IIR_MSI) {
- dbg("%s: msr=%02x", __func__, data[3]);
+ dev_dbg(&port->dev, "%s: msr=%02x\n",
+ __func__, data[3]);
ark3116_update_msr(port, data[3]);
break;
} else if (id == UART_IIR_RLSI) {
- dbg("%s: lsr=%02x", __func__, data[2]);
+ dev_dbg(&port->dev, "%s: lsr=%02x\n",
+ __func__, data[2]);
ark3116_update_lsr(port, data[2]);
break;
}
@@ -647,8 +594,7 @@ static void ark3116_read_int_callback(struct urb *urb)
/*
* Not sure what this data meant...
*/
- usb_serial_debug_data(debug, &port->dev,
- __func__,
+ usb_serial_debug_data(&port->dev, __func__,
urb->actual_length,
urb->transfer_buffer);
break;
@@ -662,7 +608,7 @@ static void ark3116_read_int_callback(struct urb *urb)
}
-/* Data comes in via the bulk (data) URB, erors/interrupts via the int URB.
+/* Data comes in via the bulk (data) URB, errors/interrupts via the int URB.
* This means that we cannot be sure which data byte has an associated error
* condition, so we report an error for all data in the next bulk read.
*
@@ -677,7 +623,6 @@ static void ark3116_process_read_urb(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct ark3116_private *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
char tty_flag = TTY_NORMAL;
unsigned long flags;
@@ -692,10 +637,6 @@ static void ark3116_process_read_urb(struct urb *urb)
if (!urb->actual_length)
return;
- tty = tty_port_tty_get(&port->port);
- if (!tty)
- return;
-
if (lsr & UART_LSR_BRK_ERROR_BITS) {
if (lsr & UART_LSR_BI)
tty_flag = TTY_BREAK;
@@ -706,38 +647,30 @@ static void ark3116_process_read_urb(struct urb *urb)
/* overrun is special, not associated with a char */
if (lsr & UART_LSR_OE)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
}
- tty_insert_flip_string_fixed_flag(tty, data, tty_flag,
+ tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag,
urb->actual_length);
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
+ tty_flip_buffer_push(&port->port);
}
-static struct usb_driver ark3116_driver = {
- .name = "ark3116",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
static struct usb_serial_driver ark3116_device = {
.driver = {
.owner = THIS_MODULE,
.name = "ark3116",
},
.id_table = id_table,
- .usb_driver = &ark3116_driver,
.num_ports = 1,
.attach = ark3116_attach,
- .release = ark3116_release,
+ .port_probe = ark3116_port_probe,
+ .port_remove = ark3116_port_remove,
.set_termios = ark3116_set_termios,
.init_termios = ark3116_init_termios,
.ioctl = ark3116_ioctl,
.tiocmget = ark3116_tiocmget,
.tiocmset = ark3116_tiocmset,
- .get_icount = ark3116_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.open = ark3116_open,
.close = ark3116_close,
.break_ctl = ark3116_break_ctl,
@@ -745,40 +678,17 @@ static struct usb_serial_driver ark3116_device = {
.process_read_urb = ark3116_process_read_urb,
};
-static int __init ark3116_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&ark3116_device);
- if (retval)
- return retval;
- retval = usb_register(&ark3116_driver);
- if (retval == 0) {
- printk(KERN_INFO "%s:"
- DRIVER_VERSION ":"
- DRIVER_DESC "\n",
- KBUILD_MODNAME);
- } else
- usb_serial_deregister(&ark3116_device);
- return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ark3116_device, NULL
+};
-static void __exit ark3116_exit(void)
-{
- usb_deregister(&ark3116_driver);
- usb_serial_deregister(&ark3116_device);
-}
+module_usb_serial_driver(serial_drivers, id_table);
-module_init(ark3116_init);
-module_exit(ark3116_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debug");
-
/*
* The following describes what I learned from studying the old
* ark3116.c driver, disassembling the windows driver, and some lucky
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 36df35295db..15bc71853db 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -2,73 +2,29 @@
* Belkin USB Serial Adapter Driver
*
* Copyright (C) 2000 William Greathouse (wgreathouse@smva.com)
- * Copyright (C) 2000-2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2000-2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2010 Johan Hovold (jhovold@gmail.com)
*
* This program is largely derived from work by the linux-usb group
* and associated source files. Please see the usb/serial files for
* individual credits and copyrights.
*
- * 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 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.
*
* See Documentation/usb/usb-serial.txt for more information on using this
* driver
*
* TODO:
- * -- Add true modem contol line query capability. Currently we track the
+ * -- Add true modem control line query capability. Currently we track the
* states reported by the interrupt and the states we request.
- * -- Add error reporting back to application for UART error conditions.
- * Just point me at how to implement this and I'll do it. I've put the
- * framework in, but haven't analyzed the "tty_flip" interface yet.
* -- Add support for flush commands
- * -- Add everything that is missing :)
- *
- * 27-Nov-2001 gkh
- * compressed all the differnent device entries into 1.
- *
- * 30-May-2001 gkh
- * switched from using spinlock to a semaphore, which fixes lots of
- * problems.
- *
- * 08-Apr-2001 gb
- * - Identify version on module load.
- *
- * 12-Mar-2001 gkh
- * - Added support for the GoHubs GO-COM232 device which is the same as the
- * Peracom device.
- *
- * 06-Nov-2000 gkh
- * - Added support for the old Belkin and Peracom devices.
- * - Made the port able to be opened multiple times.
- * - Added some defaults incase the line settings are things these devices
- * can't support.
- *
- * 18-Oct-2000 William Greathouse
- * Released into the wild (linux-usb-devel)
- *
- * 17-Oct-2000 William Greathouse
- * Add code to recognize firmware version and set hardware flow control
- * appropriately. Belkin states that firmware prior to 3.05 does not
- * operate correctly in hardware handshake mode. I have verified this
- * on firmware 2.05 -- for both RTS and DTR input flow control, the control
- * line is not reset. The test performed by the Belkin Win* driver is
- * to enable hardware flow control for firmware 2.06 or greater and
- * for 1.00 or prior. I am only enabling for 2.06 or greater.
- *
- * 12-Oct-2000 William Greathouse
- * First cut at supporting Belkin USB Serial Adapter F5U103
- * I did not have a copy of the original work to support this
- * adapter, so pardon any stupid mistakes. All of the information
- * I am using to write this driver was acquired by using a modified
- * UsbSnoop on Windows2000 and from examining the other USB drivers.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -80,18 +36,12 @@
#include <linux/usb/serial.h>
#include "belkin_sa.h"
-static int debug;
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.3"
#define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>"
#define DRIVER_DESC "USB Belkin Serial converter driver"
/* function prototypes for a Belkin USB Serial Adapter F5U103 */
-static int belkin_sa_startup(struct usb_serial *serial);
-static void belkin_sa_release(struct usb_serial *serial);
+static int belkin_sa_port_probe(struct usb_serial_port *port);
+static int belkin_sa_port_remove(struct usb_serial_port *port);
static int belkin_sa_open(struct tty_struct *tty,
struct usb_serial_port *port);
static void belkin_sa_close(struct usb_serial_port *port);
@@ -100,12 +50,12 @@ static void belkin_sa_process_read_urb(struct urb *urb);
static void belkin_sa_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios * old);
static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state);
-static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file);
-static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
+static int belkin_sa_tiocmget(struct tty_struct *tty);
+static int belkin_sa_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
-static const struct usb_device_id id_table_combined[] = {
+static const struct usb_device_id id_table[] = {
{ USB_DEVICE(BELKIN_SA_VID, BELKIN_SA_PID) },
{ USB_DEVICE(BELKIN_OLD_VID, BELKIN_OLD_PID) },
{ USB_DEVICE(PERACOM_VID, PERACOM_PID) },
@@ -114,15 +64,7 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE(usb, id_table_combined);
-
-static struct usb_driver belkin_driver = {
- .name = "belkin",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
- .no_dynamic_id = 1,
-};
+MODULE_DEVICE_TABLE(usb, id_table);
/* All of the device info needed for the serial converters */
static struct usb_serial_driver belkin_device = {
@@ -131,8 +73,7 @@ static struct usb_serial_driver belkin_device = {
.name = "belkin",
},
.description = "Belkin / Peracom / GoHubs USB Serial Adapter",
- .usb_driver = &belkin_driver,
- .id_table = id_table_combined,
+ .id_table = id_table,
.num_ports = 1,
.open = belkin_sa_open,
.close = belkin_sa_close,
@@ -142,8 +83,12 @@ static struct usb_serial_driver belkin_device = {
.break_ctl = belkin_sa_break_ctl,
.tiocmget = belkin_sa_tiocmget,
.tiocmset = belkin_sa_tiocmset,
- .attach = belkin_sa_startup,
- .release = belkin_sa_release,
+ .port_probe = belkin_sa_port_probe,
+ .port_remove = belkin_sa_port_remove,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+ &belkin_device, NULL
};
struct belkin_sa_private {
@@ -168,17 +113,15 @@ struct belkin_sa_private {
(c), BELKIN_SA_SET_REQUEST_TYPE, \
(v), 0, NULL, 0, WDR_TIMEOUT)
-/* do some startup allocations not currently performed by usb_serial_probe() */
-static int belkin_sa_startup(struct usb_serial *serial)
+static int belkin_sa_port_probe(struct usb_serial_port *port)
{
- struct usb_device *dev = serial->dev;
+ struct usb_device *dev = port->serial->dev;
struct belkin_sa_private *priv;
- /* allocate the private data structure */
priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL);
if (!priv)
- return -1; /* error */
- /* set initial values for control structures */
+ return -ENOMEM;
+
spin_lock_init(&priv->lock);
priv->control_state = 0;
priv->last_lsr = 0;
@@ -190,20 +133,19 @@ static int belkin_sa_startup(struct usb_serial *serial)
le16_to_cpu(dev->descriptor.bcdDevice),
priv->bad_flow_control);
- init_waitqueue_head(&serial->port[0]->write_wait);
- usb_set_serial_port_data(serial->port[0], priv);
+ usb_set_serial_port_data(port, priv);
return 0;
}
-static void belkin_sa_release(struct usb_serial *serial)
+static int belkin_sa_port_remove(struct usb_serial_port *port)
{
- int i;
+ struct belkin_sa_private *priv;
- dbg("%s", __func__);
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
- for (i = 0; i < serial->num_ports; ++i)
- kfree(usb_get_serial_port_data(serial->port[i]));
+ return 0;
}
static int belkin_sa_open(struct tty_struct *tty,
@@ -211,8 +153,6 @@ static int belkin_sa_open(struct tty_struct *tty,
{
int retval;
- dbg("%s port %d", __func__, port->number);
-
retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (retval) {
dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
@@ -228,8 +168,6 @@ static int belkin_sa_open(struct tty_struct *tty,
static void belkin_sa_close(struct usb_serial_port *port)
{
- dbg("%s port %d", __func__, port->number);
-
usb_serial_generic_close(port);
usb_kill_urb(port->interrupt_in_urb);
}
@@ -251,17 +189,16 @@ static void belkin_sa_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
goto exit;
}
- usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, data);
+ usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
/* Handle known interrupt data */
/* ignore data[0] and data[1] */
@@ -304,7 +241,6 @@ static void belkin_sa_process_read_urb(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
unsigned long flags;
unsigned char status;
@@ -321,10 +257,6 @@ static void belkin_sa_process_read_urb(struct urb *urb)
if (!urb->actual_length)
return;
- tty = tty_port_tty_get(&port->port);
- if (!tty)
- return;
-
if (status & BELKIN_SA_LSR_ERR) {
/* Break takes precedence over parity, which takes precedence
* over framing errors. */
@@ -338,13 +270,12 @@ static void belkin_sa_process_read_urb(struct urb *urb)
/* Overrun is special, not associated with a char. */
if (status & BELKIN_SA_LSR_OE)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
}
- tty_insert_flip_string_fixed_flag(tty, data, tty_flag,
+ tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag,
urb->actual_length);
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
+ tty_flip_buffer_push(&port->port);
}
static void belkin_sa_set_termios(struct tty_struct *tty,
@@ -361,7 +292,7 @@ static void belkin_sa_set_termios(struct tty_struct *tty,
unsigned long control_state;
int bad_flow_control;
speed_t baud;
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
iflag = termios->c_iflag;
cflag = termios->c_cflag;
@@ -444,7 +375,9 @@ static void belkin_sa_set_termios(struct tty_struct *tty,
case CS8:
urb_value = BELKIN_SA_DATA_BITS(8);
break;
- default: dbg("CSIZE was not CS5-CS8, using default of 8");
+ default:
+ dev_dbg(&port->dev,
+ "CSIZE was not CS5-CS8, using default of 8\n");
urb_value = BELKIN_SA_DATA_BITS(8);
break;
}
@@ -497,15 +430,13 @@ static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state)
dev_err(&port->dev, "Set break_ctl %d\n", break_state);
}
-static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file)
+static int belkin_sa_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
unsigned long control_state;
unsigned long flags;
- dbg("%s", __func__);
-
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -513,7 +444,7 @@ static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file)
return control_state;
}
-static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
+static int belkin_sa_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
@@ -525,8 +456,6 @@ static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
int rts = 0;
int dtr = 0;
- dbg("%s", __func__);
-
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
@@ -565,39 +494,8 @@ exit:
return retval;
}
-
-static int __init belkin_sa_init(void)
-{
- int retval;
- retval = usb_serial_register(&belkin_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&belkin_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&belkin_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit belkin_sa_exit (void)
-{
- usb_deregister(&belkin_driver);
- usb_serial_deregister(&belkin_device);
-}
-
-
-module_init(belkin_sa_init);
-module_exit(belkin_sa_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 7f547dc3a59..9374bd2aba2 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -38,15 +38,14 @@ static int usb_serial_device_match(struct device *dev,
return 0;
}
-static ssize_t show_port_number(struct device *dev,
+static ssize_t port_number_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
- return sprintf(buf, "%d\n", port->number - port->serial->minor);
+ return sprintf(buf, "%d\n", port->port_number);
}
-
-static DEVICE_ATTR(port_number, S_IRUGO, show_port_number, NULL);
+static DEVICE_ATTR_RO(port_number);
static int usb_serial_device_probe(struct device *dev)
{
@@ -60,29 +59,34 @@ static int usb_serial_device_probe(struct device *dev)
retval = -ENODEV;
goto exit;
}
- if (port->dev_state != PORT_REGISTERING)
+
+ /* make sure suspend/resume doesn't race against port_probe */
+ retval = usb_autopm_get_interface(port->serial->interface);
+ if (retval)
goto exit;
driver = port->serial->type;
if (driver->port_probe) {
retval = driver->port_probe(port);
if (retval)
- goto exit;
+ goto exit_with_autopm;
}
retval = device_create_file(dev, &dev_attr_port_number);
if (retval) {
if (driver->port_remove)
retval = driver->port_remove(port);
- goto exit;
+ goto exit_with_autopm;
}
- minor = port->number;
+ minor = port->minor;
tty_register_device(usb_serial_tty_driver, minor, dev);
dev_info(&port->serial->dev->dev,
"%s converter now attached to ttyUSB%d\n",
driver->description, minor);
+exit_with_autopm:
+ usb_autopm_put_interface(port->serial->interface);
exit:
return retval;
}
@@ -93,13 +97,22 @@ static int usb_serial_device_remove(struct device *dev)
struct usb_serial_port *port;
int retval = 0;
int minor;
+ int autopm_err;
port = to_usb_serial_port(dev);
if (!port)
return -ENODEV;
- if (port->dev_state != PORT_UNREGISTERING)
- return retval;
+ /*
+ * Make sure suspend/resume doesn't race against port_remove.
+ *
+ * Note that no further runtime PM callbacks will be made if
+ * autopm_get fails.
+ */
+ autopm_err = usb_autopm_get_interface(port->serial->interface);
+
+ minor = port->minor;
+ tty_unregister_device(usb_serial_tty_driver, minor);
device_remove_file(&port->dev, &dev_attr_port_number);
@@ -107,32 +120,43 @@ static int usb_serial_device_remove(struct device *dev)
if (driver->port_remove)
retval = driver->port_remove(port);
- minor = port->number;
- tty_unregister_device(usb_serial_tty_driver, minor);
dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
driver->description, minor);
+ if (!autopm_err)
+ usb_autopm_put_interface(port->serial->interface);
+
return retval;
}
-#ifdef CONFIG_HOTPLUG
-static ssize_t store_new_id(struct device_driver *driver,
+static ssize_t new_id_store(struct device_driver *driver,
const char *buf, size_t count)
{
struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver);
- ssize_t retval = usb_store_new_id(&usb_drv->dynids, driver, buf, count);
+ ssize_t retval = usb_store_new_id(&usb_drv->dynids, usb_drv->id_table,
+ driver, buf, count);
if (retval >= 0 && usb_drv->usb_driver != NULL)
retval = usb_store_new_id(&usb_drv->usb_driver->dynids,
+ usb_drv->usb_driver->id_table,
&usb_drv->usb_driver->drvwrap.driver,
buf, count);
return retval;
}
-static struct driver_attribute drv_attrs[] = {
- __ATTR(new_id, S_IWUSR, NULL, store_new_id),
- __ATTR_NULL,
+static ssize_t new_id_show(struct device_driver *driver, char *buf)
+{
+ struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver);
+
+ return usb_show_dynids(&usb_drv->dynids, buf);
+}
+static DRIVER_ATTR_RW(new_id);
+
+static struct attribute *usb_serial_drv_attrs[] = {
+ &driver_attr_new_id.attr,
+ NULL,
};
+ATTRIBUTE_GROUPS(usb_serial_drv);
static void free_dynids(struct usb_serial_driver *drv)
{
@@ -146,21 +170,12 @@ static void free_dynids(struct usb_serial_driver *drv)
spin_unlock(&drv->dynids.lock);
}
-#else
-static struct driver_attribute drv_attrs[] = {
- __ATTR_NULL,
-};
-static inline void free_dynids(struct usb_serial_driver *drv)
-{
-}
-#endif
-
struct bus_type usb_serial_bus_type = {
.name = "usb-serial",
.match = usb_serial_device_match,
.probe = usb_serial_device_probe,
.remove = usb_serial_device_remove,
- .drv_attrs = drv_attrs,
+ .drv_groups = usb_serial_drv_groups,
};
int usb_serial_bus_register(struct usb_serial_driver *driver)
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 63f7cc45bca..2d72aa3564a 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -16,7 +16,6 @@
*/
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -70,30 +69,28 @@
#define CH341_NBREAK_BITS_REG2 0x40
-static int debug;
-
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x4348, 0x5523) },
{ USB_DEVICE(0x1a86, 0x7523) },
+ { USB_DEVICE(0x1a86, 0x5523) },
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
struct ch341_private {
spinlock_t lock; /* access lock */
- wait_queue_head_t delta_msr_wait; /* wait queue for modem status */
unsigned baud_rate; /* set baud rate */
u8 line_control; /* set line control value RTS/DTR */
u8 line_status; /* active status of modem control inputs */
- u8 multi_status_change; /* status changed multiple since last call */
};
static int ch341_control_out(struct usb_device *dev, u8 request,
u16 value, u16 index)
{
int r;
- dbg("ch341_control_out(%02x,%02x,%04x,%04x)", USB_DIR_OUT|0x40,
- (int)request, (int)value, (int)index);
+
+ dev_dbg(&dev->dev, "ch341_control_out(%02x,%02x,%04x,%04x)\n",
+ USB_DIR_OUT|0x40, (int)request, (int)value, (int)index);
r = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
@@ -107,8 +104,10 @@ static int ch341_control_in(struct usb_device *dev,
char *buf, unsigned bufsize)
{
int r;
- dbg("ch341_control_in(%02x,%02x,%04x,%04x,%p,%u)", USB_DIR_IN|0x40,
- (int)request, (int)value, (int)index, buf, (int)bufsize);
+
+ dev_dbg(&dev->dev, "ch341_control_in(%02x,%02x,%04x,%04x,%p,%u)\n",
+ USB_DIR_IN|0x40, (int)request, (int)value, (int)index, buf,
+ (int)bufsize);
r = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
@@ -124,8 +123,6 @@ static int ch341_set_baudrate(struct usb_device *dev,
unsigned long factor;
short divisor;
- dbg("ch341_set_baudrate(%d)", priv->baud_rate);
-
if (!priv->baud_rate)
return -EINVAL;
factor = (CH341_BAUDBASE_FACTOR / priv->baud_rate);
@@ -152,7 +149,6 @@ static int ch341_set_baudrate(struct usb_device *dev,
static int ch341_set_handshake(struct usb_device *dev, u8 control)
{
- dbg("ch341_set_handshake(0x%02x)", control);
return ch341_control_out(dev, 0xa4, ~control, 0);
}
@@ -163,8 +159,6 @@ static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
const unsigned size = 8;
unsigned long flags;
- dbg("ch341_get_status()");
-
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
@@ -178,7 +172,6 @@ static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
r = 0;
spin_lock_irqsave(&priv->lock, flags);
priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT;
- priv->multi_status_change = 0;
spin_unlock_irqrestore(&priv->lock, flags);
} else
r = -EPROTO;
@@ -195,8 +188,6 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
int r;
const unsigned size = 8;
- dbg("ch341_configure()");
-
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
@@ -247,35 +238,40 @@ out: kfree(buffer);
return r;
}
-/* allocate private data */
-static int ch341_attach(struct usb_serial *serial)
+static int ch341_port_probe(struct usb_serial_port *port)
{
struct ch341_private *priv;
int r;
- dbg("ch341_attach()");
-
- /* private data */
priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
priv->baud_rate = DEFAULT_BAUD_RATE;
priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
- r = ch341_configure(serial->dev, priv);
+ r = ch341_configure(port->serial->dev, priv);
if (r < 0)
goto error;
- usb_set_serial_port_data(serial->port[0], priv);
+ usb_set_serial_port_data(port, priv);
return 0;
error: kfree(priv);
return r;
}
+static int ch341_port_remove(struct usb_serial_port *port)
+{
+ struct ch341_private *priv;
+
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
+}
+
static int ch341_carrier_raised(struct usb_serial_port *port)
{
struct ch341_private *priv = usb_get_serial_port_data(port);
@@ -289,7 +285,6 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on)
struct ch341_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
/* drop DTR and RTS */
spin_lock_irqsave(&priv->lock, flags);
if (on)
@@ -298,13 +293,10 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on)
priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
spin_unlock_irqrestore(&priv->lock, flags);
ch341_set_handshake(port->serial->dev, priv->line_control);
- wake_up_interruptible(&priv->delta_msr_wait);
}
static void ch341_close(struct usb_serial_port *port)
{
- dbg("%s - port %d", __func__, port->number);
-
usb_serial_generic_close(port);
usb_kill_urb(port->interrupt_in_urb);
}
@@ -314,11 +306,9 @@ static void ch341_close(struct usb_serial_port *port)
static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
- struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
+ struct ch341_private *priv = usb_get_serial_port_data(port);
int r;
- dbg("ch341_open()");
-
priv->baud_rate = DEFAULT_BAUD_RATE;
r = ch341_configure(serial->dev, priv);
@@ -333,14 +323,13 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
if (r)
goto out;
- dbg("%s - submitting interrupt urb", __func__);
- port->interrupt_in_urb->dev = serial->dev;
+ dev_dbg(&port->dev, "%s - submitting interrupt urb\n", __func__);
r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (r) {
- dev_err(&port->dev, "%s - failed submitting interrupt urb,"
- " error %d\n", __func__, r);
+ dev_err(&port->dev, "%s - failed to submit interrupt urb: %d\n",
+ __func__, r);
ch341_close(port);
- return -EPROTO;
+ goto out;
}
r = usb_serial_generic_open(tty, port);
@@ -358,8 +347,6 @@ static void ch341_set_termios(struct tty_struct *tty,
unsigned baud_rate;
unsigned long flags;
- dbg("ch341_set_termios()");
-
baud_rate = tty_get_baud_rate(tty);
priv->baud_rate = baud_rate;
@@ -393,13 +380,9 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state)
uint16_t reg_contents;
uint8_t *break_reg;
- dbg("%s()", __func__);
-
break_reg = kmalloc(2, GFP_KERNEL);
- if (!break_reg) {
- dev_err(&port->dev, "%s - kmalloc failed\n", __func__);
+ if (!break_reg)
return;
- }
r = ch341_control_in(port->serial->dev, CH341_REQ_READ_REG,
ch341_break_reg, 0, break_reg, 2);
@@ -408,19 +391,19 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state)
__func__, r);
goto out;
}
- dbg("%s - initial ch341 break register contents - reg1: %x, reg2: %x",
- __func__, break_reg[0], break_reg[1]);
+ dev_dbg(&port->dev, "%s - initial ch341 break register contents - reg1: %x, reg2: %x\n",
+ __func__, break_reg[0], break_reg[1]);
if (break_state != 0) {
- dbg("%s - Enter break state requested", __func__);
+ dev_dbg(&port->dev, "%s - Enter break state requested\n", __func__);
break_reg[0] &= ~CH341_NBREAK_BITS_REG1;
break_reg[1] &= ~CH341_NBREAK_BITS_REG2;
} else {
- dbg("%s - Leave break state requested", __func__);
+ dev_dbg(&port->dev, "%s - Leave break state requested\n", __func__);
break_reg[0] |= CH341_NBREAK_BITS_REG1;
break_reg[1] |= CH341_NBREAK_BITS_REG2;
}
- dbg("%s - New ch341 break register contents - reg1: %x, reg2: %x",
- __func__, break_reg[0], break_reg[1]);
+ dev_dbg(&port->dev, "%s - New ch341 break register contents - reg1: %x, reg2: %x\n",
+ __func__, break_reg[0], break_reg[1]);
reg_contents = get_unaligned_le16(break_reg);
r = ch341_control_out(port->serial->dev, CH341_REQ_WRITE_REG,
ch341_break_reg, reg_contents);
@@ -431,7 +414,7 @@ out:
kfree(break_reg);
}
-static int ch341_tiocmset(struct tty_struct *tty, struct file *file,
+static int ch341_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
@@ -454,15 +437,57 @@ static int ch341_tiocmset(struct tty_struct *tty, struct file *file,
return ch341_set_handshake(port->serial->dev, control);
}
+static void ch341_update_line_status(struct usb_serial_port *port,
+ unsigned char *data, size_t len)
+{
+ struct ch341_private *priv = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
+ unsigned long flags;
+ u8 status;
+ u8 delta;
+
+ if (len < 4)
+ return;
+
+ status = ~data[2] & CH341_BITS_MODEM_STAT;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ delta = status ^ priv->line_status;
+ priv->line_status = status;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (data[1] & CH341_MULT_STAT)
+ dev_dbg(&port->dev, "%s - multiple status change\n", __func__);
+
+ if (!delta)
+ return;
+
+ if (delta & CH341_BIT_CTS)
+ port->icount.cts++;
+ if (delta & CH341_BIT_DSR)
+ port->icount.dsr++;
+ if (delta & CH341_BIT_RI)
+ port->icount.rng++;
+ if (delta & CH341_BIT_DCD) {
+ port->icount.dcd++;
+ tty = tty_port_tty_get(&port->port);
+ if (tty) {
+ usb_serial_handle_dcd_change(port, tty,
+ status & CH341_BIT_DCD);
+ tty_kref_put(tty);
+ }
+ }
+
+ wake_up_interruptible(&port->port.delta_msr_wait);
+}
+
static void ch341_read_int_callback(struct urb *urb)
{
- struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+ struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
- unsigned int actual_length = urb->actual_length;
+ unsigned int len = urb->actual_length;
int status;
- dbg("%s (%d)", __func__, port->number);
-
switch (urb->status) {
case 0:
/* success */
@@ -471,98 +496,26 @@ static void ch341_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__,
- urb->status);
+ dev_dbg(&urb->dev->dev, "%s - urb shutting down: %d\n",
+ __func__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __func__,
- urb->status);
+ dev_dbg(&urb->dev->dev, "%s - nonzero urb status: %d\n",
+ __func__, urb->status);
goto exit;
}
- usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, urb->transfer_buffer);
-
- if (actual_length >= 4) {
- struct ch341_private *priv = usb_get_serial_port_data(port);
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
- priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT;
- if ((data[1] & CH341_MULT_STAT))
- priv->multi_status_change = 1;
- spin_unlock_irqrestore(&priv->lock, flags);
- wake_up_interruptible(&priv->delta_msr_wait);
- }
-
+ usb_serial_debug_data(&port->dev, __func__, len, data);
+ ch341_update_line_status(port, data, len);
exit:
status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status)
- dev_err(&urb->dev->dev,
- "%s - usb_submit_urb failed with result %d\n",
+ if (status) {
+ dev_err(&urb->dev->dev, "%s - usb_submit_urb failed: %d\n",
__func__, status);
-}
-
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
-{
- struct ch341_private *priv = usb_get_serial_port_data(port);
- unsigned long flags;
- u8 prevstatus;
- u8 status;
- u8 changed;
- u8 multi_change = 0;
-
- spin_lock_irqsave(&priv->lock, flags);
- prevstatus = priv->line_status;
- priv->multi_status_change = 0;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- while (!multi_change) {
- interruptible_sleep_on(&priv->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- spin_lock_irqsave(&priv->lock, flags);
- status = priv->line_status;
- multi_change = priv->multi_status_change;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- changed = prevstatus ^ status;
-
- if (((arg & TIOCM_RNG) && (changed & CH341_BIT_RI)) ||
- ((arg & TIOCM_DSR) && (changed & CH341_BIT_DSR)) ||
- ((arg & TIOCM_CD) && (changed & CH341_BIT_DCD)) ||
- ((arg & TIOCM_CTS) && (changed & CH341_BIT_CTS))) {
- return 0;
- }
- prevstatus = status;
- }
-
- return 0;
-}
-
-/*static int ch341_ioctl(struct usb_serial_port *port, struct file *file,*/
-static int ch341_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct usb_serial_port *port = tty->driver_data;
- dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
-
- switch (cmd) {
- case TIOCMIWAIT:
- dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
- return wait_modem_info(port, arg);
-
- default:
- dbg("%s not supported = 0x%04x", __func__, cmd);
- break;
}
-
- return -ENOIOCTLCMD;
}
-static int ch341_tiocmget(struct tty_struct *tty, struct file *file)
+static int ch341_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct ch341_private *priv = usb_get_serial_port_data(port);
@@ -571,8 +524,6 @@ static int ch341_tiocmget(struct tty_struct *tty, struct file *file)
u8 status;
unsigned int result;
- dbg("%s (%d)", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
mcr = priv->line_control;
status = priv->line_status;
@@ -585,86 +536,49 @@ static int ch341_tiocmget(struct tty_struct *tty, struct file *file)
| ((status & CH341_BIT_RI) ? TIOCM_RI : 0)
| ((status & CH341_BIT_DCD) ? TIOCM_CD : 0);
- dbg("%s - result = %x", __func__, result);
+ dev_dbg(&port->dev, "%s - result = %x\n", __func__, result);
return result;
}
-
-static int ch341_reset_resume(struct usb_interface *intf)
+static int ch341_reset_resume(struct usb_serial *serial)
{
- struct usb_device *dev = interface_to_usbdev(intf);
- struct usb_serial *serial = NULL;
struct ch341_private *priv;
- serial = usb_get_intfdata(intf);
priv = usb_get_serial_port_data(serial->port[0]);
- /*reconfigure ch341 serial port after bus-reset*/
- ch341_configure(dev, priv);
-
- usb_serial_resume(intf);
+ /* reconfigure ch341 serial port after bus-reset */
+ ch341_configure(serial->dev, priv);
return 0;
}
-static struct usb_driver ch341_driver = {
- .name = "ch341",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .reset_resume = ch341_reset_resume,
- .id_table = id_table,
- .no_dynamic_id = 1,
- .supports_autosuspend = 1,
-};
-
static struct usb_serial_driver ch341_device = {
.driver = {
.owner = THIS_MODULE,
.name = "ch341-uart",
},
.id_table = id_table,
- .usb_driver = &ch341_driver,
.num_ports = 1,
.open = ch341_open,
.dtr_rts = ch341_dtr_rts,
.carrier_raised = ch341_carrier_raised,
.close = ch341_close,
- .ioctl = ch341_ioctl,
.set_termios = ch341_set_termios,
.break_ctl = ch341_break_ctl,
.tiocmget = ch341_tiocmget,
.tiocmset = ch341_tiocmset,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
.read_int_callback = ch341_read_int_callback,
- .attach = ch341_attach,
+ .port_probe = ch341_port_probe,
+ .port_remove = ch341_port_remove,
+ .reset_resume = ch341_reset_resume,
};
-static int __init ch341_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&ch341_device);
- if (retval)
- return retval;
- retval = usb_register(&ch341_driver);
- if (retval)
- usb_serial_deregister(&ch341_device);
- return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ch341_device, NULL
+};
-static void __exit ch341_exit(void)
-{
- usb_deregister(&ch341_driver);
- usb_serial_deregister(&ch341_device);
-}
+module_usb_serial_driver(serial_drivers, id_table);
-module_init(ch341_init);
-module_exit(ch341_exit);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
-/* EOF ch341.c */
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 1ee6b2ab0f8..8d7fc48b1f3 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -11,8 +11,9 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/console.h>
@@ -20,8 +21,6 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-static int debug;
-
struct usbcons_info {
int magic;
int break_flag;
@@ -68,8 +67,6 @@ static int usb_console_setup(struct console *co, char *options)
struct tty_struct *tty = NULL;
struct ktermios dummy;
- dbg("%s", __func__);
-
if (options) {
baud = simple_strtoul(options, NULL, 10);
s = options;
@@ -110,18 +107,18 @@ static int usb_console_setup(struct console *co, char *options)
* no need to check the index here: if the index is wrong, console
* code won't call us
*/
- serial = usb_serial_get_by_index(co->index);
- if (serial == NULL) {
+ port = usb_serial_port_get_by_minor(co->index);
+ if (port == NULL) {
/* no device is connected yet, sorry :( */
- err("No USB device connected to ttyUSB%i", co->index);
+ pr_err("No USB device connected to ttyUSB%i\n", co->index);
return -ENODEV;
}
+ serial = port->serial;
retval = usb_autopm_get_interface(serial->interface);
if (retval)
goto error_get_interface;
- port = serial->port[co->index - serial->minor];
tty_port_tty_set(&port->port, NULL);
info->port = port;
@@ -137,7 +134,6 @@ static int usb_console_setup(struct console *co, char *options)
tty = kzalloc(sizeof(*tty), GFP_KERNEL);
if (!tty) {
retval = -ENOMEM;
- err("no more memory");
goto reset_open_count;
}
kref_init(&tty->kref);
@@ -146,26 +142,21 @@ static int usb_console_setup(struct console *co, char *options)
tty->index = co->index;
if (tty_init_termios(tty)) {
retval = -ENOMEM;
- err("no more memory");
goto free_tty;
}
}
/* only call the device specific open if this
* is the first time the port is opened */
- if (serial->type->open)
- retval = serial->type->open(NULL, port);
- else
- retval = usb_serial_generic_open(NULL, port);
-
+ retval = serial->type->open(NULL, port);
if (retval) {
- err("could not open USB console port");
+ dev_err(&port->dev, "could not open USB console port\n");
goto fail;
}
if (serial->type->set_termios) {
- tty->termios->c_cflag = cflag;
- tty_termios_encode_baud_rate(tty->termios, baud, baud);
+ tty->termios.c_cflag = cflag;
+ tty_termios_encode_baud_rate(&tty->termios, baud, baud);
memset(&dummy, 0, sizeof(struct ktermios));
serial->type->set_termios(tty, port, &dummy);
@@ -212,10 +203,10 @@ static void usb_console_write(struct console *co,
if (count == 0)
return;
- dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
+ dev_dbg(&port->dev, "%s - %d byte(s)\n", __func__, count);
if (!port->port.console) {
- dbg("%s - port not opened", __func__);
+ dev_dbg(&port->dev, "%s - port not opened\n", __func__);
return;
}
@@ -232,21 +223,14 @@ static void usb_console_write(struct console *co,
}
/* pass on to the driver specific version of this function if
it is available */
- if (serial->type->write)
- retval = serial->type->write(NULL, port, buf, i);
- else
- retval = usb_serial_generic_write(NULL, port, buf, i);
- dbg("%s - return value : %d", __func__, retval);
+ retval = serial->type->write(NULL, port, buf, i);
+ dev_dbg(&port->dev, "%s - write: %d\n", __func__, retval);
if (lf) {
/* append CR after LF */
unsigned char cr = 13;
- if (serial->type->write)
- retval = serial->type->write(NULL,
- port, &cr, 1);
- else
- retval = usb_serial_generic_write(NULL,
- port, &cr, 1);
- dbg("%s - return value : %d", __func__, retval);
+ retval = serial->type->write(NULL, port, &cr, 1);
+ dev_dbg(&port->dev, "%s - write cr: %d\n",
+ __func__, retval);
}
buf += i;
count -= i;
@@ -283,10 +267,8 @@ void usb_serial_console_disconnect(struct usb_serial *serial)
}
}
-void usb_serial_console_init(int serial_debug, int minor)
+void usb_serial_console_init(int minor)
{
- debug = serial_debug;
-
if (minor == 0) {
/*
* Call register_console() if this is the first device plugged
@@ -301,7 +283,7 @@ void usb_serial_console_init(int serial_debug, int minor)
* register_console). console_write() is called immediately
* from register_console iff CON_PRINTBUFFER is set in flags.
*/
- dbg("registering the USB serial console.");
+ pr_debug("registering the USB serial console.\n");
register_console(&usbcons);
}
}
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 8d7731dbf47..330df5ce435 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -24,10 +24,6 @@
#include <linux/uaccess.h>
#include <linux/usb/serial.h>
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.09"
#define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver"
/*
@@ -35,23 +31,21 @@
*/
static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *);
static void cp210x_close(struct usb_serial_port *);
-static void cp210x_get_termios(struct tty_struct *,
- struct usb_serial_port *port);
+static void cp210x_get_termios(struct tty_struct *, struct usb_serial_port *);
static void cp210x_get_termios_port(struct usb_serial_port *port,
unsigned int *cflagp, unsigned int *baudp);
+static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *,
+ struct ktermios *);
static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *,
struct ktermios*);
-static int cp210x_tiocmget(struct tty_struct *, struct file *);
-static int cp210x_tiocmset(struct tty_struct *, struct file *,
- unsigned int, unsigned int);
-static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *,
+static int cp210x_tiocmget(struct tty_struct *);
+static int cp210x_tiocmset(struct tty_struct *, unsigned int, unsigned int);
+static int cp210x_tiocmset_port(struct usb_serial_port *port,
unsigned int, unsigned int);
static void cp210x_break_ctl(struct tty_struct *, int);
static int cp210x_startup(struct usb_serial *);
+static void cp210x_release(struct usb_serial *);
static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
-static int cp210x_carrier_raised(struct usb_serial_port *p);
-
-static int debug;
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */
@@ -59,6 +53,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
{ USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
{ USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */
+ { USB_DEVICE(0x0846, 0x1100) }, /* NetGear Managed Switch M4100 series, M5300 series, M7100 series */
{ USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
{ USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */
{ USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */
@@ -66,6 +61,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
{ USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */
{ USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */
+ { USB_DEVICE(0x0FDE, 0xCA05) }, /* OWL Wireless Electricity Monitor CM-160 */
{ USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
@@ -81,20 +77,23 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
{ USB_DEVICE(0x10C4, 0x806F) }, /* IMS USB to RS422 Converter Cable */
{ USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */
+ { USB_DEVICE(0x10C4, 0x80C4) }, /* Cygnal Integrated Products, Inc., Optris infrared thermometer */
{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
{ USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */
{ USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
{ USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */
{ USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
{ USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */
- { USB_DEVICE(0x10C4, 0x8149) }, /* West Mountain Radio Computerized Battery Analyzer */
{ USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
+ { USB_DEVICE(0x2405, 0x0003) }, /* West Mountain Radio RIGblaster Advantage */
{ USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */
{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
+ { USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */
{ USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */
{ USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */
{ USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */
+ { USB_DEVICE(0x10C4, 0x81A9) }, /* Multiplex RC Interface */
{ USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
{ USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */
{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
@@ -104,17 +103,29 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x81F2) }, /* C1007 HF band RFID controller */
{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
{ USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */
- { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demostration module */
- { USB_DEVICE(0x10C4, 0x8293) }, /* Telegesys ETRX2USB */
+ { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */
+ { USB_DEVICE(0x10C4, 0x8281) }, /* Nanotec Plug & Drive */
+ { USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */
{ USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */
{ USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
{ USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */
{ USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */
+ { USB_DEVICE(0x10C4, 0x83D8) }, /* DekTec DTA Plus VHF/UHF Booster/Attenuator */
{ USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */
+ { USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */
{ USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
{ USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
+ { USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */
+ { USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */
+ { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */
+ { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
+ { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
+ { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */
+ { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
{ USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
@@ -124,36 +135,65 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10CE, 0xEA6A) }, /* Silicon Labs MobiData GPRS USB Modem 100EU */
{ USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
{ USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */
+ { USB_DEVICE(0x166A, 0x0201) }, /* Clipsal 5500PACA C-Bus Pascal Automation Controller */
+ { USB_DEVICE(0x166A, 0x0301) }, /* Clipsal 5800PC C-Bus Wireless PC Interface */
{ USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
+ { USB_DEVICE(0x166A, 0x0304) }, /* Clipsal 5000CT2 C-Bus Black and White Touchscreen */
+ { USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */
+ { USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */
+ { USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
{ USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */
{ USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
{ USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */
{ USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */
+ { USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */
+ { USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */
{ USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
+ { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
+ { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
+ { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */
+ { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */
+ { USB_DEVICE(0x1FB9, 0x0100) }, /* Lake Shore Model 121 Current Source */
+ { USB_DEVICE(0x1FB9, 0x0200) }, /* Lake Shore Model 218A Temperature Monitor */
+ { USB_DEVICE(0x1FB9, 0x0201) }, /* Lake Shore Model 219 Temperature Monitor */
+ { USB_DEVICE(0x1FB9, 0x0202) }, /* Lake Shore Model 233 Temperature Transmitter */
+ { USB_DEVICE(0x1FB9, 0x0203) }, /* Lake Shore Model 235 Temperature Transmitter */
+ { USB_DEVICE(0x1FB9, 0x0300) }, /* Lake Shore Model 335 Temperature Controller */
+ { USB_DEVICE(0x1FB9, 0x0301) }, /* Lake Shore Model 336 Temperature Controller */
+ { USB_DEVICE(0x1FB9, 0x0302) }, /* Lake Shore Model 350 Temperature Controller */
+ { USB_DEVICE(0x1FB9, 0x0303) }, /* Lake Shore Model 371 AC Bridge */
+ { USB_DEVICE(0x1FB9, 0x0400) }, /* Lake Shore Model 411 Handheld Gaussmeter */
+ { USB_DEVICE(0x1FB9, 0x0401) }, /* Lake Shore Model 425 Gaussmeter */
+ { USB_DEVICE(0x1FB9, 0x0402) }, /* Lake Shore Model 455A Gaussmeter */
+ { USB_DEVICE(0x1FB9, 0x0403) }, /* Lake Shore Model 475A Gaussmeter */
+ { USB_DEVICE(0x1FB9, 0x0404) }, /* Lake Shore Model 465 Three Axis Gaussmeter */
+ { USB_DEVICE(0x1FB9, 0x0600) }, /* Lake Shore Model 625A Superconducting MPS */
+ { USB_DEVICE(0x1FB9, 0x0601) }, /* Lake Shore Model 642A Magnet Power Supply */
+ { USB_DEVICE(0x1FB9, 0x0602) }, /* Lake Shore Model 648 Magnet Power Supply */
+ { USB_DEVICE(0x1FB9, 0x0700) }, /* Lake Shore Model 737 VSM Controller */
+ { USB_DEVICE(0x1FB9, 0x0701) }, /* Lake Shore Model 776 Hall Matrix */
+ { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
+ { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */
+ { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */
{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver cp210x_driver = {
- .name = "cp210x",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
+struct cp210x_serial_private {
+ __u8 bInterfaceNumber;
};
static struct usb_serial_driver cp210x_device = {
.driver = {
.owner = THIS_MODULE,
- .name = "cp210x",
+ .name = "cp210x",
},
- .usb_driver = &cp210x_driver,
.id_table = id_table,
.num_ports = 1,
.bulk_in_size = 256,
@@ -162,16 +202,22 @@ static struct usb_serial_driver cp210x_device = {
.close = cp210x_close,
.break_ctl = cp210x_break_ctl,
.set_termios = cp210x_set_termios,
- .tiocmget = cp210x_tiocmget,
+ .tiocmget = cp210x_tiocmget,
.tiocmset = cp210x_tiocmset,
.attach = cp210x_startup,
- .dtr_rts = cp210x_dtr_rts,
- .carrier_raised = cp210x_carrier_raised
+ .release = cp210x_release,
+ .dtr_rts = cp210x_dtr_rts
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+ &cp210x_device, NULL
};
/* Config request types */
-#define REQTYPE_HOST_TO_DEVICE 0x41
-#define REQTYPE_DEVICE_TO_HOST 0xc1
+#define REQTYPE_HOST_TO_INTERFACE 0x41
+#define REQTYPE_INTERFACE_TO_HOST 0xc1
+#define REQTYPE_HOST_TO_DEVICE 0x40
+#define REQTYPE_DEVICE_TO_HOST 0xc0
/* Config request codes */
#define CP210X_IFC_ENABLE 0x00
@@ -198,6 +244,8 @@ static struct usb_serial_driver cp210x_device = {
#define CP210X_EMBED_EVENTS 0x15
#define CP210X_GET_EVENTSTATE 0x16
#define CP210X_SET_CHARS 0x19
+#define CP210X_GET_BAUDRATE 0x1D
+#define CP210X_SET_BAUDRATE 0x1E
/* CP210X_IFC_ENABLE */
#define UART_ENABLE 0x0001
@@ -251,22 +299,22 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
+ struct cp210x_serial_private *spriv = usb_get_serial_data(serial);
__le32 *buf;
int result, i, length;
/* Number of integers required to contain the array */
- length = (((size - 1) | 3) + 1)/4;
+ length = (((size - 1) | 3) + 1) / 4;
buf = kcalloc(length, sizeof(__le32), GFP_KERNEL);
- if (!buf) {
- dev_err(&port->dev, "%s - out of memory.\n", __func__);
+ if (!buf)
return -ENOMEM;
- }
/* Issue the request, attempting to read 'size' bytes */
result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
- request, REQTYPE_DEVICE_TO_HOST, 0x0000,
- 0, buf, size, 300);
+ request, REQTYPE_INTERFACE_TO_HOST, 0x0000,
+ spriv->bInterfaceNumber, buf, size,
+ USB_CTRL_GET_TIMEOUT);
/* Convert data into an array of integers */
for (i = 0; i < length; i++)
@@ -275,10 +323,12 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
kfree(buf);
if (result != size) {
- dbg("%s - Unable to send config request, "
- "request=0x%x size=%d result=%d\n",
- __func__, request, size, result);
- return -EPROTO;
+ dev_dbg(&port->dev, "%s - Unable to send config request, request=0x%x size=%d result=%d\n",
+ __func__, request, size, result);
+ if (result > 0)
+ result = -EPROTO;
+
+ return result;
}
return 0;
@@ -294,18 +344,16 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
+ struct cp210x_serial_private *spriv = usb_get_serial_data(serial);
__le32 *buf;
int result, i, length;
/* Number of integers required to contain the array */
- length = (((size - 1) | 3) + 1)/4;
+ length = (((size - 1) | 3) + 1) / 4;
buf = kmalloc(length * sizeof(__le32), GFP_KERNEL);
- if (!buf) {
- dev_err(&port->dev, "%s - out of memory.\n",
- __func__);
+ if (!buf)
return -ENOMEM;
- }
/* Array of integers into bytes */
for (i = 0; i < length; i++)
@@ -314,22 +362,26 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
if (size > 2) {
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
- request, REQTYPE_HOST_TO_DEVICE, 0x0000,
- 0, buf, size, 300);
+ request, REQTYPE_HOST_TO_INTERFACE, 0x0000,
+ spriv->bInterfaceNumber, buf, size,
+ USB_CTRL_SET_TIMEOUT);
} else {
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
- request, REQTYPE_HOST_TO_DEVICE, data[0],
- 0, NULL, 0, 300);
+ request, REQTYPE_HOST_TO_INTERFACE, data[0],
+ spriv->bInterfaceNumber, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
}
kfree(buf);
if ((size > 2 && result != size) || result < 0) {
- dbg("%s - Unable to send request, "
- "request=0x%x size=%d result=%d\n",
- __func__, request, size, result);
- return -EPROTO;
+ dev_dbg(&port->dev, "%s - Unable to send request, request=0x%x size=%d result=%d\n",
+ __func__, request, size, result);
+ if (result > 0)
+ result = -EPROTO;
+
+ return result;
}
return 0;
@@ -350,9 +402,10 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port,
* cp210x_quantise_baudrate
* Quantises the baud rate as per AN205 Table 1
*/
-static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
- if (baud <= 56) baud = 0;
- else if (baud <= 300) baud = 300;
+static unsigned int cp210x_quantise_baudrate(unsigned int baud)
+{
+ if (baud <= 300)
+ baud = 300;
else if (baud <= 600) baud = 600;
else if (baud <= 1200) baud = 1200;
else if (baud <= 1800) baud = 1800;
@@ -380,10 +433,10 @@ static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
else if (baud <= 491520) baud = 460800;
else if (baud <= 567138) baud = 500000;
else if (baud <= 670254) baud = 576000;
- else if (baud <= 1053257) baud = 921600;
- else if (baud <= 1474560) baud = 1228800;
- else if (baud <= 2457600) baud = 1843200;
- else baud = 3686400;
+ else if (baud < 1000000)
+ baud = 921600;
+ else if (baud > 2000000)
+ baud = 2000000;
return baud;
}
@@ -391,33 +444,27 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
{
int result;
- dbg("%s - port %d", __func__, port->number);
-
- if (cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_ENABLE)) {
- dev_err(&port->dev, "%s - Unable to enable UART\n",
- __func__);
- return -EPROTO;
- }
-
- result = usb_serial_generic_open(tty, port);
- if (result)
+ result = cp210x_set_config_single(port, CP210X_IFC_ENABLE,
+ UART_ENABLE);
+ if (result) {
+ dev_err(&port->dev, "%s - Unable to enable UART\n", __func__);
return result;
+ }
/* Configure the termios structure */
cp210x_get_termios(tty, port);
- return 0;
+
+ /* The baud rate must be initialised on cp2104 */
+ if (tty)
+ cp210x_change_speed(tty, port, NULL);
+
+ return usb_serial_generic_open(tty, port);
}
static void cp210x_close(struct usb_serial_port *port)
{
- dbg("%s - port %d", __func__, port->number);
-
usb_serial_generic_close(port);
-
- mutex_lock(&port->serial->disc_mutex);
- if (!port->serial->disconnected)
- cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE);
- mutex_unlock(&port->serial->disc_mutex);
+ cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE);
}
/*
@@ -433,11 +480,9 @@ static void cp210x_get_termios(struct tty_struct *tty,
if (tty) {
cp210x_get_termios_port(tty->driver_data,
- &tty->termios->c_cflag, &baud);
+ &tty->termios.c_cflag, &baud);
tty_encode_baud_rate(tty, baud, baud);
- }
-
- else {
+ } else {
unsigned int cflag;
cflag = 0;
cp210x_get_termios_port(port, &cflag, &baud);
@@ -451,18 +496,14 @@ static void cp210x_get_termios(struct tty_struct *tty,
static void cp210x_get_termios_port(struct usb_serial_port *port,
unsigned int *cflagp, unsigned int *baudp)
{
+ struct device *dev = &port->dev;
unsigned int cflag, modem_ctl[4];
unsigned int baud;
unsigned int bits;
- dbg("%s - port %d", __func__, port->number);
-
- cp210x_get_config(port, CP210X_GET_BAUDDIV, &baud, 2);
- /* Convert to baudrate */
- if (baud)
- baud = cp210x_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud);
+ cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4);
- dbg("%s - baud rate = %d", __func__, baud);
+ dev_dbg(dev, "%s - baud rate = %d\n", __func__, baud);
*baudp = baud;
cflag = *cflagp;
@@ -471,31 +512,30 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
cflag &= ~CSIZE;
switch (bits & BITS_DATA_MASK) {
case BITS_DATA_5:
- dbg("%s - data bits = 5", __func__);
+ dev_dbg(dev, "%s - data bits = 5\n", __func__);
cflag |= CS5;
break;
case BITS_DATA_6:
- dbg("%s - data bits = 6", __func__);
+ dev_dbg(dev, "%s - data bits = 6\n", __func__);
cflag |= CS6;
break;
case BITS_DATA_7:
- dbg("%s - data bits = 7", __func__);
+ dev_dbg(dev, "%s - data bits = 7\n", __func__);
cflag |= CS7;
break;
case BITS_DATA_8:
- dbg("%s - data bits = 8", __func__);
+ dev_dbg(dev, "%s - data bits = 8\n", __func__);
cflag |= CS8;
break;
case BITS_DATA_9:
- dbg("%s - data bits = 9 (not supported, using 8 data bits)",
- __func__);
+ dev_dbg(dev, "%s - data bits = 9 (not supported, using 8 data bits)\n", __func__);
cflag |= CS8;
bits &= ~BITS_DATA_MASK;
bits |= BITS_DATA_8;
cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2);
break;
default:
- dbg("%s - Unknown number of data bits, using 8", __func__);
+ dev_dbg(dev, "%s - Unknown number of data bits, using 8\n", __func__);
cflag |= CS8;
bits &= ~BITS_DATA_MASK;
bits |= BITS_DATA_8;
@@ -505,34 +545,29 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
switch (bits & BITS_PARITY_MASK) {
case BITS_PARITY_NONE:
- dbg("%s - parity = NONE", __func__);
+ dev_dbg(dev, "%s - parity = NONE\n", __func__);
cflag &= ~PARENB;
break;
case BITS_PARITY_ODD:
- dbg("%s - parity = ODD", __func__);
+ dev_dbg(dev, "%s - parity = ODD\n", __func__);
cflag |= (PARENB|PARODD);
break;
case BITS_PARITY_EVEN:
- dbg("%s - parity = EVEN", __func__);
+ dev_dbg(dev, "%s - parity = EVEN\n", __func__);
cflag &= ~PARODD;
cflag |= PARENB;
break;
case BITS_PARITY_MARK:
- dbg("%s - parity = MARK (not supported, disabling parity)",
- __func__);
- cflag &= ~PARENB;
- bits &= ~BITS_PARITY_MASK;
- cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2);
+ dev_dbg(dev, "%s - parity = MARK\n", __func__);
+ cflag |= (PARENB|PARODD|CMSPAR);
break;
case BITS_PARITY_SPACE:
- dbg("%s - parity = SPACE (not supported, disabling parity)",
- __func__);
- cflag &= ~PARENB;
- bits &= ~BITS_PARITY_MASK;
- cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2);
+ dev_dbg(dev, "%s - parity = SPACE\n", __func__);
+ cflag &= ~PARODD;
+ cflag |= (PARENB|CMSPAR);
break;
default:
- dbg("%s - Unknown parity mode, disabling parity", __func__);
+ dev_dbg(dev, "%s - Unknown parity mode, disabling parity\n", __func__);
cflag &= ~PARENB;
bits &= ~BITS_PARITY_MASK;
cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2);
@@ -542,21 +577,19 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
cflag &= ~CSTOPB;
switch (bits & BITS_STOP_MASK) {
case BITS_STOP_1:
- dbg("%s - stop bits = 1", __func__);
+ dev_dbg(dev, "%s - stop bits = 1\n", __func__);
break;
case BITS_STOP_1_5:
- dbg("%s - stop bits = 1.5 (not supported, using 1 stop bit)",
- __func__);
+ dev_dbg(dev, "%s - stop bits = 1.5 (not supported, using 1 stop bit)\n", __func__);
bits &= ~BITS_STOP_MASK;
cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2);
break;
case BITS_STOP_2:
- dbg("%s - stop bits = 2", __func__);
+ dev_dbg(dev, "%s - stop bits = 2\n", __func__);
cflag |= CSTOPB;
break;
default:
- dbg("%s - Unknown number of stop bits, using 1 stop bit",
- __func__);
+ dev_dbg(dev, "%s - Unknown number of stop bits, using 1 stop bit\n", __func__);
bits &= ~BITS_STOP_MASK;
cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2);
break;
@@ -564,45 +597,82 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
cp210x_get_config(port, CP210X_GET_FLOW, modem_ctl, 16);
if (modem_ctl[0] & 0x0008) {
- dbg("%s - flow control = CRTSCTS", __func__);
+ dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__);
cflag |= CRTSCTS;
} else {
- dbg("%s - flow control = NONE", __func__);
+ dev_dbg(dev, "%s - flow control = NONE\n", __func__);
cflag &= ~CRTSCTS;
}
*cflagp = cflag;
}
+/*
+ * CP2101 supports the following baud rates:
+ *
+ * 300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 28800,
+ * 38400, 56000, 57600, 115200, 128000, 230400, 460800, 921600
+ *
+ * CP2102 and CP2103 support the following additional rates:
+ *
+ * 4000, 16000, 51200, 64000, 76800, 153600, 250000, 256000, 500000,
+ * 576000
+ *
+ * The device will map a requested rate to a supported one, but the result
+ * of requests for rates greater than 1053257 is undefined (see AN205).
+ *
+ * CP2104, CP2105 and CP2110 support most rates up to 2M, 921k and 1M baud,
+ * respectively, with an error less than 1%. The actual rates are determined
+ * by
+ *
+ * div = round(freq / (2 x prescale x request))
+ * actual = freq / (2 x prescale x div)
+ *
+ * For CP2104 and CP2105 freq is 48Mhz and prescale is 4 for request <= 365bps
+ * or 1 otherwise.
+ * For CP2110 freq is 24Mhz and prescale is 4 for request <= 300bps or 1
+ * otherwise.
+ */
+static void cp210x_change_speed(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
+{
+ u32 baud;
+
+ baud = tty->termios.c_ospeed;
+
+ /* This maps the requested rate to a rate valid on cp2102 or cp2103,
+ * or to an arbitrary rate in [1M,2M].
+ *
+ * NOTE: B0 is not implemented.
+ */
+ baud = cp210x_quantise_baudrate(baud);
+
+ dev_dbg(&port->dev, "%s - setting baud rate to %u\n", __func__, baud);
+ if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud,
+ sizeof(baud))) {
+ dev_warn(&port->dev, "failed to set baud rate to %u\n", baud);
+ if (old_termios)
+ baud = old_termios->c_ospeed;
+ else
+ baud = 9600;
+ }
+
+ tty_encode_baud_rate(tty, baud, baud);
+}
+
static void cp210x_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
+ struct device *dev = &port->dev;
unsigned int cflag, old_cflag;
- unsigned int baud = 0, bits;
+ unsigned int bits;
unsigned int modem_ctl[4];
- dbg("%s - port %d", __func__, port->number);
-
- if (!tty)
- return;
-
- tty->termios->c_cflag &= ~CMSPAR;
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
old_cflag = old_termios->c_cflag;
- baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty));
-
- /* If the baud rate is to be updated*/
- if (baud != tty_termios_baud_rate(old_termios) && baud != 0) {
- dbg("%s - Setting baud rate to %d baud", __func__,
- baud);
- if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV,
- ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) {
- dbg("Baud rate requested not supported by device");
- baud = tty_termios_baud_rate(old_termios);
- }
- }
- /* Report back the resulting baud rate */
- tty_encode_baud_rate(tty, baud, baud);
+
+ if (tty->termios.c_ospeed != old_termios->c_ospeed)
+ cp210x_change_speed(tty, port, old_termios);
/* If the number of data bits is to be updated */
if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
@@ -611,51 +681,58 @@ static void cp210x_set_termios(struct tty_struct *tty,
switch (cflag & CSIZE) {
case CS5:
bits |= BITS_DATA_5;
- dbg("%s - data bits = 5", __func__);
+ dev_dbg(dev, "%s - data bits = 5\n", __func__);
break;
case CS6:
bits |= BITS_DATA_6;
- dbg("%s - data bits = 6", __func__);
+ dev_dbg(dev, "%s - data bits = 6\n", __func__);
break;
case CS7:
bits |= BITS_DATA_7;
- dbg("%s - data bits = 7", __func__);
+ dev_dbg(dev, "%s - data bits = 7\n", __func__);
break;
case CS8:
bits |= BITS_DATA_8;
- dbg("%s - data bits = 8", __func__);
+ dev_dbg(dev, "%s - data bits = 8\n", __func__);
break;
/*case CS9:
bits |= BITS_DATA_9;
- dbg("%s - data bits = 9", __func__);
+ dev_dbg(dev, "%s - data bits = 9\n", __func__);
break;*/
default:
- dbg("cp210x driver does not "
- "support the number of bits requested,"
- " using 8 bit mode\n");
- bits |= BITS_DATA_8;
- break;
+ dev_dbg(dev, "cp210x driver does not support the number of bits requested, using 8 bit mode\n");
+ bits |= BITS_DATA_8;
+ break;
}
if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
- dbg("Number of data bits requested "
- "not supported by device\n");
+ dev_dbg(dev, "Number of data bits requested not supported by device\n");
}
- if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) {
+ if ((cflag & (PARENB|PARODD|CMSPAR)) !=
+ (old_cflag & (PARENB|PARODD|CMSPAR))) {
cp210x_get_config(port, CP210X_GET_LINE_CTL, &bits, 2);
bits &= ~BITS_PARITY_MASK;
if (cflag & PARENB) {
- if (cflag & PARODD) {
- bits |= BITS_PARITY_ODD;
- dbg("%s - parity = ODD", __func__);
+ if (cflag & CMSPAR) {
+ if (cflag & PARODD) {
+ bits |= BITS_PARITY_MARK;
+ dev_dbg(dev, "%s - parity = MARK\n", __func__);
+ } else {
+ bits |= BITS_PARITY_SPACE;
+ dev_dbg(dev, "%s - parity = SPACE\n", __func__);
+ }
} else {
- bits |= BITS_PARITY_EVEN;
- dbg("%s - parity = EVEN", __func__);
+ if (cflag & PARODD) {
+ bits |= BITS_PARITY_ODD;
+ dev_dbg(dev, "%s - parity = ODD\n", __func__);
+ } else {
+ bits |= BITS_PARITY_EVEN;
+ dev_dbg(dev, "%s - parity = EVEN\n", __func__);
+ }
}
}
if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
- dbg("Parity mode not supported "
- "by device\n");
+ dev_dbg(dev, "Parity mode not supported by device\n");
}
if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
@@ -663,56 +740,53 @@ static void cp210x_set_termios(struct tty_struct *tty,
bits &= ~BITS_STOP_MASK;
if (cflag & CSTOPB) {
bits |= BITS_STOP_2;
- dbg("%s - stop bits = 2", __func__);
+ dev_dbg(dev, "%s - stop bits = 2\n", __func__);
} else {
bits |= BITS_STOP_1;
- dbg("%s - stop bits = 1", __func__);
+ dev_dbg(dev, "%s - stop bits = 1\n", __func__);
}
if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
- dbg("Number of stop bits requested "
- "not supported by device\n");
+ dev_dbg(dev, "Number of stop bits requested not supported by device\n");
}
if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
cp210x_get_config(port, CP210X_GET_FLOW, modem_ctl, 16);
- dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
- __func__, modem_ctl[0], modem_ctl[1],
- modem_ctl[2], modem_ctl[3]);
+ dev_dbg(dev, "%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x\n",
+ __func__, modem_ctl[0], modem_ctl[1],
+ modem_ctl[2], modem_ctl[3]);
if (cflag & CRTSCTS) {
modem_ctl[0] &= ~0x7B;
modem_ctl[0] |= 0x09;
modem_ctl[1] = 0x80;
- dbg("%s - flow control = CRTSCTS", __func__);
+ dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__);
} else {
modem_ctl[0] &= ~0x7B;
modem_ctl[0] |= 0x01;
modem_ctl[1] |= 0x40;
- dbg("%s - flow control = NONE", __func__);
+ dev_dbg(dev, "%s - flow control = NONE\n", __func__);
}
- dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
- __func__, modem_ctl[0], modem_ctl[1],
- modem_ctl[2], modem_ctl[3]);
+ dev_dbg(dev, "%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x\n",
+ __func__, modem_ctl[0], modem_ctl[1],
+ modem_ctl[2], modem_ctl[3]);
cp210x_set_config(port, CP210X_SET_FLOW, modem_ctl, 16);
}
}
-static int cp210x_tiocmset (struct tty_struct *tty, struct file *file,
+static int cp210x_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
- return cp210x_tiocmset_port(port, file, set, clear);
+ return cp210x_tiocmset_port(port, set, clear);
}
-static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *file,
+static int cp210x_tiocmset_port(struct usb_serial_port *port,
unsigned int set, unsigned int clear)
{
unsigned int control = 0;
- dbg("%s - port %d", __func__, port->number);
-
if (set & TIOCM_RTS) {
control |= CONTROL_RTS;
control |= CONTROL_WRITE_RTS;
@@ -730,7 +804,7 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *file,
control |= CONTROL_WRITE_DTR;
}
- dbg("%s - control = 0x%.4x", __func__, control);
+ dev_dbg(&port->dev, "%s - control = 0x%.4x\n", __func__, control);
return cp210x_set_config(port, CP210X_SET_MHS, &control, 2);
}
@@ -738,19 +812,17 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *file,
static void cp210x_dtr_rts(struct usb_serial_port *p, int on)
{
if (on)
- cp210x_tiocmset_port(p, NULL, TIOCM_DTR|TIOCM_RTS, 0);
+ cp210x_tiocmset_port(p, TIOCM_DTR|TIOCM_RTS, 0);
else
- cp210x_tiocmset_port(p, NULL, 0, TIOCM_DTR|TIOCM_RTS);
+ cp210x_tiocmset_port(p, 0, TIOCM_DTR|TIOCM_RTS);
}
-static int cp210x_tiocmget (struct tty_struct *tty, struct file *file)
+static int cp210x_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
unsigned int control;
int result;
- dbg("%s - port %d", __func__, port->number);
-
cp210x_get_config(port, CP210X_GET_MDMSTS, &control, 1);
result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0)
@@ -760,75 +832,54 @@ static int cp210x_tiocmget (struct tty_struct *tty, struct file *file)
|((control & CONTROL_RING)? TIOCM_RI : 0)
|((control & CONTROL_DCD) ? TIOCM_CD : 0);
- dbg("%s - control = 0x%.2x", __func__, control);
+ dev_dbg(&port->dev, "%s - control = 0x%.2x\n", __func__, control);
return result;
}
-static int cp210x_carrier_raised(struct usb_serial_port *p)
-{
- unsigned int control;
- cp210x_get_config(p, CP210X_GET_MDMSTS, &control, 1);
- if (control & CONTROL_DCD)
- return 1;
- return 0;
-}
-
-static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
+static void cp210x_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
unsigned int state;
- dbg("%s - port %d", __func__, port->number);
if (break_state == 0)
state = BREAK_OFF;
else
state = BREAK_ON;
- dbg("%s - turning break %s", __func__,
- state == BREAK_OFF ? "off" : "on");
+ dev_dbg(&port->dev, "%s - turning break %s\n", __func__,
+ state == BREAK_OFF ? "off" : "on");
cp210x_set_config(port, CP210X_SET_BREAK, &state, 2);
}
static int cp210x_startup(struct usb_serial *serial)
{
+ struct usb_host_interface *cur_altsetting;
+ struct cp210x_serial_private *spriv;
+
/* cp210x buffers behave strangely unless device is reset */
usb_reset_device(serial->dev);
- return 0;
-}
-static int __init cp210x_init(void)
-{
- int retval;
+ spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
+ if (!spriv)
+ return -ENOMEM;
- retval = usb_serial_register(&cp210x_device);
- if (retval)
- return retval; /* Failed to register */
+ cur_altsetting = serial->interface->cur_altsetting;
+ spriv->bInterfaceNumber = cur_altsetting->desc.bInterfaceNumber;
- retval = usb_register(&cp210x_driver);
- if (retval) {
- /* Failed to register */
- usb_serial_deregister(&cp210x_device);
- return retval;
- }
+ usb_set_serial_data(serial, spriv);
- /* Success */
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
return 0;
}
-static void __exit cp210x_exit(void)
+static void cp210x_release(struct usb_serial *serial)
{
- usb_deregister(&cp210x_driver);
- usb_serial_deregister(&cp210x_device);
+ struct cp210x_serial_private *spriv;
+
+ spriv = usb_get_serial_data(serial);
+ kfree(spriv);
}
-module_init(cp210x_init);
-module_exit(cp210x_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable verbose debugging messages");
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index f744ab7a3b1..2916dea3ede 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -30,7 +30,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -43,12 +42,6 @@
#define CYBERJACK_LOCAL_BUF_SIZE 32
-static int debug;
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.01"
#define DRIVER_AUTHOR "Matthias Bruestle"
#define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver"
@@ -57,9 +50,8 @@ static int debug;
#define CYBERJACK_PRODUCT_ID 0x0100
/* Function prototypes */
-static int cyberjack_startup(struct usb_serial *serial);
-static void cyberjack_disconnect(struct usb_serial *serial);
-static void cyberjack_release(struct usb_serial *serial);
+static int cyberjack_port_probe(struct usb_serial_port *port);
+static int cyberjack_port_remove(struct usb_serial_port *port);
static int cyberjack_open(struct tty_struct *tty,
struct usb_serial_port *port);
static void cyberjack_close(struct usb_serial_port *port);
@@ -77,26 +69,16 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver cyberjack_driver = {
- .name = "cyberjack",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
static struct usb_serial_driver cyberjack_device = {
.driver = {
.owner = THIS_MODULE,
.name = "cyberjack",
},
.description = "Reiner SCT Cyberjack USB card reader",
- .usb_driver = &cyberjack_driver,
.id_table = id_table,
.num_ports = 1,
- .attach = cyberjack_startup,
- .disconnect = cyberjack_disconnect,
- .release = cyberjack_release,
+ .port_probe = cyberjack_port_probe,
+ .port_remove = cyberjack_port_remove,
.open = cyberjack_open,
.close = cyberjack_close,
.write = cyberjack_write,
@@ -106,6 +88,10 @@ static struct usb_serial_driver cyberjack_device = {
.write_bulk_callback = cyberjack_write_bulk_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &cyberjack_device, NULL
+};
+
struct cyberjack_private {
spinlock_t lock; /* Lock for SMP */
short rdtodo; /* Bytes still to read */
@@ -114,62 +100,39 @@ struct cyberjack_private {
short wrsent; /* Data already sent */
};
-/* do some startup allocations not currently performed by usb_serial_probe() */
-static int cyberjack_startup(struct usb_serial *serial)
+static int cyberjack_port_probe(struct usb_serial_port *port)
{
struct cyberjack_private *priv;
- int i;
-
- dbg("%s", __func__);
+ int result;
- /* allocate the private data structure */
priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
- /* set initial values */
spin_lock_init(&priv->lock);
priv->rdtodo = 0;
priv->wrfilled = 0;
priv->wrsent = 0;
- usb_set_serial_port_data(serial->port[0], priv);
- init_waitqueue_head(&serial->port[0]->write_wait);
+ usb_set_serial_port_data(port, priv);
- for (i = 0; i < serial->num_ports; ++i) {
- int result;
- serial->port[i]->interrupt_in_urb->dev = serial->dev;
- result = usb_submit_urb(serial->port[i]->interrupt_in_urb,
- GFP_KERNEL);
- if (result)
- dev_err(&serial->dev->dev,
- "usb_submit_urb(read int) failed\n");
- dbg("%s - usb_submit_urb(int urb)", __func__);
- }
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (result)
+ dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
return 0;
}
-static void cyberjack_disconnect(struct usb_serial *serial)
+static int cyberjack_port_remove(struct usb_serial_port *port)
{
- int i;
-
- dbg("%s", __func__);
+ struct cyberjack_private *priv;
- for (i = 0; i < serial->num_ports; ++i)
- usb_kill_urb(serial->port[i]->interrupt_in_urb);
-}
+ usb_kill_urb(port->interrupt_in_urb);
-static void cyberjack_release(struct usb_serial *serial)
-{
- int i;
-
- dbg("%s", __func__);
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
- for (i = 0; i < serial->num_ports; ++i) {
- /* My special items, the standard routines free my urbs */
- kfree(usb_get_serial_port_data(serial->port[i]));
- }
+ return 0;
}
static int cyberjack_open(struct tty_struct *tty,
@@ -179,9 +142,7 @@ static int cyberjack_open(struct tty_struct *tty,
unsigned long flags;
int result = 0;
- dbg("%s - port %d", __func__, port->number);
-
- dbg("%s - usb_clear_halt", __func__);
+ dev_dbg(&port->dev, "%s - usb_clear_halt\n", __func__);
usb_clear_halt(port->serial->dev, port->write_urb->pipe);
priv = usb_get_serial_port_data(port);
@@ -196,60 +157,48 @@ static int cyberjack_open(struct tty_struct *tty,
static void cyberjack_close(struct usb_serial_port *port)
{
- dbg("%s - port %d", __func__, port->number);
-
- if (port->serial->dev) {
- /* shutdown any bulk reads that might be going on */
- usb_kill_urb(port->write_urb);
- usb_kill_urb(port->read_urb);
- }
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
}
static int cyberjack_write(struct tty_struct *tty,
struct usb_serial_port *port, const unsigned char *buf, int count)
{
- struct usb_serial *serial = port->serial;
+ struct device *dev = &port->dev;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int result;
int wrexpected;
- dbg("%s - port %d", __func__, port->number);
-
if (count == 0) {
- dbg("%s - write request of 0 bytes", __func__);
+ dev_dbg(dev, "%s - write request of 0 bytes\n", __func__);
return 0;
}
- spin_lock_bh(&port->lock);
- if (port->write_urb_busy) {
- spin_unlock_bh(&port->lock);
- dbg("%s - already writing", __func__);
+ if (!test_and_clear_bit(0, &port->write_urbs_free)) {
+ dev_dbg(dev, "%s - already writing\n", __func__);
return 0;
}
- port->write_urb_busy = 1;
- spin_unlock_bh(&port->lock);
spin_lock_irqsave(&priv->lock, flags);
if (count+priv->wrfilled > sizeof(priv->wrbuf)) {
/* To much data for buffer. Reset buffer. */
priv->wrfilled = 0;
- port->write_urb_busy = 0;
spin_unlock_irqrestore(&priv->lock, flags);
+ set_bit(0, &port->write_urbs_free);
return 0;
}
/* Copy data */
memcpy(priv->wrbuf + priv->wrfilled, buf, count);
- usb_serial_debug_data(debug, &port->dev, __func__, count,
- priv->wrbuf + priv->wrfilled);
+ usb_serial_debug_data(dev, __func__, count, priv->wrbuf + priv->wrfilled);
priv->wrfilled += count;
if (priv->wrfilled >= 3) {
wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
- dbg("%s - expected data: %d", __func__, wrexpected);
+ dev_dbg(dev, "%s - expected data: %d\n", __func__, wrexpected);
} else
wrexpected = sizeof(priv->wrbuf);
@@ -257,7 +206,7 @@ static int cyberjack_write(struct tty_struct *tty,
/* We have enough data to begin transmission */
int length;
- dbg("%s - transmitting data (frame 1)", __func__);
+ dev_dbg(dev, "%s - transmitting data (frame 1)\n", __func__);
length = (wrexpected > port->bulk_out_size) ?
port->bulk_out_size : wrexpected;
@@ -265,33 +214,27 @@ static int cyberjack_write(struct tty_struct *tty,
priv->wrsent = length;
/* set up our urb */
- usb_fill_bulk_urb(port->write_urb, serial->dev,
- usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
- port->write_urb->transfer_buffer, length,
- ((serial->type->write_bulk_callback) ?
- serial->type->write_bulk_callback :
- cyberjack_write_bulk_callback),
- port);
+ port->write_urb->transfer_buffer_length = length;
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
dev_err(&port->dev,
- "%s - failed submitting write urb, error %d",
+ "%s - failed submitting write urb, error %d\n",
__func__, result);
/* Throw away data. No better idea what to do with it. */
priv->wrfilled = 0;
priv->wrsent = 0;
spin_unlock_irqrestore(&priv->lock, flags);
- port->write_urb_busy = 0;
+ set_bit(0, &port->write_urbs_free);
return 0;
}
- dbg("%s - priv->wrsent=%d", __func__, priv->wrsent);
- dbg("%s - priv->wrfilled=%d", __func__, priv->wrfilled);
+ dev_dbg(dev, "%s - priv->wrsent=%d\n", __func__, priv->wrsent);
+ dev_dbg(dev, "%s - priv->wrfilled=%d\n", __func__, priv->wrfilled);
if (priv->wrsent >= priv->wrfilled) {
- dbg("%s - buffer cleaned", __func__);
+ dev_dbg(dev, "%s - buffer cleaned\n", __func__);
memset(priv->wrbuf, 0, sizeof(priv->wrbuf));
priv->wrfilled = 0;
priv->wrsent = 0;
@@ -313,18 +256,16 @@ static void cyberjack_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
+ struct device *dev = &port->dev;
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
int result;
- dbg("%s - port %d", __func__, port->number);
-
/* the urb might have been killed. */
if (status)
return;
- usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, data);
+ usb_serial_debug_data(dev, __func__, urb->actual_length, data);
/* React only to interrupts signaling a bulk_in transfer */
if (urb->actual_length == 4 && data[0] == 0x01) {
@@ -337,68 +278,56 @@ static void cyberjack_read_int_callback(struct urb *urb)
old_rdtodo = priv->rdtodo;
- if (old_rdtodo + size < old_rdtodo) {
- dbg("To many bulk_in urbs to do.");
+ if (old_rdtodo > SHRT_MAX - size) {
+ dev_dbg(dev, "To many bulk_in urbs to do.\n");
spin_unlock(&priv->lock);
goto resubmit;
}
- /* "+=" is probably more fault tollerant than "=" */
+ /* "+=" is probably more fault tolerant than "=" */
priv->rdtodo += size;
- dbg("%s - rdtodo: %d", __func__, priv->rdtodo);
+ dev_dbg(dev, "%s - rdtodo: %d\n", __func__, priv->rdtodo);
spin_unlock(&priv->lock);
if (!old_rdtodo) {
- port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- dev_err(&port->dev, "%s - failed resubmitting "
- "read urb, error %d\n",
+ dev_err(dev, "%s - failed resubmitting read urb, error %d\n",
__func__, result);
- dbg("%s - usb_submit_urb(read urb)", __func__);
+ dev_dbg(dev, "%s - usb_submit_urb(read urb)\n", __func__);
}
}
resubmit:
- port->interrupt_in_urb->dev = port->serial->dev;
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result)
dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
- dbg("%s - usb_submit_urb(int urb)", __func__);
+ dev_dbg(dev, "%s - usb_submit_urb(int urb)\n", __func__);
}
static void cyberjack_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty;
+ struct device *dev = &port->dev;
unsigned char *data = urb->transfer_buffer;
short todo;
int result;
int status = urb->status;
- dbg("%s - port %d", __func__, port->number);
-
- usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, data);
+ usb_serial_debug_data(dev, __func__, urb->actual_length, data);
if (status) {
- dbg("%s - nonzero read bulk status received: %d",
- __func__, status);
+ dev_dbg(dev, "%s - nonzero read bulk status received: %d\n",
+ __func__, status);
return;
}
- tty = tty_port_tty_get(&port->port);
- if (!tty) {
- dbg("%s - ignoring since device not open", __func__);
- return;
- }
if (urb->actual_length) {
- tty_insert_flip_string(tty, data, urb->actual_length);
- tty_flip_buffer_push(tty);
+ tty_insert_flip_string(&port->port, data, urb->actual_length);
+ tty_flip_buffer_push(&port->port);
}
- tty_kref_put(tty);
spin_lock(&priv->lock);
@@ -411,16 +340,15 @@ static void cyberjack_read_bulk_callback(struct urb *urb)
spin_unlock(&priv->lock);
- dbg("%s - rdtodo: %d", __func__, todo);
+ dev_dbg(dev, "%s - rdtodo: %d\n", __func__, todo);
/* Continue to read if we have still urbs to do. */
if (todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/) {
- port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- dev_err(&port->dev, "%s - failed resubmitting read "
- "urb, error %d\n", __func__, result);
- dbg("%s - usb_submit_urb(read urb)", __func__);
+ dev_err(dev, "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
+ dev_dbg(dev, "%s - usb_submit_urb(read urb)\n", __func__);
}
}
@@ -428,14 +356,13 @@ static void cyberjack_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
+ struct device *dev = &port->dev;
int status = urb->status;
- dbg("%s - port %d", __func__, port->number);
-
- port->write_urb_busy = 0;
+ set_bit(0, &port->write_urbs_free);
if (status) {
- dbg("%s - nonzero write bulk status received: %d",
- __func__, status);
+ dev_dbg(dev, "%s - nonzero write bulk status received: %d\n",
+ __func__, status);
return;
}
@@ -445,7 +372,7 @@ static void cyberjack_write_bulk_callback(struct urb *urb)
if (priv->wrfilled) {
int length, blksize, result;
- dbg("%s - transmitting data (frame n)", __func__);
+ dev_dbg(dev, "%s - transmitting data (frame n)\n", __func__);
length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ?
port->bulk_out_size : (priv->wrfilled - priv->wrsent);
@@ -455,19 +382,12 @@ static void cyberjack_write_bulk_callback(struct urb *urb)
priv->wrsent += length;
/* set up our urb */
- usb_fill_bulk_urb(port->write_urb, port->serial->dev,
- usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
- port->write_urb->transfer_buffer, length,
- ((port->serial->type->write_bulk_callback) ?
- port->serial->type->write_bulk_callback :
- cyberjack_write_bulk_callback),
- port);
+ port->write_urb->transfer_buffer_length = length;
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev,
- "%s - failed submitting write urb, error %d\n",
+ dev_err(dev, "%s - failed submitting write urb, error %d\n",
__func__, result);
/* Throw away data. No better idea what to do with it. */
priv->wrfilled = 0;
@@ -475,14 +395,14 @@ static void cyberjack_write_bulk_callback(struct urb *urb)
goto exit;
}
- dbg("%s - priv->wrsent=%d", __func__, priv->wrsent);
- dbg("%s - priv->wrfilled=%d", __func__, priv->wrfilled);
+ dev_dbg(dev, "%s - priv->wrsent=%d\n", __func__, priv->wrsent);
+ dev_dbg(dev, "%s - priv->wrfilled=%d\n", __func__, priv->wrfilled);
blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
if (priv->wrsent >= priv->wrfilled ||
priv->wrsent >= blksize) {
- dbg("%s - buffer cleaned", __func__);
+ dev_dbg(dev, "%s - buffer cleaned\n", __func__);
memset(priv->wrbuf, 0, sizeof(priv->wrbuf));
priv->wrfilled = 0;
priv->wrsent = 0;
@@ -494,40 +414,8 @@ exit:
usb_serial_port_softint(port);
}
-static int __init cyberjack_init(void)
-{
- int retval;
- retval = usb_serial_register(&cyberjack_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&cyberjack_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION " "
- DRIVER_AUTHOR "\n");
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
-
- return 0;
-failed_usb_register:
- usb_serial_deregister(&cyberjack_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit cyberjack_exit(void)
-{
- usb_deregister(&cyberjack_driver);
- usb_serial_deregister(&cyberjack_device);
-}
-
-module_init(cyberjack_init);
-module_exit(cyberjack_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 2edf238b00b..01bf5339281 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -16,32 +16,6 @@
*
* See http://geocities.com/i0xox0i for information on this driver and the
* earthmate usb device.
- *
- * Lonnie Mendez <dignome@gmail.com>
- * 4-29-2005
- * Fixed problem where setting or retreiving the serial config would fail
- * with EPIPE. Removed CRTS toggling so the driver behaves more like
- * other usbserial adapters. Issued new interval of 1ms instead of the
- * default 10ms. As a result, transfer speed has been substantially
- * increased from avg. 850bps to avg. 3300bps. initial termios has also
- * been modified. Cleaned up code and formatting issues so it is more
- * readable. Replaced the C++ style comments.
- *
- * Lonnie Mendez <dignome@gmail.com>
- * 12-15-2004
- * Incorporated write buffering from pl2303 driver. Fixed bug with line
- * handling so both lines are raised in cypress_open. (was dropping rts)
- * Various code cleanups made as well along with other misc bug fixes.
- *
- * Lonnie Mendez <dignome@gmail.com>
- * 04-10-2004
- * Driver modified to support dynamic line settings. Various improvments
- * and features.
- *
- * Neil Whelchel
- * 10-2003
- * Driver first released.
- *
*/
/* Thanks to Neil Whelchel for writing the first cypress m8 implementation
@@ -53,7 +27,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -72,15 +45,10 @@
#include "cypress_m8.h"
-static int debug;
-static int stats;
+static bool stats;
static int interval;
-static int unstable_bauds;
+static bool unstable_bauds;
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.10"
#define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>"
#define DRIVER_DESC "Cypress USB to Serial Driver"
@@ -96,6 +64,7 @@ static const struct usb_device_id id_table_earthmate[] = {
static const struct usb_device_id id_table_cyphidcomrs232[] = {
{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
{ USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
+ { USB_DEVICE(VENDOR_ID_FRWD, PRODUCT_ID_CYPHIDCOM_FRWD) },
{ } /* Terminating entry */
};
@@ -109,20 +78,13 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
{ USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
+ { USB_DEVICE(VENDOR_ID_FRWD, PRODUCT_ID_CYPHIDCOM_FRWD) },
{ USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver cypress_driver = {
- .name = "cypress",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
- .no_dynamic_id = 1,
-};
-
enum packet_format {
packet_format_1, /* b0:status, b1:payload count */
packet_format_2 /* b0[7:3]:status, b0[2:0]:payload count */
@@ -150,18 +112,17 @@ struct cypress_private {
int baud_rate; /* stores current baud rate in
integer form */
int isthrottled; /* if throttled, discard reads */
- wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */
- char prev_status, diff_status; /* used for TIOCMIWAIT */
+ char prev_status; /* used for TIOCMIWAIT */
/* we pass a pointer to this as the argument sent to
cypress_set_termios old_termios */
struct ktermios tmp_termios; /* stores the old termios settings */
};
/* function prototypes for the Cypress USB to serial device */
-static int cypress_earthmate_startup(struct usb_serial *serial);
-static int cypress_hidcom_startup(struct usb_serial *serial);
-static int cypress_ca42v2_startup(struct usb_serial *serial);
-static void cypress_release(struct usb_serial *serial);
+static int cypress_earthmate_port_probe(struct usb_serial_port *port);
+static int cypress_hidcom_port_probe(struct usb_serial_port *port);
+static int cypress_ca42v2_port_probe(struct usb_serial_port *port);
+static int cypress_port_remove(struct usb_serial_port *port);
static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port);
static void cypress_close(struct usb_serial_port *port);
static void cypress_dtr_rts(struct usb_serial_port *port, int on);
@@ -169,12 +130,10 @@ static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static void cypress_send(struct usb_serial_port *port);
static int cypress_write_room(struct tty_struct *tty);
-static int cypress_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg);
static void cypress_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
-static int cypress_tiocmget(struct tty_struct *tty, struct file *file);
-static int cypress_tiocmset(struct tty_struct *tty, struct file *file,
+static int cypress_tiocmget(struct tty_struct *tty);
+static int cypress_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
static int cypress_chars_in_buffer(struct tty_struct *tty);
static void cypress_throttle(struct tty_struct *tty);
@@ -189,20 +148,19 @@ static struct usb_serial_driver cypress_earthmate_device = {
.name = "earthmate",
},
.description = "DeLorme Earthmate USB",
- .usb_driver = &cypress_driver,
.id_table = id_table_earthmate,
.num_ports = 1,
- .attach = cypress_earthmate_startup,
- .release = cypress_release,
+ .port_probe = cypress_earthmate_port_probe,
+ .port_remove = cypress_port_remove,
.open = cypress_open,
.close = cypress_close,
.dtr_rts = cypress_dtr_rts,
.write = cypress_write,
.write_room = cypress_write_room,
- .ioctl = cypress_ioctl,
.set_termios = cypress_set_termios,
.tiocmget = cypress_tiocmget,
.tiocmset = cypress_tiocmset,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
.chars_in_buffer = cypress_chars_in_buffer,
.throttle = cypress_throttle,
.unthrottle = cypress_unthrottle,
@@ -216,20 +174,19 @@ static struct usb_serial_driver cypress_hidcom_device = {
.name = "cyphidcom",
},
.description = "HID->COM RS232 Adapter",
- .usb_driver = &cypress_driver,
.id_table = id_table_cyphidcomrs232,
.num_ports = 1,
- .attach = cypress_hidcom_startup,
- .release = cypress_release,
+ .port_probe = cypress_hidcom_port_probe,
+ .port_remove = cypress_port_remove,
.open = cypress_open,
.close = cypress_close,
.dtr_rts = cypress_dtr_rts,
.write = cypress_write,
.write_room = cypress_write_room,
- .ioctl = cypress_ioctl,
.set_termios = cypress_set_termios,
.tiocmget = cypress_tiocmget,
.tiocmset = cypress_tiocmset,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
.chars_in_buffer = cypress_chars_in_buffer,
.throttle = cypress_throttle,
.unthrottle = cypress_unthrottle,
@@ -243,20 +200,19 @@ static struct usb_serial_driver cypress_ca42v2_device = {
.name = "nokiaca42v2",
},
.description = "Nokia CA-42 V2 Adapter",
- .usb_driver = &cypress_driver,
.id_table = id_table_nokiaca42v2,
.num_ports = 1,
- .attach = cypress_ca42v2_startup,
- .release = cypress_release,
+ .port_probe = cypress_ca42v2_port_probe,
+ .port_remove = cypress_port_remove,
.open = cypress_open,
.close = cypress_close,
.dtr_rts = cypress_dtr_rts,
.write = cypress_write,
.write_room = cypress_write_room,
- .ioctl = cypress_ioctl,
.set_termios = cypress_set_termios,
.tiocmget = cypress_tiocmget,
.tiocmset = cypress_tiocmset,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
.chars_in_buffer = cypress_chars_in_buffer,
.throttle = cypress_throttle,
.unthrottle = cypress_unthrottle,
@@ -264,10 +220,21 @@ static struct usb_serial_driver cypress_ca42v2_device = {
.write_int_callback = cypress_write_int_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &cypress_earthmate_device, &cypress_hidcom_device,
+ &cypress_ca42v2_device, NULL
+};
+
/*****************************************************************************
* Cypress serial helper functions
*****************************************************************************/
+/* FRWD Dongle hidcom needs to skip reset and speed checks */
+static inline bool is_frwd(struct usb_device *dev)
+{
+ return ((le16_to_cpu(dev->descriptor.idVendor) == VENDOR_ID_FRWD) &&
+ (le16_to_cpu(dev->descriptor.idProduct) == PRODUCT_ID_CYPHIDCOM_FRWD));
+}
static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
{
@@ -277,6 +244,10 @@ static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
if (unstable_bauds)
return new_rate;
+ /* FRWD Dongle uses 115200 bps */
+ if (is_frwd(port->serial->dev))
+ return new_rate;
+
/*
* The general purpose firmware for the Cypress M8 allows for
* a maximum speed of 57600bps (I have no idea whether DeLorme
@@ -295,8 +266,9 @@ static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
* safest speed for a part like that.
*/
if (new_rate > 4800) {
- dbg("%s - failed setting baud rate, device incapable "
- "speed %d", __func__, new_rate);
+ dev_dbg(&port->dev,
+ "%s - failed setting baud rate, device incapable speed %d\n",
+ __func__, new_rate);
return -1;
}
}
@@ -306,8 +278,9 @@ static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
/* 300 and 600 baud rates are supported under
* the generic firmware, but are not used with
* NMEA and SiRF protocols */
- dbg("%s - failed setting baud rate, unsupported speed "
- "of %d on Earthmate GPS", __func__, new_rate);
+ dev_dbg(&port->dev,
+ "%s - failed setting baud rate, unsupported speed of %d on Earthmate GPS\n",
+ __func__, new_rate);
return -1;
}
break;
@@ -326,12 +299,11 @@ static int cypress_serial_control(struct tty_struct *tty,
{
int new_baudrate = 0, retval = 0, tries = 0;
struct cypress_private *priv;
+ struct device *dev = &port->dev;
u8 *feature_buffer;
const unsigned int feature_len = 5;
unsigned long flags;
- dbg("%s", __func__);
-
priv = usb_get_serial_port_data(port);
if (!priv->comm_is_ok)
@@ -346,16 +318,16 @@ static int cypress_serial_control(struct tty_struct *tty,
/* 0 means 'Hang up' so doesn't change the true bit rate */
new_baudrate = priv->baud_rate;
if (baud_rate && baud_rate != priv->baud_rate) {
- dbg("%s - baud rate is changing", __func__);
+ dev_dbg(dev, "%s - baud rate is changing\n", __func__);
retval = analyze_baud_rate(port, baud_rate);
if (retval >= 0) {
new_baudrate = retval;
- dbg("%s - New baud rate set to %d",
- __func__, new_baudrate);
+ dev_dbg(dev, "%s - New baud rate set to %d\n",
+ __func__, new_baudrate);
}
}
- dbg("%s - baud rate is being sent as %d",
- __func__, new_baudrate);
+ dev_dbg(dev, "%s - baud rate is being sent as %d\n", __func__,
+ new_baudrate);
/* fill the feature_buffer with new configuration */
put_unaligned_le32(new_baudrate, feature_buffer);
@@ -367,9 +339,8 @@ static int cypress_serial_control(struct tty_struct *tty,
/* 1 bit gap */
feature_buffer[4] |= (reset << 7); /* assign reset at end of byte, 1 bit space */
- dbg("%s - device is being sent this feature report:",
- __func__);
- dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__,
+ dev_dbg(dev, "%s - device is being sent this feature report:\n", __func__);
+ dev_dbg(dev, "%s - %02X - %02X - %02X - %02X - %02X\n", __func__,
feature_buffer[0], feature_buffer[1],
feature_buffer[2], feature_buffer[3],
feature_buffer[4]);
@@ -389,8 +360,8 @@ static int cypress_serial_control(struct tty_struct *tty,
retval != -ENODEV);
if (retval != feature_len) {
- dev_err(&port->dev, "%s - failed sending serial "
- "line settings - %d\n", __func__, retval);
+ dev_err(dev, "%s - failed sending serial line settings - %d\n",
+ __func__, retval);
cypress_set_dead(port);
} else {
spin_lock_irqsave(&priv->lock, flags);
@@ -411,7 +382,7 @@ static int cypress_serial_control(struct tty_struct *tty,
retval = -ENOTTY;
goto out;
}
- dbg("%s - retreiving serial line settings", __func__);
+ dev_dbg(dev, "%s - retreiving serial line settings\n", __func__);
do {
retval = usb_control_msg(port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0),
@@ -426,8 +397,8 @@ static int cypress_serial_control(struct tty_struct *tty,
&& retval != -ENODEV);
if (retval != feature_len) {
- dev_err(&port->dev, "%s - failed to retrieve serial "
- "line settings - %d\n", __func__, retval);
+ dev_err(dev, "%s - failed to retrieve serial line settings - %d\n",
+ __func__, retval);
cypress_set_dead(port);
goto out;
} else {
@@ -462,7 +433,7 @@ static void cypress_set_dead(struct usb_serial_port *port)
spin_unlock_irqrestore(&priv->lock, flags);
dev_err(&port->dev, "cypress_m8 suspending failing port %d - "
- "interval might be too short\n", port->number);
+ "interval might be too short\n", port->port_number);
}
@@ -471,12 +442,10 @@ static void cypress_set_dead(struct usb_serial_port *port)
*****************************************************************************/
-static int generic_startup(struct usb_serial *serial)
+static int cypress_generic_port_probe(struct usb_serial_port *port)
{
+ struct usb_serial *serial = port->serial;
struct cypress_private *priv;
- struct usb_serial_port *port = serial->port[0];
-
- dbg("%s - port %d", __func__, port->number);
priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
if (!priv)
@@ -488,9 +457,12 @@ static int generic_startup(struct usb_serial *serial)
kfree(priv);
return -ENOMEM;
}
- init_waitqueue_head(&priv->delta_msr_wait);
- usb_reset_configuration(serial->dev);
+ /* Skip reset for FRWD device. It is a workaound:
+ device hangs if it receives SET_CONFIGURE in Configured
+ state. */
+ if (!is_frwd(serial->dev))
+ usb_reset_configuration(serial->dev);
priv->cmd_ctrl = 0;
priv->line_control = 0;
@@ -510,32 +482,33 @@ static int generic_startup(struct usb_serial *serial)
if (interval > 0) {
priv->write_urb_interval = interval;
priv->read_urb_interval = interval;
- dbg("%s - port %d read & write intervals forced to %d",
- __func__, port->number, interval);
+ dev_dbg(&port->dev, "%s - read & write intervals forced to %d\n",
+ __func__, interval);
} else {
priv->write_urb_interval = port->interrupt_out_urb->interval;
priv->read_urb_interval = port->interrupt_in_urb->interval;
- dbg("%s - port %d intervals: read=%d write=%d",
- __func__, port->number,
- priv->read_urb_interval, priv->write_urb_interval);
+ dev_dbg(&port->dev, "%s - intervals: read=%d write=%d\n",
+ __func__, priv->read_urb_interval,
+ priv->write_urb_interval);
}
usb_set_serial_port_data(port, priv);
+ port->port.drain_delay = 256;
+
return 0;
}
-static int cypress_earthmate_startup(struct usb_serial *serial)
+static int cypress_earthmate_port_probe(struct usb_serial_port *port)
{
+ struct usb_serial *serial = port->serial;
struct cypress_private *priv;
- struct usb_serial_port *port = serial->port[0];
-
- dbg("%s", __func__);
+ int ret;
- if (generic_startup(serial)) {
- dbg("%s - Failed setting up port %d", __func__,
- port->number);
- return 1;
+ ret = cypress_generic_port_probe(port);
+ if (ret) {
+ dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
+ return ret;
}
priv = usb_get_serial_port_data(port);
@@ -549,70 +522,61 @@ static int cypress_earthmate_startup(struct usb_serial *serial)
handle GET_CONFIG requests; everything they've
produced since that time crashes if this command is
attempted :-( */
- dbg("%s - Marking this device as unsafe for GET_CONFIG "
- "commands", __func__);
+ dev_dbg(&port->dev,
+ "%s - Marking this device as unsafe for GET_CONFIG commands\n",
+ __func__);
priv->get_cfg_unsafe = !0;
}
return 0;
-} /* cypress_earthmate_startup */
-
+}
-static int cypress_hidcom_startup(struct usb_serial *serial)
+static int cypress_hidcom_port_probe(struct usb_serial_port *port)
{
struct cypress_private *priv;
+ int ret;
- dbg("%s", __func__);
-
- if (generic_startup(serial)) {
- dbg("%s - Failed setting up port %d", __func__,
- serial->port[0]->number);
- return 1;
+ ret = cypress_generic_port_probe(port);
+ if (ret) {
+ dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
+ return ret;
}
- priv = usb_get_serial_port_data(serial->port[0]);
+ priv = usb_get_serial_port_data(port);
priv->chiptype = CT_CYPHIDCOM;
return 0;
-} /* cypress_hidcom_startup */
-
+}
-static int cypress_ca42v2_startup(struct usb_serial *serial)
+static int cypress_ca42v2_port_probe(struct usb_serial_port *port)
{
struct cypress_private *priv;
+ int ret;
- dbg("%s", __func__);
-
- if (generic_startup(serial)) {
- dbg("%s - Failed setting up port %d", __func__,
- serial->port[0]->number);
- return 1;
+ ret = cypress_generic_port_probe(port);
+ if (ret) {
+ dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
+ return ret;
}
- priv = usb_get_serial_port_data(serial->port[0]);
+ priv = usb_get_serial_port_data(port);
priv->chiptype = CT_CA42V2;
return 0;
-} /* cypress_ca42v2_startup */
-
+}
-static void cypress_release(struct usb_serial *serial)
+static int cypress_port_remove(struct usb_serial_port *port)
{
struct cypress_private *priv;
- dbg("%s - port %d", __func__, serial->port[0]->number);
-
- /* all open ports are closed at this point */
+ priv = usb_get_serial_port_data(port);
- priv = usb_get_serial_port_data(serial->port[0]);
+ kfifo_free(&priv->write_fifo);
+ kfree(priv);
- if (priv) {
- kfifo_free(&priv->write_fifo);
- kfree(priv);
- }
+ return 0;
}
-
static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
@@ -620,8 +584,6 @@ static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port)
unsigned long flags;
int result = 0;
- dbg("%s - port %d", __func__, port->number);
-
if (!priv->comm_is_ok)
return -EIO;
@@ -663,7 +625,7 @@ static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port)
__func__, result);
cypress_set_dead(port);
}
- port->port.drain_delay = 256;
+
return result;
} /* cypress_open */
@@ -686,26 +648,17 @@ static void cypress_close(struct usb_serial_port *port)
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
- /* writing is potentially harmful, lock must be taken */
- mutex_lock(&port->serial->disc_mutex);
- if (port->serial->disconnected) {
- mutex_unlock(&port->serial->disc_mutex);
- return;
- }
spin_lock_irqsave(&priv->lock, flags);
kfifo_reset_out(&priv->write_fifo);
spin_unlock_irqrestore(&priv->lock, flags);
- dbg("%s - stopping urbs", __func__);
+ dev_dbg(&port->dev, "%s - stopping urbs\n", __func__);
usb_kill_urb(port->interrupt_in_urb);
usb_kill_urb(port->interrupt_out_urb);
if (stats)
dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
priv->bytes_in, priv->bytes_out, priv->cmd_count);
- mutex_unlock(&port->serial->disc_mutex);
} /* cypress_close */
@@ -714,7 +667,7 @@ static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
{
struct cypress_private *priv = usb_get_serial_port_data(port);
- dbg("%s - port %d, %d bytes", __func__, port->number, count);
+ dev_dbg(&port->dev, "%s - %d bytes\n", __func__, count);
/* line control commands, which need to be executed immediately,
are not put into the buffer for obvious reasons.
@@ -740,18 +693,18 @@ static void cypress_send(struct usb_serial_port *port)
{
int count = 0, result, offset, actual_size;
struct cypress_private *priv = usb_get_serial_port_data(port);
+ struct device *dev = &port->dev;
unsigned long flags;
if (!priv->comm_is_ok)
return;
- dbg("%s - port %d", __func__, port->number);
- dbg("%s - interrupt out size is %d", __func__,
- port->interrupt_out_size);
+ dev_dbg(dev, "%s - interrupt out size is %d\n", __func__,
+ port->interrupt_out_size);
spin_lock_irqsave(&priv->lock, flags);
if (priv->write_urb_in_use) {
- dbg("%s - can't write, urb in use", __func__);
+ dev_dbg(dev, "%s - can't write, urb in use\n", __func__);
spin_unlock_irqrestore(&priv->lock, flags);
return;
}
@@ -781,7 +734,7 @@ static void cypress_send(struct usb_serial_port *port)
if (priv->cmd_ctrl) {
priv->cmd_count++;
- dbg("%s - line control command being issued", __func__);
+ dev_dbg(dev, "%s - line control command being issued\n", __func__);
spin_unlock_irqrestore(&priv->lock, flags);
goto send;
} else
@@ -803,7 +756,7 @@ static void cypress_send(struct usb_serial_port *port)
port->interrupt_out_buffer[0] |= count;
}
- dbg("%s - count is %d", __func__, count);
+ dev_dbg(dev, "%s - count is %d\n", __func__, count);
send:
spin_lock_irqsave(&priv->lock, flags);
@@ -816,9 +769,8 @@ send:
actual_size = count +
(priv->pkt_fmt == packet_format_1 ? 2 : 1);
- usb_serial_debug_data(debug, &port->dev, __func__,
- port->interrupt_out_size,
- port->interrupt_out_urb->transfer_buffer);
+ usb_serial_debug_data(dev, __func__, port->interrupt_out_size,
+ port->interrupt_out_urb->transfer_buffer);
usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev,
usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress),
@@ -826,7 +778,7 @@ send:
cypress_write_int_callback, port, priv->write_urb_interval);
result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev,
+ dev_err_console(port,
"%s - failed submitting write urb, error %d\n",
__func__, result);
priv->write_urb_in_use = 0;
@@ -853,18 +805,16 @@ static int cypress_write_room(struct tty_struct *tty)
int room = 0;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
room = kfifo_avail(&priv->write_fifo);
spin_unlock_irqrestore(&priv->lock, flags);
- dbg("%s - returns %d", __func__, room);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, room);
return room;
}
-static int cypress_tiocmget(struct tty_struct *tty, struct file *file)
+static int cypress_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
@@ -872,8 +822,6 @@ static int cypress_tiocmget(struct tty_struct *tty, struct file *file)
unsigned int result = 0;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
control = priv->line_control;
status = priv->current_status;
@@ -886,21 +834,19 @@ static int cypress_tiocmget(struct tty_struct *tty, struct file *file)
| ((status & UART_RI) ? TIOCM_RI : 0)
| ((status & UART_CD) ? TIOCM_CD : 0);
- dbg("%s - result = %x", __func__, result);
+ dev_dbg(&port->dev, "%s - result = %x\n", __func__, result);
return result;
}
-static int cypress_tiocmset(struct tty_struct *tty, struct file *file,
+static int cypress_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
if (set & TIOCM_RTS)
priv->line_control |= CONTROL_RTS;
@@ -916,102 +862,54 @@ static int cypress_tiocmset(struct tty_struct *tty, struct file *file,
return cypress_write(tty, port, NULL, 0);
}
-
-static int cypress_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct cypress_private *priv = usb_get_serial_port_data(port);
-
- dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
-
- switch (cmd) {
- /* This code comes from drivers/char/serial.c and ftdi_sio.c */
- case TIOCMIWAIT:
- while (priv != NULL) {
- interruptible_sleep_on(&priv->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- else {
- char diff = priv->diff_status;
- if (diff == 0)
- return -EIO; /* no change => error */
-
- /* consume all events */
- priv->diff_status = 0;
-
- /* return 0 if caller wanted to know about
- these bits */
- if (((arg & TIOCM_RNG) && (diff & UART_RI)) ||
- ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
- ((arg & TIOCM_CD) && (diff & UART_CD)) ||
- ((arg & TIOCM_CTS) && (diff & UART_CTS)))
- return 0;
- /* otherwise caller can't care less about what
- * happened, and so we continue to wait for
- * more events.
- */
- }
- }
- return 0;
- default:
- break;
- }
- dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __func__, cmd);
- return -ENOIOCTLCMD;
-} /* cypress_ioctl */
-
-
static void cypress_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
+ struct device *dev = &port->dev;
int data_bits, stop_bits, parity_type, parity_enable;
unsigned cflag, iflag;
unsigned long flags;
__u8 oldlines;
int linechange = 0;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
/* We can't clean this one up as we don't know the device type
early enough */
if (!priv->termios_initialized) {
if (priv->chiptype == CT_EARTHMATE) {
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL |
+ tty->termios = tty_std_termios;
+ tty->termios.c_cflag = B4800 | CS8 | CREAD | HUPCL |
CLOCAL;
- tty->termios->c_ispeed = 4800;
- tty->termios->c_ospeed = 4800;
+ tty->termios.c_ispeed = 4800;
+ tty->termios.c_ospeed = 4800;
} else if (priv->chiptype == CT_CYPHIDCOM) {
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ tty->termios = tty_std_termios;
+ tty->termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
CLOCAL;
- tty->termios->c_ispeed = 9600;
- tty->termios->c_ospeed = 9600;
+ tty->termios.c_ispeed = 9600;
+ tty->termios.c_ospeed = 9600;
} else if (priv->chiptype == CT_CA42V2) {
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ tty->termios = tty_std_termios;
+ tty->termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
CLOCAL;
- tty->termios->c_ispeed = 9600;
- tty->termios->c_ospeed = 9600;
+ tty->termios.c_ispeed = 9600;
+ tty->termios.c_ospeed = 9600;
}
priv->termios_initialized = 1;
}
spin_unlock_irqrestore(&priv->lock, flags);
/* Unsupported features need clearing */
- tty->termios->c_cflag &= ~(CMSPAR|CRTSCTS);
+ tty->termios.c_cflag &= ~(CMSPAR|CRTSCTS);
- cflag = tty->termios->c_cflag;
- iflag = tty->termios->c_iflag;
+ cflag = tty->termios.c_cflag;
+ iflag = tty->termios.c_iflag;
/* check if there are new settings */
if (old_termios) {
spin_lock_irqsave(&priv->lock, flags);
- priv->tmp_termios = *(tty->termios);
+ priv->tmp_termios = tty->termios;
spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -1042,23 +940,21 @@ static void cypress_set_termios(struct tty_struct *tty,
data_bits = 3;
break;
default:
- dev_err(&port->dev, "%s - CSIZE was set, but not CS5-CS8\n",
- __func__);
+ dev_err(dev, "%s - CSIZE was set, but not CS5-CS8\n", __func__);
data_bits = 3;
}
spin_lock_irqsave(&priv->lock, flags);
oldlines = priv->line_control;
if ((cflag & CBAUD) == B0) {
/* drop dtr and rts */
- dbg("%s - dropping the lines, baud rate 0bps", __func__);
+ dev_dbg(dev, "%s - dropping the lines, baud rate 0bps\n", __func__);
priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
} else
priv->line_control = (CONTROL_DTR | CONTROL_RTS);
spin_unlock_irqrestore(&priv->lock, flags);
- dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, "
- "%d data_bits (+5)", __func__, stop_bits,
- parity_enable, parity_type, data_bits);
+ dev_dbg(dev, "%s - sending %d stop_bits, %d parity_enable, %d parity_type, %d data_bits (+5)\n",
+ __func__, stop_bits, parity_enable, parity_type, data_bits);
cypress_serial_control(tty, port, tty_get_baud_rate(tty),
data_bits, stop_bits,
@@ -1075,11 +971,10 @@ static void cypress_set_termios(struct tty_struct *tty,
spin_lock_irqsave(&priv->lock, flags);
if (priv->chiptype == CT_EARTHMATE && priv->baud_rate == 4800) {
- dbg("Using custom termios settings for a baud rate of "
- "4800bps.");
+ dev_dbg(dev, "Using custom termios settings for a baud rate of 4800bps.\n");
/* define custom termios settings for NMEA protocol */
- tty->termios->c_iflag /* input modes - */
+ tty->termios.c_iflag /* input modes - */
&= ~(IGNBRK /* disable ignore break */
| BRKINT /* disable break causes interrupt */
| PARMRK /* disable mark parity errors */
@@ -1089,10 +984,10 @@ static void cypress_set_termios(struct tty_struct *tty,
| ICRNL /* disable translate CR to NL */
| IXON); /* disable enable XON/XOFF flow control */
- tty->termios->c_oflag /* output modes */
+ tty->termios.c_oflag /* output modes */
&= ~OPOST; /* disable postprocess output char */
- tty->termios->c_lflag /* line discipline modes */
+ tty->termios.c_lflag /* line discipline modes */
&= ~(ECHO /* disable echo input characters */
| ECHONL /* disable echo new line */
| ICANON /* disable erase, kill, werase, and rprnt
@@ -1121,13 +1016,11 @@ static int cypress_chars_in_buffer(struct tty_struct *tty)
int chars = 0;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
chars = kfifo_len(&priv->write_fifo);
spin_unlock_irqrestore(&priv->lock, flags);
- dbg("%s - returns %d", __func__, chars);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
return chars;
}
@@ -1137,8 +1030,6 @@ static void cypress_throttle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irq(&priv->lock);
priv->rx_flags = THROTTLED;
spin_unlock_irq(&priv->lock);
@@ -1151,8 +1042,6 @@ static void cypress_unthrottle(struct tty_struct *tty)
struct cypress_private *priv = usb_get_serial_port_data(port);
int actually_throttled, result;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irq(&priv->lock);
actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
priv->rx_flags = 0;
@@ -1162,8 +1051,6 @@ static void cypress_unthrottle(struct tty_struct *tty)
return;
if (actually_throttled) {
- port->interrupt_in_urb->dev = port->serial->dev;
-
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result) {
dev_err(&port->dev, "%s - failed submitting read urb, "
@@ -1178,6 +1065,7 @@ static void cypress_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct cypress_private *priv = usb_get_serial_port_data(port);
+ struct device *dev = &urb->dev->dev;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
unsigned long flags;
@@ -1188,8 +1076,6 @@ static void cypress_read_int_callback(struct urb *urb)
int i = 0;
int status = urb->status;
- dbg("%s - port %d", __func__, port->number);
-
switch (status) {
case 0: /* success */
break;
@@ -1203,16 +1089,15 @@ static void cypress_read_int_callback(struct urb *urb)
/* FALLS THROUGH */
default:
/* something ugly is going on... */
- dev_err(&urb->dev->dev,
- "%s - unexpected nonzero read status received: %d\n",
- __func__, status);
+ dev_err(dev, "%s - unexpected nonzero read status received: %d\n",
+ __func__, status);
cypress_set_dead(port);
return;
}
spin_lock_irqsave(&priv->lock, flags);
if (priv->rx_flags & THROTTLED) {
- dbg("%s - now throttling", __func__);
+ dev_dbg(dev, "%s - now throttling\n", __func__);
priv->rx_flags |= ACTUALLY_THROTTLED;
spin_unlock_irqrestore(&priv->lock, flags);
return;
@@ -1221,7 +1106,7 @@ static void cypress_read_int_callback(struct urb *urb)
tty = tty_port_tty_get(&port->port);
if (!tty) {
- dbg("%s - bad tty pointer - exiting", __func__);
+ dev_dbg(dev, "%s - bad tty pointer - exiting\n", __func__);
return;
}
@@ -1248,29 +1133,41 @@ static void cypress_read_int_callback(struct urb *urb)
}
spin_unlock_irqrestore(&priv->lock, flags);
if (result < bytes) {
- dbg("%s - wrong packet size - received %d bytes but packet "
- "said %d bytes", __func__, result, bytes);
+ dev_dbg(dev,
+ "%s - wrong packet size - received %d bytes but packet said %d bytes\n",
+ __func__, result, bytes);
goto continue_read;
}
- usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, data);
+ usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
spin_lock_irqsave(&priv->lock, flags);
/* check to see if status has changed */
if (priv->current_status != priv->prev_status) {
- priv->diff_status |= priv->current_status ^
- priv->prev_status;
- wake_up_interruptible(&priv->delta_msr_wait);
+ u8 delta = priv->current_status ^ priv->prev_status;
+
+ if (delta & UART_MSR_MASK) {
+ if (delta & UART_CTS)
+ port->icount.cts++;
+ if (delta & UART_DSR)
+ port->icount.dsr++;
+ if (delta & UART_RI)
+ port->icount.rng++;
+ if (delta & UART_CD)
+ port->icount.dcd++;
+
+ wake_up_interruptible(&port->port.delta_msr_wait);
+ }
+
priv->prev_status = priv->current_status;
}
spin_unlock_irqrestore(&priv->lock, flags);
/* hangup, as defined in acm.c... this might be a bad place for it
* though */
- if (tty && !(tty->termios->c_cflag & CLOCAL) &&
+ if (tty && !(tty->termios.c_cflag & CLOCAL) &&
!(priv->current_status & UART_CD)) {
- dbg("%s - calling hangup", __func__);
+ dev_dbg(dev, "%s - calling hangup\n", __func__);
tty_hangup(tty);
goto continue_read;
}
@@ -1283,15 +1180,15 @@ static void cypress_read_int_callback(struct urb *urb)
if (priv->current_status & CYP_ERROR) {
spin_unlock_irqrestore(&priv->lock, flags);
tty_flag = TTY_PARITY;
- dbg("%s - Parity Error detected", __func__);
+ dev_dbg(dev, "%s - Parity Error detected\n", __func__);
} else
spin_unlock_irqrestore(&priv->lock, flags);
/* process read if there is data other than line status */
- if (tty && bytes > i) {
- tty_insert_flip_string_fixed_flag(tty, data + i,
+ if (bytes > i) {
+ tty_insert_flip_string_fixed_flag(&port->port, data + i,
tty_flag, bytes - i);
- tty_flip_buffer_push(tty);
+ tty_flip_buffer_push(&port->port);
}
spin_lock_irqsave(&priv->lock, flags);
@@ -1314,9 +1211,8 @@ continue_read:
priv->read_urb_interval);
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result && result != -EPERM) {
- dev_err(&urb->dev->dev, "%s - failed resubmitting "
- "read urb, error %d\n", __func__,
- result);
+ dev_err(dev, "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
cypress_set_dead(port);
}
}
@@ -1327,11 +1223,9 @@ static void cypress_write_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct cypress_private *priv = usb_get_serial_port_data(port);
- int result;
+ struct device *dev = &urb->dev->dev;
int status = urb->status;
- dbg("%s - port %d", __func__, port->number);
-
switch (status) {
case 0:
/* success */
@@ -1340,31 +1234,16 @@ static void cypress_write_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
priv->write_urb_in_use = 0;
return;
- case -EPIPE: /* no break needed; clear halt and resubmit */
- if (!priv->comm_is_ok)
- break;
- usb_clear_halt(port->serial->dev, 0x02);
- /* error in the urb, so we have to resubmit it */
- dbg("%s - nonzero write bulk status received: %d",
- __func__, status);
- port->interrupt_out_urb->transfer_buffer_length = 1;
- port->interrupt_out_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
- if (!result)
- return;
- dev_err(&urb->dev->dev,
- "%s - failed resubmitting write urb, error %d\n",
- __func__, result);
- cypress_set_dead(port);
- break;
+ case -EPIPE:
+ /* Cannot call usb_clear_halt while in_interrupt */
+ /* FALLTHROUGH */
default:
- dev_err(&urb->dev->dev,
- "%s - unexpected nonzero write status received: %d\n",
- __func__, status);
+ dev_err(dev, "%s - unexpected nonzero write status received: %d\n",
+ __func__, status);
cypress_set_dead(port);
break;
}
@@ -1374,66 +1253,12 @@ static void cypress_write_int_callback(struct urb *urb)
cypress_send(port);
}
-
-/*****************************************************************************
- * Module functions
- *****************************************************************************/
-
-static int __init cypress_init(void)
-{
- int retval;
-
- dbg("%s", __func__);
-
- retval = usb_serial_register(&cypress_earthmate_device);
- if (retval)
- goto failed_em_register;
- retval = usb_serial_register(&cypress_hidcom_device);
- if (retval)
- goto failed_hidcom_register;
- retval = usb_serial_register(&cypress_ca42v2_device);
- if (retval)
- goto failed_ca42v2_register;
- retval = usb_register(&cypress_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-
-failed_usb_register:
- usb_serial_deregister(&cypress_ca42v2_device);
-failed_ca42v2_register:
- usb_serial_deregister(&cypress_hidcom_device);
-failed_hidcom_register:
- usb_serial_deregister(&cypress_earthmate_device);
-failed_em_register:
- return retval;
-}
-
-
-static void __exit cypress_exit(void)
-{
- dbg("%s", __func__);
-
- usb_deregister(&cypress_driver);
- usb_serial_deregister(&cypress_earthmate_device);
- usb_serial_deregister(&cypress_hidcom_device);
- usb_serial_deregister(&cypress_ca42v2_device);
-}
-
-
-module_init(cypress_init);
-module_exit(cypress_exit);
+module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
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, "Enable statistics or not");
module_param(interval, int, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/cypress_m8.h b/drivers/usb/serial/cypress_m8.h
index 67cf6082688..119d2e17077 100644
--- a/drivers/usb/serial/cypress_m8.h
+++ b/drivers/usb/serial/cypress_m8.h
@@ -24,6 +24,10 @@
#define VENDOR_ID_CYPRESS 0x04b4
#define PRODUCT_ID_CYPHIDCOM 0x5500
+/* FRWD Dongle - a GPS sports watch */
+#define VENDOR_ID_FRWD 0x6737
+#define PRODUCT_ID_CYPHIDCOM_FRWD 0x0001
+
/* Powercom UPS, chip CY7C63723 */
#define VENDOR_ID_POWERCOM 0x0d9f
#define PRODUCT_ID_UPS 0x0002
@@ -51,19 +55,23 @@
#define CT_GENERIC 0x0F
/* End of chiptype definitions */
-/* RS-232 serial data communication protocol definitions */
-/* these are sent / read at byte 0 of the input/output hid reports */
-/* You can find these values defined in the CY4601 USB to Serial design notes */
-
-#define CONTROL_DTR 0x20 /* data terminal ready - flow control - host to device */
-#define UART_DSR 0x20 /* data set ready - flow control - device to host */
-#define CONTROL_RTS 0x10 /* request to send - flow control - host to device */
-#define UART_CTS 0x10 /* clear to send - flow control - device to host */
-#define UART_RI 0x10 /* ring indicator - modem - device to host */
-#define UART_CD 0x40 /* carrier detect - modem - device to host */
-#define CYP_ERROR 0x08 /* received from input report - device to host */
-/* Note - the below has nothing to do with the "feature report" reset */
-#define CONTROL_RESET 0x08 /* sent with output report - host to device */
+/*
+ * RS-232 serial data communication protocol definitions.
+ *
+ * These are sent / read at byte 0 of the input/output hid reports.
+ * You can find these values defined in the CY4601 USB to Serial design notes.
+ */
+
+#define CONTROL_DTR 0x20 /* data terminal ready */
+#define CONTROL_RTS 0x10 /* request to send */
+#define CONTROL_RESET 0x08 /* sent with output report */
+
+#define UART_MSR_MASK 0xf0
+#define UART_RI 0x80 /* ring indicator */
+#define UART_CD 0x40 /* carrier detect */
+#define UART_DSR 0x20 /* data set ready */
+#define UART_CTS 0x10 /* clear to send */
+#define CYP_ERROR 0x08 /* received from input report */
/* End of RS-232 protocol definitions */
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index b92070c103c..8a23c53b946 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -13,227 +13,10 @@
*
* Peter Berger (pberger@brimson.com)
* Al Borchers (borchers@steinerpoint.com)
-*
-* (12/03/2001) gkh
-* switched to using port->port.count instead of private version.
-* Removed port->active
-*
-* (04/08/2001) gb
-* Identify version on module load.
-*
-* (11/01/2000) Adam J. Richter
-* usb_device_id table support
-*
-* (11/01/2000) pberger and borchers
-* -- Turned off the USB_DISABLE_SPD flag for write bulk urbs--it caused
-* USB 4 ports to hang on startup.
-* -- Serialized access to write urbs by adding the dp_write_urb_in_use
-* flag; otherwise, the driver caused SMP system hangs. Watching the
-* urb status is not sufficient.
-*
-* (10/05/2000) gkh
-* -- Fixed bug with urb->dev not being set properly, now that the usb
-* core needs it.
-*
-* (8/8/2000) pberger and borchers
-* -- Fixed close so that
-* - it can timeout while waiting for transmit idle, if needed;
-* - it ignores interrupts when flushing the port, turning
-* of modem signalling, and so on;
-* - it waits for the flush to really complete before returning.
-* -- Read_bulk_callback and write_bulk_callback check for a closed
-* port before using the tty struct or writing to the port.
-* -- The two changes above fix the oops caused by interrupted closes.
-* -- Added interruptible args to write_oob_command and set_modem_signals
-* and added a timeout arg to transmit_idle; needed for fixes to
-* close.
-* -- Added code for rx_throttle and rx_unthrottle so that input flow
-* control works.
-* -- Added code to set overrun, parity, framing, and break errors
-* (untested).
-* -- Set USB_DISABLE_SPD flag for write bulk urbs, so no 0 length
-* bulk writes are done. These hung the Digi USB device. The
-* 0 length bulk writes were a new feature of usb-uhci added in
-* the 2.4.0-test6 kernels.
-* -- Fixed mod inc race in open; do mod inc before sleeping to wait
-* for a close to finish.
-*
-* (7/31/2000) pberger
-* -- Fixed bugs with hardware handshaking:
-* - Added code to set/clear tty->hw_stopped in digi_read_oob_callback()
-* and digi_set_termios()
-* -- Added code in digi_set_termios() to
-* - add conditional in code handling transition from B0 to only
-* set RTS if RTS/CTS flow control is either not in use or if
-* the port is not currently throttled.
-* - handle turning off CRTSCTS.
-*
-* (7/30/2000) borchers
-* -- Added support for more than one Digi USB device by moving
-* globals to a private structure in the pointed to from the
-* usb_serial structure.
-* -- Moved the modem change and transmit idle wait queues into
-* the port private structure, so each port has its own queue
-* rather than sharing global queues.
-* -- Added support for break signals.
-*
-* (7/25/2000) pberger
-* -- Added USB-2 support. Note: the USB-2 supports 3 devices: two
-* serial and a parallel port. The parallel port is implemented
-* as a serial-to-parallel converter. That is, the driver actually
-* presents all three USB-2 interfaces as serial ports, but the third
-* one physically connects to a parallel device. Thus, for example,
-* one could plug a parallel printer into the USB-2's third port,
-* but from the kernel's (and userland's) point of view what's
-* actually out there is a serial device.
-*
-* (7/15/2000) borchers
-* -- Fixed race in open when a close is in progress.
-* -- Keep count of opens and dec the module use count for each
-* outstanding open when shutdown is called (on disconnect).
-* -- Fixed sanity checks in read_bulk_callback and write_bulk_callback
-* so pointers are checked before use.
-* -- Split read bulk callback into in band and out of band
-* callbacks, and no longer restart read chains if there is
-* a status error or a sanity error. This fixed the seg
-* faults and other errors we used to get on disconnect.
-* -- Port->active is once again a flag as usb-serial intended it
-* to be, not a count. Since it was only a char it would
-* have been limited to 256 simultaneous opens. Now the open
-* count is kept in the port private structure in dp_open_count.
-* -- Added code for modularization of the digi_acceleport driver.
-*
-* (6/27/2000) pberger and borchers
-* -- Zeroed out sync field in the wakeup_task before first use;
-* otherwise the uninitialized value might prevent the task from
-* being scheduled.
-* -- Initialized ret value to 0 in write_bulk_callback, otherwise
-* the uninitialized value could cause a spurious debugging message.
-*
-* (6/22/2000) pberger and borchers
-* -- Made cond_wait_... inline--apparently on SPARC the flags arg
-* to spin_lock_irqsave cannot be passed to another function
-* to call spin_unlock_irqrestore. Thanks to Pauline Middelink.
-* -- In digi_set_modem_signals the inner nested spin locks use just
-* spin_lock() rather than spin_lock_irqsave(). The old code
-* mistakenly left interrupts off. Thanks to Pauline Middelink.
-* -- copy_from_user (which can sleep) is no longer called while a
-* spinlock is held. We copy to a local buffer before getting
-* the spinlock--don't like the extra copy but the code is simpler.
-* -- Printk and dbg are no longer called while a spin lock is held.
-*
-* (6/4/2000) pberger and borchers
-* -- Replaced separate calls to spin_unlock_irqrestore and
-* interruptible_sleep_on_timeout with a new function
-* cond_wait_interruptible_timeout_irqrestore. This eliminates
-* the race condition where the wake up could happen after
-* the unlock and before the sleep.
-* -- Close now waits for output to drain.
-* -- Open waits until any close in progress is finished.
-* -- All out of band responses are now processed, not just the
-* first in a USB packet.
-* -- Fixed a bug that prevented the driver from working when the
-* first Digi port was not the first USB serial port--the driver
-* was mistakenly using the external USB serial port number to
-* try to index into its internal ports.
-* -- Fixed an SMP bug -- write_bulk_callback is called directly from
-* an interrupt, so spin_lock_irqsave/spin_unlock_irqrestore are
-* needed for locks outside write_bulk_callback that are also
-* acquired by write_bulk_callback to prevent deadlocks.
-* -- Fixed support for select() by making digi_chars_in_buffer()
-* return 256 when -EINPROGRESS is set, as the line discipline
-* code in n_tty.c expects.
-* -- Fixed an include file ordering problem that prevented debugging
-* messages from working.
-* -- Fixed an intermittent timeout problem that caused writes to
-* sometimes get stuck on some machines on some kernels. It turns
-* out in these circumstances write_chan() (in n_tty.c) was
-* asleep waiting for our wakeup call. Even though we call
-* wake_up_interruptible() in digi_write_bulk_callback(), there is
-* a race condition that could cause the wakeup to fail: if our
-* wake_up_interruptible() call occurs between the time that our
-* driver write routine finishes and write_chan() sets current->state
-* to TASK_INTERRUPTIBLE, the effect of our wakeup setting the state
-* to TASK_RUNNING will be lost and write_chan's subsequent call to
-* schedule() will never return (unless it catches a signal).
-* This race condition occurs because write_bulk_callback() (and thus
-* the wakeup) are called asynchronously from an interrupt, rather than
-* from the scheduler. We can avoid the race by calling the wakeup
-* from the scheduler queue and that's our fix: Now, at the end of
-* write_bulk_callback() we queue up a wakeup call on the scheduler
-* task queue. We still also invoke the wakeup directly since that
-* squeezes a bit more performance out of the driver, and any lost
-* race conditions will get cleaned up at the next scheduler run.
-*
-* NOTE: The problem also goes away if you comment out
-* the two code lines in write_chan() where current->state
-* is set to TASK_RUNNING just before calling driver.write() and to
-* TASK_INTERRUPTIBLE immediately afterwards. This is why the
-* problem did not show up with the 2.2 kernels -- they do not
-* include that code.
-*
-* (5/16/2000) pberger and borchers
-* -- Added timeouts to sleeps, to defend against lost wake ups.
-* -- Handle transition to/from B0 baud rate in digi_set_termios.
-*
-* (5/13/2000) pberger and borchers
-* -- All commands now sent on out of band port, using
-* digi_write_oob_command.
-* -- Get modem control signals whenever they change, support TIOCMGET/
-* SET/BIS/BIC ioctls.
-* -- digi_set_termios now supports parity, word size, stop bits, and
-* receive enable.
-* -- Cleaned up open and close, use digi_set_termios and
-* digi_write_oob_command to set port parameters.
-* -- Added digi_startup_device to start read chains on all ports.
-* -- Write buffer is only used when count==1, to be sure put_char can
-* write a char (unless the buffer is full).
-*
-* (5/10/2000) pberger and borchers
-* -- Added MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT calls on open/close.
-* -- Fixed problem where the first incoming character is lost on
-* port opens after the first close on that port. Now we keep
-* the read_urb chain open until shutdown.
-* -- Added more port conditioning calls in digi_open and digi_close.
-* -- Convert port->active to a use count so that we can deal with multiple
-* opens and closes properly.
-* -- Fixed some problems with the locking code.
-*
-* (5/3/2000) pberger and borchers
-* -- First alpha version of the driver--many known limitations and bugs.
-*
-*
-* Locking and SMP
-*
-* - Each port, including the out-of-band port, has a lock used to
-* serialize all access to the port's private structure.
-* - The port lock is also used to serialize all writes and access to
-* the port's URB.
-* - The port lock is also used for the port write_wait condition
-* variable. Holding the port lock will prevent a wake up on the
-* port's write_wait; this can be used with cond_wait_... to be sure
-* the wake up is not lost in a race when dropping the lock and
-* sleeping waiting for the wakeup.
-* - digi_write() does not sleep, since it is sometimes called on
-* interrupt time.
-* - digi_write_bulk_callback() and digi_read_bulk_callback() are
-* called directly from interrupts. Hence spin_lock_irqsave()
-* and spin_unlock_irqrestore() are used in the rest of the code
-* for any locks they acquire.
-* - digi_write_bulk_callback() gets the port lock before waking up
-* processes sleeping on the port write_wait. It also schedules
-* wake ups so they happen from the scheduler, because the tty
-* system can miss wake ups from interrupts.
-* - All sleeps use a timeout of DIGI_RETRY_TIMEOUT before looping to
-* recheck the condition they are sleeping on. This is defensive,
-* in case a wake up is lost.
-* - Following Documentation/DocBook/kernel-locking.pdf no spin locks
-* are held when calling copy_to/from_user or printk.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -248,10 +31,6 @@
/* Defines */
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.80.1.2"
#define DRIVER_AUTHOR "Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>"
#define DRIVER_DESC "Digi AccelePort USB-2/USB-4 Serial Converter driver"
@@ -416,7 +195,6 @@ struct digi_port {
unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE];
int dp_write_urb_in_use;
unsigned int dp_modem_signals;
- wait_queue_head_t dp_modem_change_wait;
int dp_transmit_idle;
wait_queue_head_t dp_transmit_idle_wait;
int dp_throttled;
@@ -430,7 +208,6 @@ struct digi_port {
/* Local Function Declarations */
-static void digi_wakeup_write(struct usb_serial_port *port);
static void digi_wakeup_write_lock(struct work_struct *work);
static int digi_write_oob_command(struct usb_serial_port *port,
unsigned char *buf, int count, int interruptible);
@@ -445,31 +222,28 @@ static void digi_rx_unthrottle(struct tty_struct *tty);
static void digi_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios);
static void digi_break_ctl(struct tty_struct *tty, int break_state);
-static int digi_tiocmget(struct tty_struct *tty, struct file *file);
-static int digi_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear);
+static int digi_tiocmget(struct tty_struct *tty);
+static int digi_tiocmset(struct tty_struct *tty, unsigned int set,
+ unsigned int clear);
static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
- const unsigned char *buf, int count);
+ const unsigned char *buf, int count);
static void digi_write_bulk_callback(struct urb *urb);
static int digi_write_room(struct tty_struct *tty);
static int digi_chars_in_buffer(struct tty_struct *tty);
static int digi_open(struct tty_struct *tty, struct usb_serial_port *port);
static void digi_close(struct usb_serial_port *port);
-static int digi_carrier_raised(struct usb_serial_port *port);
static void digi_dtr_rts(struct usb_serial_port *port, int on);
static int digi_startup_device(struct usb_serial *serial);
static int digi_startup(struct usb_serial *serial);
static void digi_disconnect(struct usb_serial *serial);
static void digi_release(struct usb_serial *serial);
+static int digi_port_probe(struct usb_serial_port *port);
+static int digi_port_remove(struct usb_serial_port *port);
static void digi_read_bulk_callback(struct urb *urb);
static int digi_read_inb_callback(struct urb *urb);
static int digi_read_oob_callback(struct urb *urb);
-/* Statics */
-
-static int debug;
-
static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(DIGI_VENDOR_ID, DIGI_2_ID) },
{ USB_DEVICE(DIGI_VENDOR_ID, DIGI_4_ID) },
@@ -488,15 +262,6 @@ static const struct usb_device_id id_table_4[] = {
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver digi_driver = {
- .name = "digi_acceleport",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
- .no_dynamic_id = 1,
-};
-
-
/* device info needed for the Digi serial converter */
static struct usb_serial_driver digi_acceleport_2_device = {
@@ -505,13 +270,11 @@ static struct usb_serial_driver digi_acceleport_2_device = {
.name = "digi_2",
},
.description = "Digi 2 port USB adapter",
- .usb_driver = &digi_driver,
.id_table = id_table_2,
.num_ports = 3,
.open = digi_open,
.close = digi_close,
.dtr_rts = digi_dtr_rts,
- .carrier_raised = digi_carrier_raised,
.write = digi_write,
.write_room = digi_write_room,
.write_bulk_callback = digi_write_bulk_callback,
@@ -526,6 +289,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
.attach = digi_startup,
.disconnect = digi_disconnect,
.release = digi_release,
+ .port_probe = digi_port_probe,
+ .port_remove = digi_port_remove,
};
static struct usb_serial_driver digi_acceleport_4_device = {
@@ -534,7 +299,6 @@ static struct usb_serial_driver digi_acceleport_4_device = {
.name = "digi_4",
},
.description = "Digi 4 port USB adapter",
- .usb_driver = &digi_driver,
.id_table = id_table_4,
.num_ports = 4,
.open = digi_open,
@@ -553,8 +317,13 @@ static struct usb_serial_driver digi_acceleport_4_device = {
.attach = digi_startup,
.disconnect = digi_disconnect,
.release = digi_release,
+ .port_probe = digi_port_probe,
+ .port_remove = digi_port_remove,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &digi_acceleport_2_device, &digi_acceleport_4_device, NULL
+};
/* Functions */
@@ -602,20 +371,10 @@ static void digi_wakeup_write_lock(struct work_struct *work)
unsigned long flags;
spin_lock_irqsave(&priv->dp_port_lock, flags);
- digi_wakeup_write(port);
+ tty_port_tty_wakeup(&port->port);
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
}
-static void digi_wakeup_write(struct usb_serial_port *port)
-{
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- if (tty) {
- tty_wakeup(tty);
- tty_kref_put(tty);
- }
-}
-
-
/*
* Digi Write OOB Command
*
@@ -630,14 +389,15 @@ static void digi_wakeup_write(struct usb_serial_port *port)
static int digi_write_oob_command(struct usb_serial_port *port,
unsigned char *buf, int count, int interruptible)
{
-
int ret = 0;
int len;
struct usb_serial_port *oob_port = (struct usb_serial_port *)((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port;
struct digi_port *oob_priv = usb_get_serial_port_data(oob_port);
unsigned long flags = 0;
- dbg("digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, count);
+ dev_dbg(&port->dev,
+ "digi_write_oob_command: TOP: port=%d, count=%d\n",
+ oob_priv->dp_port_num, count);
spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
while (count > 0) {
@@ -656,7 +416,6 @@ static int digi_write_oob_command(struct usb_serial_port *port,
len &= ~3;
memcpy(oob_port->write_urb->transfer_buffer, buf, len);
oob_port->write_urb->transfer_buffer_length = len;
- oob_port->write_urb->dev = port->serial->dev;
ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC);
if (ret == 0) {
oob_priv->dp_write_urb_in_use = 1;
@@ -694,7 +453,7 @@ static int digi_write_inb_command(struct usb_serial_port *port,
unsigned char *data = port->write_urb->transfer_buffer;
unsigned long flags = 0;
- dbg("digi_write_inb_command: TOP: port=%d, count=%d",
+ dev_dbg(&port->dev, "digi_write_inb_command: TOP: port=%d, count=%d\n",
priv->dp_port_num, count);
if (timeout)
@@ -734,7 +493,6 @@ static int digi_write_inb_command(struct usb_serial_port *port,
memcpy(data, buf, len);
port->write_urb->transfer_buffer_length = len;
}
- port->write_urb->dev = port->serial->dev;
ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (ret == 0) {
@@ -777,7 +535,8 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
unsigned long flags = 0;
- dbg("digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x",
+ dev_dbg(&port->dev,
+ "digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x\n",
port_priv->dp_port_num, modem_signals);
spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
@@ -805,7 +564,6 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
data[7] = 0;
oob_port->write_urb->transfer_buffer_length = 8;
- oob_port->write_urb->dev = port->serial->dev;
ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC);
if (ret == 0) {
@@ -878,9 +636,6 @@ static void digi_rx_throttle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
-
- dbg("digi_rx_throttle: TOP: port=%d", priv->dp_port_num);
-
/* stop receiving characters by not resubmitting the read urb */
spin_lock_irqsave(&priv->dp_port_lock, flags);
priv->dp_throttled = 1;
@@ -896,15 +651,11 @@ static void digi_rx_unthrottle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
- dbg("digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num);
-
spin_lock_irqsave(&priv->dp_port_lock, flags);
/* restart read chain */
- if (priv->dp_throttle_restart) {
- port->read_urb->dev = port->serial->dev;
+ if (priv->dp_throttle_restart)
ret = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- }
/* turn throttle off */
priv->dp_throttled = 0;
@@ -923,8 +674,9 @@ static void digi_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
struct digi_port *priv = usb_get_serial_port_data(port);
- unsigned int iflag = tty->termios->c_iflag;
- unsigned int cflag = tty->termios->c_cflag;
+ struct device *dev = &port->dev;
+ unsigned int iflag = tty->termios.c_iflag;
+ unsigned int cflag = tty->termios.c_cflag;
unsigned int old_iflag = old_termios->c_iflag;
unsigned int old_cflag = old_termios->c_cflag;
unsigned char buf[32];
@@ -933,7 +685,9 @@ static void digi_set_termios(struct tty_struct *tty,
int i = 0;
speed_t baud;
- dbg("digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", priv->dp_port_num, iflag, old_iflag, cflag, old_cflag);
+ dev_dbg(dev,
+ "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x\n",
+ priv->dp_port_num, iflag, old_iflag, cflag, old_cflag);
/* set baud rate */
baud = tty_get_baud_rate(tty);
@@ -945,7 +699,7 @@ static void digi_set_termios(struct tty_struct *tty,
/* don't set RTS if using hardware flow control */
/* and throttling input */
modem_signals = TIOCM_DTR;
- if (!(tty->termios->c_cflag & CRTSCTS) ||
+ if (!(tty->termios.c_cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &tty->flags))
modem_signals |= TIOCM_RTS;
digi_set_modem_signals(port, modem_signals, 1);
@@ -984,7 +738,7 @@ static void digi_set_termios(struct tty_struct *tty,
}
}
/* set parity */
- tty->termios->c_cflag &= ~CMSPAR;
+ tty->termios.c_cflag &= ~CMSPAR;
if ((cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD))) {
if (cflag&PARENB) {
@@ -1009,7 +763,8 @@ static void digi_set_termios(struct tty_struct *tty,
case CS7: arg = DIGI_WORD_SIZE_7; break;
case CS8: arg = DIGI_WORD_SIZE_8; break;
default:
- dbg("digi_set_termios: can't handle word size %d",
+ dev_dbg(dev,
+ "digi_set_termios: can't handle word size %d\n",
(cflag&CSIZE));
break;
}
@@ -1102,7 +857,7 @@ static void digi_set_termios(struct tty_struct *tty,
}
ret = digi_write_oob_command(port, buf, i, 1);
if (ret != 0)
- dbg("digi_set_termios: write oob failed, ret=%d", ret);
+ dev_dbg(dev, "digi_set_termios: write oob failed, ret=%d\n", ret);
tty_encode_baud_rate(tty, baud, baud);
}
@@ -1120,15 +875,13 @@ static void digi_break_ctl(struct tty_struct *tty, int break_state)
}
-static int digi_tiocmget(struct tty_struct *tty, struct file *file)
+static int digi_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int val;
unsigned long flags;
- dbg("%s: TOP: port=%d", __func__, priv->dp_port_num);
-
spin_lock_irqsave(&priv->dp_port_lock, flags);
val = priv->dp_modem_signals;
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
@@ -1136,16 +889,14 @@ static int digi_tiocmget(struct tty_struct *tty, struct file *file)
}
-static int digi_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
+static int digi_tiocmset(struct tty_struct *tty,
+ unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int val;
unsigned long flags;
- dbg("%s: TOP: port=%d", __func__, priv->dp_port_num);
-
spin_lock_irqsave(&priv->dp_port_lock, flags);
val = (priv->dp_modem_signals & ~clear) | set;
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
@@ -1162,7 +913,8 @@ static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
unsigned char *data = port->write_urb->transfer_buffer;
unsigned long flags = 0;
- dbg("digi_write: TOP: port=%d, count=%d, in_interrupt=%ld",
+ dev_dbg(&port->dev,
+ "digi_write: TOP: port=%d, count=%d, in_interrupt=%ld\n",
priv->dp_port_num, count, in_interrupt());
/* copy user data (which can sleep) before getting spin lock */
@@ -1197,7 +949,6 @@ static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
}
port->write_urb->transfer_buffer_length = data_len+2;
- port->write_urb->dev = port->serial->dev;
*data++ = DIGI_CMD_SEND_DATA;
*data++ = data_len;
@@ -1219,10 +970,10 @@ static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
/* return length of new data written, or error */
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
if (ret < 0)
- dev_err(&port->dev,
+ dev_err_console(port,
"%s: usb_submit_urb failed, ret=%d, port=%d\n",
__func__, ret, priv->dp_port_num);
- dbg("digi_write: returning %d", ret);
+ dev_dbg(&port->dev, "digi_write: returning %d\n", ret);
return ret;
}
@@ -1237,8 +988,6 @@ static void digi_write_bulk_callback(struct urb *urb)
int ret = 0;
int status = urb->status;
- dbg("digi_write_bulk_callback: TOP, status=%d", status);
-
/* port and serial sanity check */
if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
pr_err("%s: port or port->private is NULL, status=%d\n",
@@ -1255,7 +1004,7 @@ static void digi_write_bulk_callback(struct urb *urb)
/* handle oob callback */
if (priv->dp_port_num == serial_priv->ds_oob_port_num) {
- dbg("digi_write_bulk_callback: oob callback");
+ dev_dbg(&port->dev, "digi_write_bulk_callback: oob callback\n");
spin_lock(&priv->dp_port_lock);
priv->dp_write_urb_in_use = 0;
wake_up_interruptible(&port->write_wait);
@@ -1273,7 +1022,6 @@ static void digi_write_bulk_callback(struct urb *urb)
= (unsigned char)priv->dp_out_buf_len;
port->write_urb->transfer_buffer_length =
priv->dp_out_buf_len + 2;
- port->write_urb->dev = serial->dev;
memcpy(port->write_urb->transfer_buffer + 2, priv->dp_out_buf,
priv->dp_out_buf_len);
ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
@@ -1283,14 +1031,14 @@ static void digi_write_bulk_callback(struct urb *urb)
}
}
/* wake up processes sleeping on writes immediately */
- digi_wakeup_write(port);
+ tty_port_tty_wakeup(&port->port);
/* also queue up a wakeup at scheduler time, in case we */
/* lost the race in write_chan(). */
schedule_work(&priv->dp_wakeup_work);
spin_unlock(&priv->dp_port_lock);
if (ret && ret != -EPERM)
- dev_err(&port->dev,
+ dev_err_console(port,
"%s: usb_submit_urb failed, ret=%d, port=%d\n",
__func__, ret, priv->dp_port_num);
}
@@ -1310,7 +1058,7 @@ static int digi_write_room(struct tty_struct *tty)
room = port->bulk_out_size - 2 - priv->dp_out_buf_len;
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
- dbg("digi_write_room: port=%d, room=%d", priv->dp_port_num, room);
+ dev_dbg(&port->dev, "digi_write_room: port=%d, room=%d\n", priv->dp_port_num, room);
return room;
}
@@ -1321,12 +1069,12 @@ static int digi_chars_in_buffer(struct tty_struct *tty)
struct digi_port *priv = usb_get_serial_port_data(port);
if (priv->dp_write_urb_in_use) {
- dbg("digi_chars_in_buffer: port=%d, chars=%d",
+ dev_dbg(&port->dev, "digi_chars_in_buffer: port=%d, chars=%d\n",
priv->dp_port_num, port->bulk_out_size - 2);
/* return(port->bulk_out_size - 2); */
return 256;
} else {
- dbg("digi_chars_in_buffer: port=%d, chars=%d",
+ dev_dbg(&port->dev, "digi_chars_in_buffer: port=%d, chars=%d\n",
priv->dp_port_num, priv->dp_out_buf_len);
return priv->dp_out_buf_len;
}
@@ -1339,14 +1087,6 @@ static void digi_dtr_rts(struct usb_serial_port *port, int on)
digi_set_modem_signals(port, on * (TIOCM_DTR|TIOCM_RTS), 1);
}
-static int digi_carrier_raised(struct usb_serial_port *port)
-{
- struct digi_port *priv = usb_get_serial_port_data(port);
- if (priv->dp_modem_signals & TIOCM_CD)
- return 1;
- return 0;
-}
-
static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
{
int ret;
@@ -1354,8 +1094,6 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
struct digi_port *priv = usb_get_serial_port_data(port);
struct ktermios not_termios;
- dbg("digi_open: TOP: port=%d", priv->dp_port_num);
-
/* be sure the device is started up */
if (digi_startup_device(port->serial) != 0)
return -ENXIO;
@@ -1374,12 +1112,12 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
ret = digi_write_oob_command(port, buf, 8, 1);
if (ret != 0)
- dbg("digi_open: write oob failed, ret=%d", ret);
+ dev_dbg(&port->dev, "digi_open: write oob failed, ret=%d\n", ret);
/* set termios settings */
if (tty) {
- not_termios.c_cflag = ~tty->termios->c_cflag;
- not_termios.c_iflag = ~tty->termios->c_iflag;
+ not_termios.c_cflag = ~tty->termios.c_cflag;
+ not_termios.c_iflag = ~tty->termios.c_iflag;
digi_set_termios(tty, port, &not_termios);
}
return 0;
@@ -1393,67 +1131,62 @@ static void digi_close(struct usb_serial_port *port)
unsigned char buf[32];
struct digi_port *priv = usb_get_serial_port_data(port);
- dbg("digi_close: TOP: port=%d", priv->dp_port_num);
-
mutex_lock(&port->serial->disc_mutex);
/* if disconnected, just clear flags */
if (port->serial->disconnected)
goto exit;
- if (port->serial->dev) {
- /* FIXME: Transmit idle belongs in the wait_unti_sent path */
- digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
-
- /* disable input flow control */
- buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
- buf[1] = priv->dp_port_num;
- buf[2] = DIGI_DISABLE;
- buf[3] = 0;
-
- /* disable output flow control */
- buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
- buf[5] = priv->dp_port_num;
- buf[6] = DIGI_DISABLE;
- buf[7] = 0;
-
- /* disable reading modem signals automatically */
- buf[8] = DIGI_CMD_READ_INPUT_SIGNALS;
- buf[9] = priv->dp_port_num;
- buf[10] = DIGI_DISABLE;
- buf[11] = 0;
-
- /* disable receive */
- buf[12] = DIGI_CMD_RECEIVE_ENABLE;
- buf[13] = priv->dp_port_num;
- buf[14] = DIGI_DISABLE;
- buf[15] = 0;
-
- /* flush fifos */
- buf[16] = DIGI_CMD_IFLUSH_FIFO;
- buf[17] = priv->dp_port_num;
- buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
- buf[19] = 0;
-
- ret = digi_write_oob_command(port, buf, 20, 0);
- if (ret != 0)
- dbg("digi_close: write oob failed, ret=%d", ret);
-
- /* wait for final commands on oob port to complete */
- prepare_to_wait(&priv->dp_flush_wait, &wait,
- TASK_INTERRUPTIBLE);
- schedule_timeout(DIGI_CLOSE_TIMEOUT);
- finish_wait(&priv->dp_flush_wait, &wait);
-
- /* shutdown any outstanding bulk writes */
- usb_kill_urb(port->write_urb);
- }
+ /* FIXME: Transmit idle belongs in the wait_unti_sent path */
+ digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
+
+ /* disable input flow control */
+ buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
+ buf[1] = priv->dp_port_num;
+ buf[2] = DIGI_DISABLE;
+ buf[3] = 0;
+
+ /* disable output flow control */
+ buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
+ buf[5] = priv->dp_port_num;
+ buf[6] = DIGI_DISABLE;
+ buf[7] = 0;
+
+ /* disable reading modem signals automatically */
+ buf[8] = DIGI_CMD_READ_INPUT_SIGNALS;
+ buf[9] = priv->dp_port_num;
+ buf[10] = DIGI_DISABLE;
+ buf[11] = 0;
+
+ /* disable receive */
+ buf[12] = DIGI_CMD_RECEIVE_ENABLE;
+ buf[13] = priv->dp_port_num;
+ buf[14] = DIGI_DISABLE;
+ buf[15] = 0;
+
+ /* flush fifos */
+ buf[16] = DIGI_CMD_IFLUSH_FIFO;
+ buf[17] = priv->dp_port_num;
+ buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
+ buf[19] = 0;
+
+ ret = digi_write_oob_command(port, buf, 20, 0);
+ if (ret != 0)
+ dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n",
+ ret);
+ /* wait for final commands on oob port to complete */
+ prepare_to_wait(&priv->dp_flush_wait, &wait,
+ TASK_INTERRUPTIBLE);
+ schedule_timeout(DIGI_CLOSE_TIMEOUT);
+ finish_wait(&priv->dp_flush_wait, &wait);
+
+ /* shutdown any outstanding bulk writes */
+ usb_kill_urb(port->write_urb);
exit:
spin_lock_irq(&priv->dp_port_lock);
priv->dp_write_urb_in_use = 0;
wake_up_interruptible(&priv->dp_close_wait);
spin_unlock_irq(&priv->dp_port_lock);
mutex_unlock(&port->serial->disc_mutex);
- dbg("digi_close: done");
}
@@ -1483,7 +1216,6 @@ static int digi_startup_device(struct usb_serial *serial)
/* set USB_DISABLE_SPD flag for write bulk urbs */
for (i = 0; i < serial->type->num_ports + 1; i++) {
port = serial->port[i];
- port->write_urb->dev = port->serial->dev;
ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (ret != 0) {
dev_err(&port->dev,
@@ -1495,61 +1227,49 @@ static int digi_startup_device(struct usb_serial *serial)
return ret;
}
-
-static int digi_startup(struct usb_serial *serial)
+static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
{
-
- int i;
struct digi_port *priv;
- struct digi_serial *serial_priv;
- dbg("digi_startup: TOP");
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
- /* allocate the private data structures for all ports */
- /* number of regular ports + 1 for the out-of-band port */
- for (i = 0; i < serial->type->num_ports + 1; i++) {
- /* allocate port private structure */
- priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL);
- if (priv == NULL) {
- while (--i >= 0)
- kfree(usb_get_serial_port_data(serial->port[i]));
- return 1; /* error */
- }
+ spin_lock_init(&priv->dp_port_lock);
+ priv->dp_port_num = port_num;
+ init_waitqueue_head(&priv->dp_transmit_idle_wait);
+ init_waitqueue_head(&priv->dp_flush_wait);
+ init_waitqueue_head(&priv->dp_close_wait);
+ INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
+ priv->dp_port = port;
- /* initialize port private structure */
- spin_lock_init(&priv->dp_port_lock);
- priv->dp_port_num = i;
- priv->dp_out_buf_len = 0;
- priv->dp_write_urb_in_use = 0;
- priv->dp_modem_signals = 0;
- init_waitqueue_head(&priv->dp_modem_change_wait);
- priv->dp_transmit_idle = 0;
- init_waitqueue_head(&priv->dp_transmit_idle_wait);
- priv->dp_throttled = 0;
- priv->dp_throttle_restart = 0;
- init_waitqueue_head(&priv->dp_flush_wait);
- init_waitqueue_head(&priv->dp_close_wait);
- INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
- priv->dp_port = serial->port[i];
- /* initialize write wait queue for this port */
- init_waitqueue_head(&serial->port[i]->write_wait);
-
- usb_set_serial_port_data(serial->port[i], priv);
- }
+ init_waitqueue_head(&port->write_wait);
- /* allocate serial private structure */
- serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL);
- if (serial_priv == NULL) {
- for (i = 0; i < serial->type->num_ports + 1; i++)
- kfree(usb_get_serial_port_data(serial->port[i]));
- return 1; /* error */
- }
+ usb_set_serial_port_data(port, priv);
+
+ return 0;
+}
+
+static int digi_startup(struct usb_serial *serial)
+{
+ struct digi_serial *serial_priv;
+ int ret;
+
+ serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
+ if (!serial_priv)
+ return -ENOMEM;
- /* initialize serial private structure */
spin_lock_init(&serial_priv->ds_serial_lock);
serial_priv->ds_oob_port_num = serial->type->num_ports;
serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
- serial_priv->ds_device_started = 0;
+
+ ret = digi_port_init(serial_priv->ds_oob_port,
+ serial_priv->ds_oob_port_num);
+ if (ret) {
+ kfree(serial_priv);
+ return ret;
+ }
+
usb_set_serial_data(serial, serial_priv);
return 0;
@@ -1559,7 +1279,6 @@ static int digi_startup(struct usb_serial *serial)
static void digi_disconnect(struct usb_serial *serial)
{
int i;
- dbg("digi_disconnect: TOP, in_interrupt()=%ld", in_interrupt());
/* stop reads and writes on all ports */
for (i = 0; i < serial->type->num_ports + 1; i++) {
@@ -1571,16 +1290,31 @@ static void digi_disconnect(struct usb_serial *serial)
static void digi_release(struct usb_serial *serial)
{
- int i;
- dbg("digi_release: TOP, in_interrupt()=%ld", in_interrupt());
+ struct digi_serial *serial_priv;
+ struct digi_port *priv;
+
+ serial_priv = usb_get_serial_data(serial);
- /* free the private data structures for all ports */
- /* number of regular ports + 1 for the out-of-band port */
- for (i = 0; i < serial->type->num_ports + 1; i++)
- kfree(usb_get_serial_port_data(serial->port[i]));
- kfree(usb_get_serial_data(serial));
+ priv = usb_get_serial_port_data(serial_priv->ds_oob_port);
+ kfree(priv);
+
+ kfree(serial_priv);
+}
+
+static int digi_port_probe(struct usb_serial_port *port)
+{
+ return digi_port_init(port, port->port_number);
}
+static int digi_port_remove(struct usb_serial_port *port)
+{
+ struct digi_port *priv;
+
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
+}
static void digi_read_bulk_callback(struct urb *urb)
{
@@ -1590,8 +1324,6 @@ static void digi_read_bulk_callback(struct urb *urb)
int ret;
int status = urb->status;
- dbg("digi_read_bulk_callback: TOP");
-
/* port sanity check, do not resubmit if port is not valid */
if (port == NULL)
return;
@@ -1626,7 +1358,6 @@ static void digi_read_bulk_callback(struct urb *urb)
}
/* continue read */
- urb->dev = port->serial->dev;
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret != 0 && ret != -EPERM) {
dev_err(&port->dev,
@@ -1648,9 +1379,7 @@ static void digi_read_bulk_callback(struct urb *urb)
static int digi_read_inb_callback(struct urb *urb)
{
-
struct usb_serial_port *port = urb->context;
- struct tty_struct *tty;
struct digi_port *priv = usb_get_serial_port_data(port);
int opcode = ((unsigned char *)urb->transfer_buffer)[0];
int len = ((unsigned char *)urb->transfer_buffer)[1];
@@ -1674,7 +1403,6 @@ static int digi_read_inb_callback(struct urb *urb)
return -1;
}
- tty = tty_port_tty_get(&port->port);
spin_lock(&priv->dp_port_lock);
/* check for throttle; if set, do not resubmit read urb */
@@ -1684,13 +1412,13 @@ static int digi_read_inb_callback(struct urb *urb)
priv->dp_throttle_restart = 1;
/* receive data */
- if (tty && opcode == DIGI_CMD_RECEIVE_DATA) {
+ if (opcode == DIGI_CMD_RECEIVE_DATA) {
/* get flag from port_status */
flag = 0;
/* overrun is special, not associated with a char */
if (port_status & DIGI_OVERRUN_ERROR)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
/* break takes precedence over parity, */
/* which takes precedence over framing errors */
@@ -1704,18 +1432,17 @@ static int digi_read_inb_callback(struct urb *urb)
/* data length is len-1 (one byte of len is port_status) */
--len;
if (len > 0) {
- tty_insert_flip_string_fixed_flag(tty, data, flag,
- len);
- tty_flip_buffer_push(tty);
+ tty_insert_flip_string_fixed_flag(&port->port, data,
+ flag, len);
+ tty_flip_buffer_push(&port->port);
}
}
spin_unlock(&priv->dp_port_lock);
- tty_kref_put(tty);
if (opcode == DIGI_CMD_RECEIVE_DISABLE)
- dbg("%s: got RECEIVE_DISABLE", __func__);
+ dev_dbg(&port->dev, "%s: got RECEIVE_DISABLE\n", __func__);
else if (opcode != DIGI_CMD_RECEIVE_DATA)
- dbg("%s: unknown opcode: %d", __func__, opcode);
+ dev_dbg(&port->dev, "%s: unknown opcode: %d\n", __func__, opcode);
return throttled ? 1 : 0;
@@ -1742,9 +1469,6 @@ static int digi_read_oob_callback(struct urb *urb)
int i;
unsigned int rts;
- dbg("digi_read_oob_callback: port=%d, len=%d",
- priv->dp_port_num, urb->actual_length);
-
/* handle each oob command */
for (i = 0; i < urb->actual_length - 3;) {
opcode = ((unsigned char *)urb->transfer_buffer)[i++];
@@ -1752,7 +1476,7 @@ static int digi_read_oob_callback(struct urb *urb)
status = ((unsigned char *)urb->transfer_buffer)[i++];
val = ((unsigned char *)urb->transfer_buffer)[i++];
- dbg("digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d",
+ dev_dbg(&port->dev, "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d\n",
opcode, line, status, val);
if (status != 0 || line >= serial->type->num_ports)
@@ -1768,7 +1492,7 @@ static int digi_read_oob_callback(struct urb *urb)
rts = 0;
if (tty)
- rts = tty->termios->c_cflag & CRTSCTS;
+ rts = tty->termios.c_cflag & CRTSCTS;
if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
spin_lock(&priv->dp_port_lock);
@@ -1778,7 +1502,7 @@ static int digi_read_oob_callback(struct urb *urb)
/* port must be open to use tty struct */
if (rts) {
tty->hw_stopped = 0;
- digi_wakeup_write(port);
+ tty_port_tty_wakeup(&port->port);
}
} else {
priv->dp_modem_signals &= ~TIOCM_CTS;
@@ -1799,7 +1523,6 @@ static int digi_read_oob_callback(struct urb *urb)
else
priv->dp_modem_signals &= ~TIOCM_CD;
- wake_up_interruptible(&priv->dp_modem_change_wait);
spin_unlock(&priv->dp_port_lock);
} else if (opcode == DIGI_CMD_TRANSMIT_IDLE) {
spin_lock(&priv->dp_port_lock);
@@ -1815,44 +1538,8 @@ static int digi_read_oob_callback(struct urb *urb)
}
-static int __init digi_init(void)
-{
- int retval;
- retval = usb_serial_register(&digi_acceleport_2_device);
- if (retval)
- goto failed_acceleport_2_device;
- retval = usb_serial_register(&digi_acceleport_4_device);
- if (retval)
- goto failed_acceleport_4_device;
- retval = usb_register(&digi_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&digi_acceleport_4_device);
-failed_acceleport_4_device:
- usb_serial_deregister(&digi_acceleport_2_device);
-failed_acceleport_2_device:
- return retval;
-}
-
-static void __exit digi_exit (void)
-{
- usb_deregister(&digi_driver);
- usb_serial_deregister(&digi_acceleport_2_device);
- usb_serial_deregister(&digi_acceleport_4_device);
-}
-
-
-module_init(digi_init);
-module_exit(digi_exit);
-
+module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 504b5585ea4..90e603d5f66 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -17,7 +17,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -28,12 +27,6 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-static int debug;
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.3"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Gary Brubaker <xavyer@ix.netcom.com>"
#define DRIVER_DESC "USB Empeg Mark I/II Driver"
@@ -51,21 +44,12 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver empeg_driver = {
- .name = "empeg",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
static struct usb_serial_driver empeg_device = {
.driver = {
.owner = THIS_MODULE,
.name = "empeg",
},
.id_table = id_table,
- .usb_driver = &empeg_driver,
.num_ports = 1,
.bulk_out_size = 256,
.throttle = usb_serial_generic_throttle,
@@ -74,18 +58,20 @@ static struct usb_serial_driver empeg_device = {
.init_termios = empeg_init_termios,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &empeg_device, NULL
+};
+
static int empeg_startup(struct usb_serial *serial)
{
int r;
- dbg("%s", __func__);
-
if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
dev_err(&serial->dev->dev, "active config #%d != 1 ??\n",
serial->dev->actconfig->desc.bConfigurationValue);
return -ENODEV;
}
- dbg("%s - reset config", __func__);
+
r = usb_reset_configuration(serial->dev);
/* continue on with initialization */
@@ -94,7 +80,7 @@ static int empeg_startup(struct usb_serial *serial)
static void empeg_init_termios(struct tty_struct *tty)
{
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
/*
* The empeg-car player wants these particular tty settings.
@@ -136,37 +122,8 @@ static void empeg_init_termios(struct tty_struct *tty)
tty_encode_baud_rate(tty, 115200, 115200);
}
-static int __init empeg_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&empeg_device);
- if (retval)
- return retval;
- retval = usb_register(&empeg_driver);
- if (retval) {
- usb_serial_deregister(&empeg_device);
- return retval;
- }
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-}
-
-static void __exit empeg_exit(void)
-{
- usb_deregister(&empeg_driver);
- usb_serial_deregister(&empeg_device);
-}
-
-
-module_init(empeg_init);
-module_exit(empeg_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
deleted file mode 100644
index 3cfc762f505..00000000000
--- a/drivers/usb/serial/ezusb.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * EZ-USB specific functions used by some of the USB to Serial drivers.
- *
- * Copyright (C) 1999 - 2002 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 version
- * 2 as published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/tty.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-
-/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
-#define CPUCS_REG 0x7F92
-
-int ezusb_writememory(struct usb_serial *serial, int address,
- unsigned char *data, int length, __u8 request)
-{
- int result;
- unsigned char *transfer_buffer;
-
- /* dbg("ezusb_writememory %x, %d", address, length); */
- if (!serial->dev) {
- printk(KERN_ERR "ezusb: %s - no physical device present, "
- "failing.\n", __func__);
- return -ENODEV;
- }
-
- transfer_buffer = kmemdup(data, length, GFP_KERNEL);
- if (!transfer_buffer) {
- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n",
- __func__, length);
- return -ENOMEM;
- }
- result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- request, 0x40, address, 0, transfer_buffer, length, 3000);
- kfree(transfer_buffer);
- return result;
-}
-EXPORT_SYMBOL_GPL(ezusb_writememory);
-
-int ezusb_set_reset(struct usb_serial *serial, unsigned char reset_bit)
-{
- int response;
-
- /* dbg("%s - %d", __func__, reset_bit); */
- response = ezusb_writememory(serial, CPUCS_REG, &reset_bit, 1, 0xa0);
- if (response < 0)
- dev_err(&serial->dev->dev, "%s- %d failed\n",
- __func__, reset_bit);
- return response;
-}
-EXPORT_SYMBOL_GPL(ezusb_set_reset);
-
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
new file mode 100644
index 00000000000..c5dc233db2d
--- /dev/null
+++ b/drivers/usb/serial/f81232.c
@@ -0,0 +1,334 @@
+/*
+ * Fintek F81232 USB to serial adaptor driver
+ *
+ * Copyright (C) 2012 Greg Kroah-Hartman (gregkh@linuxfoundation.org)
+ * Copyright (C) 2012 Linux Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+static const struct usb_device_id id_table[] = {
+ { USB_DEVICE(0x1934, 0x0706) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+#define CONTROL_DTR 0x01
+#define CONTROL_RTS 0x02
+
+#define UART_STATE 0x08
+#define UART_STATE_TRANSIENT_MASK 0x74
+#define UART_DCD 0x01
+#define UART_DSR 0x02
+#define UART_BREAK_ERROR 0x04
+#define UART_RING 0x08
+#define UART_FRAME_ERROR 0x10
+#define UART_PARITY_ERROR 0x20
+#define UART_OVERRUN_ERROR 0x40
+#define UART_CTS 0x80
+
+struct f81232_private {
+ spinlock_t lock;
+ u8 line_control;
+ u8 line_status;
+};
+
+static void f81232_update_line_status(struct usb_serial_port *port,
+ unsigned char *data,
+ unsigned int actual_length)
+{
+ /*
+ * FIXME: Update port->icount, and call
+ *
+ * wake_up_interruptible(&port->port.delta_msr_wait);
+ *
+ * on MSR changes.
+ */
+}
+
+static void f81232_read_int_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ unsigned int actual_length = urb->actual_length;
+ int status = urb->status;
+ int retval;
+
+ switch (status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
+ return;
+ default:
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
+ goto exit;
+ }
+
+ usb_serial_debug_data(&port->dev, __func__,
+ urb->actual_length, urb->transfer_buffer);
+
+ f81232_update_line_status(port, data, actual_length);
+
+exit:
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&urb->dev->dev,
+ "%s - usb_submit_urb failed with result %d\n",
+ __func__, retval);
+}
+
+static void f81232_process_read_urb(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+ struct f81232_private *priv = usb_get_serial_port_data(port);
+ unsigned char *data = urb->transfer_buffer;
+ char tty_flag = TTY_NORMAL;
+ unsigned long flags;
+ u8 line_status;
+ int i;
+
+ /* update line status */
+ spin_lock_irqsave(&priv->lock, flags);
+ line_status = priv->line_status;
+ priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (!urb->actual_length)
+ return;
+
+ /* break takes precedence over parity, */
+ /* which takes precedence over framing errors */
+ if (line_status & UART_BREAK_ERROR)
+ tty_flag = TTY_BREAK;
+ else if (line_status & UART_PARITY_ERROR)
+ tty_flag = TTY_PARITY;
+ else if (line_status & UART_FRAME_ERROR)
+ tty_flag = TTY_FRAME;
+ dev_dbg(&port->dev, "%s - tty_flag = %d\n", __func__, tty_flag);
+
+ /* overrun is special, not associated with a char */
+ if (line_status & UART_OVERRUN_ERROR)
+ tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
+
+ if (port->port.console && port->sysrq) {
+ for (i = 0; i < urb->actual_length; ++i)
+ if (!usb_serial_handle_sysrq_char(port, data[i]))
+ tty_insert_flip_char(&port->port, data[i],
+ tty_flag);
+ } else {
+ tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag,
+ urb->actual_length);
+ }
+
+ tty_flip_buffer_push(&port->port);
+}
+
+static int set_control_lines(struct usb_device *dev, u8 value)
+{
+ /* FIXME - Stubbed out for now */
+ return 0;
+}
+
+static void f81232_break_ctl(struct tty_struct *tty, int break_state)
+{
+ /* FIXME - Stubbed out for now */
+
+ /*
+ * break_state = -1 to turn on break, and 0 to turn off break
+ * see drivers/char/tty_io.c to see it used.
+ * last_set_data_urb_value NEVER has the break bit set in it.
+ */
+}
+
+static void f81232_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
+{
+ /* FIXME - Stubbed out for now */
+
+ /* Don't change anything if nothing has changed */
+ if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios))
+ return;
+
+ /* Do the real work here... */
+ if (old_termios)
+ tty_termios_copy_hw(&tty->termios, old_termios);
+}
+
+static int f81232_tiocmget(struct tty_struct *tty)
+{
+ /* FIXME - Stubbed out for now */
+ return 0;
+}
+
+static int f81232_tiocmset(struct tty_struct *tty,
+ unsigned int set, unsigned int clear)
+{
+ /* FIXME - Stubbed out for now */
+ return 0;
+}
+
+static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port)
+{
+ int result;
+
+ /* Setup termios */
+ if (tty)
+ f81232_set_termios(tty, port, NULL);
+
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (result) {
+ dev_err(&port->dev, "%s - failed submitting interrupt urb,"
+ " error %d\n", __func__, result);
+ return result;
+ }
+
+ result = usb_serial_generic_open(tty, port);
+ if (result) {
+ usb_kill_urb(port->interrupt_in_urb);
+ return result;
+ }
+
+ return 0;
+}
+
+static void f81232_close(struct usb_serial_port *port)
+{
+ usb_serial_generic_close(port);
+ usb_kill_urb(port->interrupt_in_urb);
+}
+
+static void f81232_dtr_rts(struct usb_serial_port *port, int on)
+{
+ struct f81232_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ u8 control;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ /* Change DTR and RTS */
+ if (on)
+ priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
+ else
+ priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+ control = priv->line_control;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ set_control_lines(port->serial->dev, control);
+}
+
+static int f81232_carrier_raised(struct usb_serial_port *port)
+{
+ struct f81232_private *priv = usb_get_serial_port_data(port);
+ if (priv->line_status & UART_DCD)
+ return 1;
+ return 0;
+}
+
+static int f81232_ioctl(struct tty_struct *tty,
+ unsigned int cmd, unsigned long arg)
+{
+ struct serial_struct ser;
+ struct usb_serial_port *port = tty->driver_data;
+
+ switch (cmd) {
+ case TIOCGSERIAL:
+ memset(&ser, 0, sizeof ser);
+ ser.type = PORT_16654;
+ ser.line = port->minor;
+ ser.port = port->port_number;
+ ser.baud_base = 460800;
+
+ if (copy_to_user((void __user *)arg, &ser, sizeof ser))
+ return -EFAULT;
+
+ return 0;
+ default:
+ break;
+ }
+ return -ENOIOCTLCMD;
+}
+
+static int f81232_port_probe(struct usb_serial_port *port)
+{
+ struct f81232_private *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ spin_lock_init(&priv->lock);
+
+ usb_set_serial_port_data(port, priv);
+
+ port->port.drain_delay = 256;
+
+ return 0;
+}
+
+static int f81232_port_remove(struct usb_serial_port *port)
+{
+ struct f81232_private *priv;
+
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
+}
+
+static struct usb_serial_driver f81232_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "f81232",
+ },
+ .id_table = id_table,
+ .num_ports = 1,
+ .bulk_in_size = 256,
+ .bulk_out_size = 256,
+ .open = f81232_open,
+ .close = f81232_close,
+ .dtr_rts = f81232_dtr_rts,
+ .carrier_raised = f81232_carrier_raised,
+ .ioctl = f81232_ioctl,
+ .break_ctl = f81232_break_ctl,
+ .set_termios = f81232_set_termios,
+ .tiocmget = f81232_tiocmget,
+ .tiocmset = f81232_tiocmset,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .process_read_urb = f81232_process_read_urb,
+ .read_int_callback = f81232_read_int_callback,
+ .port_probe = f81232_port_probe,
+ .port_remove = f81232_port_remove,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+ &f81232_device,
+ NULL,
+};
+
+module_usb_serial_driver(serial_drivers, id_table);
+
+MODULE_DESCRIPTION("Fintek F81232 USB to serial adaptor driver");
+MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 76f8b355667..8a3813be1b2 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1,7 +1,7 @@
/*
* USB FTDI SIO driver
*
- * Copyright (C) 2009 - 2010
+ * Copyright (C) 2009 - 2013
* Johan Hovold (jhovold@gmail.com)
* Copyright (C) 1999 - 2001
* Greg Kroah-Hartman (greg@kroah.com)
@@ -17,7 +17,7 @@
* See Documentation/usb/usb-serial.txt for more information on using this
* driver
*
- * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
+ * See http://ftdi-usb-sio.sourceforge.net for up to date testing info
* and extra documentation
*
* Change entries from 2004 and earlier can be found in versions of this
@@ -33,7 +33,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -48,19 +47,11 @@
#include "ftdi_sio.h"
#include "ftdi_sio_ids.h"
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.6.0"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>, Andreas Mohr, Johan Hovold <jhovold@gmail.com>"
#define DRIVER_DESC "USB FTDI Serial Converters Driver"
-static int debug;
-static __u16 vendor = FTDI_VID;
-static __u16 product;
struct ftdi_private {
- struct kref kref;
enum ftdi_chip_type chip_type;
/* type of device, either SIO or FT8U232AM */
int baud_base; /* baud base clock for divisor setting */
@@ -73,9 +64,8 @@ struct ftdi_private {
*/
int flags; /* some ASYNC_xxxx flags are supported */
unsigned long last_dtr_rts; /* saved modem control outputs */
- wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
- char prev_status, diff_status; /* Used for TIOCMIWAIT */
- struct usb_serial_port *port;
+ char prev_status; /* Used for TIOCMIWAIT */
+ char transmit_empty; /* If transmitter is empty or not */
__u16 interface; /* FT2232C, FT2232H or FT4232H port interface
(0 for FT232/245) */
@@ -99,6 +89,8 @@ struct ftdi_sio_quirk {
static int ftdi_jtag_probe(struct usb_serial *serial);
static int ftdi_mtxorb_hack_setup(struct usb_serial *serial);
static int ftdi_NDI_device_setup(struct usb_serial *serial);
+static int ftdi_stmclite_probe(struct usb_serial *serial);
+static int ftdi_8u2232c_probe(struct usb_serial *serial);
static void ftdi_USB_UIRT_setup(struct ftdi_private *priv);
static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv);
@@ -122,6 +114,14 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
.port_probe = ftdi_HE_TIRA1_setup,
};
+static struct ftdi_sio_quirk ftdi_stmclite_quirk = {
+ .probe = ftdi_stmclite_probe,
+};
+
+static struct ftdi_sio_quirk ftdi_8u2232c_quirk = {
+ .probe = ftdi_8u2232c_probe,
+};
+
/*
* The 8U232AM has the same API as the sio except for:
* - it can support MUCH higher baudrates; up to:
@@ -141,14 +141,18 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
/*
- * Device ID not listed? Test via module params product/vendor or
- * /sys/bus/usb/ftdi_sio/new_id, then send patch/report!
+ * Device ID not listed? Test it using
+ * /sys/bus/usb-serial/drivers/ftdi_sio/new_id and send a patch or report.
*/
-static struct usb_device_id id_table_combined [] = {
+static const struct usb_device_id id_table_combined[] = {
+ { USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_NXTCAM_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_EV3CON_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) },
@@ -169,8 +173,11 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
- { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) ,
+ .driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_232H_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_FTX_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
@@ -178,9 +185,15 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_BOOST_PID) },
+ { USB_DEVICE(NEWPORT_VID, NEWPORT_AGILIS_PID) },
+ { USB_DEVICE(NEWPORT_VID, NEWPORT_CONEX_CC_PID) },
+ { USB_DEVICE(NEWPORT_VID, NEWPORT_CONEX_AGP_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
+ { USB_DEVICE(FTDI_VID, FTDI_TAGSYS_LP101_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_TAGSYS_P200X_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_LENZ_LIUSB_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
@@ -191,6 +204,8 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_XF_640_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_XF_642_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_URBAN_0_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_URBAN_1_PID) },
{ USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_0_PID) },
@@ -201,6 +216,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) },
+ { USB_DEVICE(FTDI_VID, FTDI_VARDAAN_PID) },
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) },
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) },
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) },
@@ -516,8 +532,13 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) },
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) },
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) },
{ USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
{ USB_DEVICE(OCT_VID, OCT_US101_PID) },
+ { USB_DEVICE(OCT_VID, OCT_DK201_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_HE_TIRA1_PID),
.driver_info = (kernel_ulong_t)&ftdi_HE_TIRA1_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID),
@@ -556,9 +577,15 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
/*
* ELV devices:
*/
+ { USB_DEVICE(FTDI_ELV_VID, FTDI_ELV_WS300_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) },
@@ -614,7 +641,9 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_OCEANIC_PID) },
{ USB_DEVICE(TTI_VID, TTI_QL355P_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
+ { USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) },
{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
+ { USB_DEVICE(MITSUBISHI_VID, MITSUBISHI_FXUSB_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
@@ -635,6 +664,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) },
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_3_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_1_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_2_PID) },
@@ -643,6 +673,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) },
@@ -674,11 +705,23 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
- { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_NZR_SEM_USB_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C2_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP2D_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP2VT_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP2VR_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVT_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVR_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVT_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVR_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) },
- { USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) },
+ { USB_DEVICE(TESTO_VID, TESTO_1_PID) },
+ { USB_DEVICE(TESTO_VID, TESTO_3_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13M_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) },
@@ -695,14 +738,44 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID),
.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
- { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S03_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_59_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57A_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57B_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29A_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29B_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29F_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_62B_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S01_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_63_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29C_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_81B_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_82B_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K5D_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K4Y_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K5G_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S05_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_60_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_61_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_62_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_63B_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_64_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_65_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_92_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_92D_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_W5R_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_A5R_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_PW1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) },
{ USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) },
{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID),
@@ -711,6 +784,8 @@ static struct usb_device_id id_table_combined [] = {
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, LMI_LM3S_ICDI_BOARD_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
@@ -757,15 +832,41 @@ static struct usb_device_id id_table_combined [] = {
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID,
+ USB_CLASS_VENDOR_SPEC,
+ USB_SUBCLASS_VENDOR_SPEC, 0x00) },
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },
{ USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) },
+ { USB_DEVICE(FTDI_VID, PI_C865_PID) },
+ { USB_DEVICE(FTDI_VID, PI_C857_PID) },
+ { USB_DEVICE(PI_VID, PI_C866_PID) },
+ { USB_DEVICE(PI_VID, PI_C663_PID) },
+ { USB_DEVICE(PI_VID, PI_C725_PID) },
+ { USB_DEVICE(PI_VID, PI_E517_PID) },
+ { USB_DEVICE(PI_VID, PI_C863_PID) },
+ { USB_DEVICE(PI_VID, PI_E861_PID) },
+ { USB_DEVICE(PI_VID, PI_C867_PID) },
+ { USB_DEVICE(PI_VID, PI_E609_PID) },
+ { USB_DEVICE(PI_VID, PI_E709_PID) },
+ { USB_DEVICE(PI_VID, PI_100F_PID) },
+ { USB_DEVICE(PI_VID, PI_1011_PID) },
+ { USB_DEVICE(PI_VID, PI_1012_PID) },
+ { USB_DEVICE(PI_VID, PI_1013_PID) },
+ { USB_DEVICE(PI_VID, PI_1014_PID) },
+ { USB_DEVICE(PI_VID, PI_1015_PID) },
+ { USB_DEVICE(PI_VID, PI_1016_PID) },
+ { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) },
{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, TI_XDS100V2_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
+ { USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) },
+ { USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) },
{ USB_DEVICE(FTDI_VID, HAMEG_HO870_PID) },
{ USB_DEVICE(FTDI_VID, MJSG_GENERIC_PID) },
{ USB_DEVICE(FTDI_VID, MJSG_SR_RADIO_PID) },
@@ -794,22 +895,63 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_CINTERION_MC55I_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { }, /* Optional parameter entry */
+ { USB_DEVICE(ST_VID, ST_STMCLT_2232_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(ST_VID, ST_STMCLT_4232_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
+ { USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
+ { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },
+ /* Crucible Devices */
+ { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) },
+ /* Cressi Devices */
+ { USB_DEVICE(FTDI_VID, FTDI_CRESSI_PID) },
+ /* Brainboxes Devices */
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_001_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_012_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_023_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_034_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_101_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_1_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_2_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_3_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_4_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_5_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_6_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_7_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_8_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_257_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_1_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_2_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_3_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_4_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_313_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_324_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_1_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_2_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_357_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_1_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_2_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_3_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_1_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_2_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_1_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_2_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_3_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_4_PID) },
+ /* Infineon Devices */
+ { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver ftdi_driver = {
- .name = "ftdi_sio",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
- .no_dynamic_id = 1,
-};
-
static const char *ftdi_chip_name[] = {
[SIO] = "SIO", /* the serial part of FT8U100AX */
[FT8U232AM] = "FT8U232AM",
@@ -817,7 +959,9 @@ static const char *ftdi_chip_name[] = {
[FT2232C] = "FT2232C",
[FT232RL] = "FT232RL",
[FT2232H] = "FT2232H",
- [FT4232H] = "FT4232H"
+ [FT4232H] = "FT4232H",
+ [FT232H] = "FT232H",
+ [FTX] = "FT-X"
};
@@ -826,28 +970,27 @@ static const char *ftdi_chip_name[] = {
#define FTDI_STATUS_B1_MASK (FTDI_RS_BI)
/* End TIOCMIWAIT */
-#define FTDI_IMPL_ASYNC_FLAGS = (ASYNC_SPD_HI | ASYNC_SPD_VHI \
- | ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP)
-
/* function prototypes for a FTDI serial converter */
static int ftdi_sio_probe(struct usb_serial *serial,
const struct usb_device_id *id);
static int ftdi_sio_port_probe(struct usb_serial_port *port);
static int ftdi_sio_port_remove(struct usb_serial_port *port);
static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port);
-static void ftdi_close(struct usb_serial_port *port);
static void ftdi_dtr_rts(struct usb_serial_port *port, int on);
static void ftdi_process_read_urb(struct urb *urb);
static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
void *dest, size_t size);
static void ftdi_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
-static int ftdi_tiocmget(struct tty_struct *tty, struct file *file);
-static int ftdi_tiocmset(struct tty_struct *tty, struct file *file,
+static int ftdi_tiocmget(struct tty_struct *tty);
+static int ftdi_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
-static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
+static int ftdi_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
static void ftdi_break_ctl(struct tty_struct *tty, int break_state);
+static bool ftdi_tx_empty(struct usb_serial_port *port);
+static int ftdi_get_modem_status(struct usb_serial_port *port,
+ unsigned char status[2]);
static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
static unsigned short int ftdi_232am_baud_to_divisor(int baud);
@@ -862,7 +1005,6 @@ static struct usb_serial_driver ftdi_sio_device = {
.name = "ftdi_sio",
},
.description = "FTDI USB Serial Device",
- .usb_driver = &ftdi_driver,
.id_table = id_table_combined,
.num_ports = 1,
.bulk_in_size = 512,
@@ -871,7 +1013,6 @@ static struct usb_serial_driver ftdi_sio_device = {
.port_probe = ftdi_sio_port_probe,
.port_remove = ftdi_sio_port_remove,
.open = ftdi_open,
- .close = ftdi_close,
.dtr_rts = ftdi_dtr_rts,
.throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle,
@@ -879,19 +1020,22 @@ static struct usb_serial_driver ftdi_sio_device = {
.prepare_write_buffer = ftdi_prepare_write_buffer,
.tiocmget = ftdi_tiocmget,
.tiocmset = ftdi_tiocmset,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.ioctl = ftdi_ioctl,
.set_termios = ftdi_set_termios,
.break_ctl = ftdi_break_ctl,
+ .tx_empty = ftdi_tx_empty,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ftdi_sio_device, NULL
};
#define WDR_TIMEOUT 5000 /* default urb timeout */
#define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */
-/* High and low are for DTR, RTS etc etc */
-#define HIGH 1
-#define LOW 0
-
/*
* ***************************************************************************
* Utility functions
@@ -951,7 +1095,7 @@ static __u32 ftdi_2232h_baud_base_to_divisor(int baud, int base)
int divisor3;
/* hi-speed baud rate is 10-bit sampling instead of 16-bit */
- divisor3 = (base / 10 / baud) * 8;
+ divisor3 = base * 8 / (baud * 10);
divisor = divisor3 >> 3;
divisor |= (__u32)divfrac[divisor3 & 0x7] << 14;
@@ -981,11 +1125,12 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set,
unsigned int clear)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
+ struct device *dev = &port->dev;
unsigned urb_value;
int rv;
if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
- dbg("%s - DTR|RTS not being set|cleared", __func__);
+ dev_dbg(dev, "%s - DTR|RTS not being set|cleared\n", __func__);
return 0; /* no change */
}
@@ -1006,18 +1151,15 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set,
urb_value, priv->interface,
NULL, 0, WDR_TIMEOUT);
if (rv < 0) {
- dbg("%s Error from MODEM_CTRL urb: DTR %s, RTS %s",
- __func__,
- (set & TIOCM_DTR) ? "HIGH" :
- (clear & TIOCM_DTR) ? "LOW" : "unchanged",
- (set & TIOCM_RTS) ? "HIGH" :
- (clear & TIOCM_RTS) ? "LOW" : "unchanged");
+ dev_dbg(dev, "%s Error from MODEM_CTRL urb: DTR %s, RTS %s\n",
+ __func__,
+ (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged",
+ (set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged");
+ rv = usb_translate_errors(rv);
} else {
- dbg("%s - DTR %s, RTS %s", __func__,
- (set & TIOCM_DTR) ? "HIGH" :
- (clear & TIOCM_DTR) ? "LOW" : "unchanged",
- (set & TIOCM_RTS) ? "HIGH" :
- (clear & TIOCM_RTS) ? "LOW" : "unchanged");
+ dev_dbg(dev, "%s - DTR %s, RTS %s\n", __func__,
+ (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged",
+ (set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged");
/* FIXME: locking on last_dtr_rts */
priv->last_dtr_rts = (priv->last_dtr_rts & ~clear) | set;
}
@@ -1029,6 +1171,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
+ struct device *dev = &port->dev;
__u32 div_value = 0;
int div_okay = 1;
int baud;
@@ -1064,7 +1207,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
alt_speed hack */
baud = tty_get_baud_rate(tty);
- dbg("%s - tty_get_baud_rate reports speed %d", __func__, baud);
+ dev_dbg(dev, "%s - tty_get_baud_rate reports speed %d\n", __func__, baud);
/* 2. Observe async-compatible custom_divisor hack, update baudrate
if needed */
@@ -1073,8 +1216,8 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
(priv->custom_divisor)) {
baud = priv->baud_base / priv->custom_divisor;
- dbg("%s - custom divisor %d sets baud rate to %d",
- __func__, priv->custom_divisor, baud);
+ dev_dbg(dev, "%s - custom divisor %d sets baud rate to %d\n",
+ __func__, priv->custom_divisor, baud);
}
/* 3. Convert baudrate to device-specific divisor */
@@ -1096,8 +1239,8 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
case 115200: div_value = ftdi_sio_b115200; break;
} /* baud */
if (div_value == 0) {
- dbg("%s - Baudrate (%d) requested is not supported",
- __func__, baud);
+ dev_dbg(dev, "%s - Baudrate (%d) requested is not supported\n",
+ __func__, baud);
div_value = ftdi_sio_b9600;
baud = 9600;
div_okay = 0;
@@ -1107,7 +1250,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
if (baud <= 3000000) {
div_value = ftdi_232am_baud_to_divisor(baud);
} else {
- dbg("%s - Baud rate too high!", __func__);
+ dev_dbg(dev, "%s - Baud rate too high!\n", __func__);
baud = 9600;
div_value = ftdi_232am_baud_to_divisor(9600);
div_okay = 0;
@@ -1115,7 +1258,8 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
break;
case FT232BM: /* FT232BM chip */
case FT2232C: /* FT2232C chip */
- case FT232RL:
+ case FT232RL: /* FT232RL chip */
+ case FTX: /* FT-X series */
if (baud <= 3000000) {
__u16 product_id = le16_to_cpu(
port->serial->dev->descriptor.idProduct);
@@ -1129,7 +1273,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
}
div_value = ftdi_232bm_baud_to_divisor(baud);
} else {
- dbg("%s - Baud rate too high!", __func__);
+ dev_dbg(dev, "%s - Baud rate too high!\n", __func__);
div_value = ftdi_232bm_baud_to_divisor(9600);
div_okay = 0;
baud = 9600;
@@ -1137,12 +1281,13 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
break;
case FT2232H: /* FT2232H chip */
case FT4232H: /* FT4232H chip */
- if ((baud <= 12000000) & (baud >= 1200)) {
+ case FT232H: /* FT232H chip */
+ if ((baud <= 12000000) && (baud >= 1200)) {
div_value = ftdi_2232h_baud_to_divisor(baud);
} else if (baud < 1200) {
div_value = ftdi_232bm_baud_to_divisor(baud);
} else {
- dbg("%s - Baud rate too high!", __func__);
+ dev_dbg(dev, "%s - Baud rate too high!\n", __func__);
div_value = ftdi_232bm_baud_to_divisor(9600);
div_okay = 0;
baud = 9600;
@@ -1151,7 +1296,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
} /* priv->chip_type */
if (div_okay) {
- dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s",
+ dev_dbg(dev, "%s - Baud rate set to %d (divisor 0x%lX) on chip %s\n",
__func__, baud, (unsigned long)div_value,
ftdi_chip_name[priv->chip_type]);
}
@@ -1171,7 +1316,10 @@ static int change_speed(struct tty_struct *tty, struct usb_serial_port *port)
urb_index_value = get_ftdi_divisor(tty, port);
urb_value = (__u16)urb_index_value;
urb_index = (__u16)(urb_index_value >> 16);
- if (priv->interface) { /* FT2232C */
+ if ((priv->chip_type == FT2232C) || (priv->chip_type == FT2232H) ||
+ (priv->chip_type == FT4232H) || (priv->chip_type == FT232H)) {
+ /* Probably the BM type needs the MSB of the encoded fractional
+ * divider also moved like for the chips above. Any infos? */
urb_index = (__u16)((urb_index << 8) | priv->interface);
}
@@ -1194,7 +1342,7 @@ static int write_latency_timer(struct usb_serial_port *port)
if (priv->flags & ASYNC_LOW_LATENCY)
l = 1;
- dbg("%s: setting latency timer = %i", __func__, l);
+ dev_dbg(&port->dev, "%s: setting latency timer = %i\n", __func__, l);
rv = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
@@ -1214,8 +1362,6 @@ static int read_latency_timer(struct usb_serial_port *port)
unsigned char *buf;
int rv;
- dbg("%s", __func__);
-
buf = kmalloc(1, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -1280,8 +1426,7 @@ static int set_serial_info(struct tty_struct *tty,
goto check_and_exit;
}
- if ((new_serial.baud_base != priv->baud_base) &&
- (new_serial.baud_base < 9600)) {
+ if (new_serial.baud_base != priv->baud_base) {
mutex_unlock(&priv->cfg_lock);
return -EINVAL;
}
@@ -1320,6 +1465,23 @@ check_and_exit:
return 0;
}
+static int get_lsr_info(struct usb_serial_port *port,
+ struct serial_struct __user *retinfo)
+{
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ unsigned int result = 0;
+
+ if (!retinfo)
+ return -EFAULT;
+
+ if (priv->transmit_empty)
+ result = TIOCSER_TEMT;
+
+ if (copy_to_user(retinfo, &result, sizeof(unsigned int)))
+ return -EFAULT;
+ return 0;
+}
+
/* Determine type of FTDI chip based on USB config and descriptor. */
static void ftdi_determine_type(struct usb_serial_port *port)
@@ -1335,8 +1497,8 @@ static void ftdi_determine_type(struct usb_serial_port *port)
version = le16_to_cpu(udev->descriptor.bcdDevice);
interfaces = udev->actconfig->desc.bNumInterfaces;
- dbg("%s: bcdDevice = 0x%x, bNumInterfaces = %u", __func__,
- version, interfaces);
+ dev_dbg(&port->dev, "%s: bcdDevice = 0x%x, bNumInterfaces = %u\n", __func__,
+ version, interfaces);
if (interfaces > 1) {
int inter;
@@ -1366,8 +1528,9 @@ static void ftdi_determine_type(struct usb_serial_port *port)
/* BM-type devices have a bug where bcdDevice gets set
* to 0x200 when iSerialNumber is 0. */
if (version < 0x500) {
- dbg("%s: something fishy - bcdDevice too low for multi-interface device",
- __func__);
+ dev_dbg(&port->dev,
+ "%s: something fishy - bcdDevice too low for multi-interface device\n",
+ __func__);
}
} else if (version < 0x200) {
/* Old device. Assume it's the original SIO. */
@@ -1381,10 +1544,17 @@ static void ftdi_determine_type(struct usb_serial_port *port)
} else if (version < 0x600) {
/* Assume it's an FT232BM (or FT245BM) */
priv->chip_type = FT232BM;
- } else {
- /* Assume it's an FT232R */
+ } else if (version < 0x900) {
+ /* Assume it's an FT232RL */
priv->chip_type = FT232RL;
+ } else if (version < 0x1000) {
+ /* Assume it's an FT232H */
+ priv->chip_type = FT232H;
+ } else {
+ /* Assume it's an FT-X series device */
+ priv->chip_type = FTX;
}
+
dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]);
}
@@ -1399,14 +1569,17 @@ static void ftdi_set_max_packet_size(struct usb_serial_port *port)
struct usb_device *udev = serial->dev;
struct usb_interface *interface = serial->interface;
- struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc;
+ struct usb_endpoint_descriptor *ep_desc;
unsigned num_endpoints;
- int i;
+ unsigned i;
num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
+ if (!num_endpoints)
+ return;
+
/* NOTE: some customers have programmed FT232R/FT245R devices
* with an endpoint size of 0 - not good. In this case, we
* want to override the endpoint descriptor setting and use a
@@ -1422,7 +1595,7 @@ static void ftdi_set_max_packet_size(struct usb_serial_port *port)
}
/* set max packet size based on descriptor */
- priv->max_packet_size = le16_to_cpu(ep_desc->wMaxPacketSize);
+ priv->max_packet_size = usb_endpoint_maxp(ep_desc);
dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
}
@@ -1434,8 +1607,8 @@ static void ftdi_set_max_packet_size(struct usb_serial_port *port)
* ***************************************************************************
*/
-static ssize_t show_latency_timer(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t latency_timer_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1445,11 +1618,10 @@ static ssize_t show_latency_timer(struct device *dev,
return sprintf(buf, "%i\n", priv->latency);
}
-
/* Write a new value of the latency timer, in units of milliseconds. */
-static ssize_t store_latency_timer(struct device *dev,
- struct device_attribute *attr, const char *valbuf,
- size_t count)
+static ssize_t latency_timer_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *valbuf, size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1462,6 +1634,7 @@ static ssize_t store_latency_timer(struct device *dev,
return -EIO;
return count;
}
+static DEVICE_ATTR_RW(latency_timer);
/* Write an event character directly to the FTDI register. The ASCII
value is in the low 8 bits, with the enable bit in the 9th bit. */
@@ -1474,7 +1647,7 @@ static ssize_t store_event_char(struct device *dev,
int v = simple_strtoul(valbuf, NULL, 10);
int rv;
- dbg("%s: setting event char = %i", __func__, v);
+ dev_dbg(&port->dev, "%s: setting event char = %i\n", __func__, v);
rv = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
@@ -1483,15 +1656,12 @@ static ssize_t store_event_char(struct device *dev,
v, priv->interface,
NULL, 0, WDR_TIMEOUT);
if (rv < 0) {
- dbg("Unable to write event character: %i", rv);
+ dev_dbg(&port->dev, "Unable to write event character: %i\n", rv);
return -EIO;
}
return count;
}
-
-static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer,
- store_latency_timer);
static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char);
static int create_sysfs_attrs(struct usb_serial_port *port)
@@ -1499,19 +1669,19 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
struct ftdi_private *priv = usb_get_serial_port_data(port);
int retval = 0;
- dbg("%s", __func__);
-
/* XXX I've no idea if the original SIO supports the event_char
* sysfs parameter, so I'm playing it safe. */
if (priv->chip_type != SIO) {
- dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
+ dev_dbg(&port->dev, "sysfs attributes for %s\n", ftdi_chip_name[priv->chip_type]);
retval = device_create_file(&port->dev, &dev_attr_event_char);
if ((!retval) &&
(priv->chip_type == FT232BM ||
priv->chip_type == FT2232C ||
priv->chip_type == FT232RL ||
priv->chip_type == FT2232H ||
- priv->chip_type == FT4232H)) {
+ priv->chip_type == FT4232H ||
+ priv->chip_type == FT232H ||
+ priv->chip_type == FTX)) {
retval = device_create_file(&port->dev,
&dev_attr_latency_timer);
}
@@ -1523,8 +1693,6 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
- dbg("%s", __func__);
-
/* XXX see create_sysfs_attrs */
if (priv->chip_type != SIO) {
device_remove_file(&port->dev, &dev_attr_event_char);
@@ -1532,7 +1700,9 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
priv->chip_type == FT2232C ||
priv->chip_type == FT232RL ||
priv->chip_type == FT2232H ||
- priv->chip_type == FT4232H) {
+ priv->chip_type == FT4232H ||
+ priv->chip_type == FT232H ||
+ priv->chip_type == FTX) {
device_remove_file(&port->dev, &dev_attr_latency_timer);
}
}
@@ -1569,25 +1739,17 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);
- dbg("%s", __func__);
-
priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
- if (!priv) {
- dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__,
- sizeof(struct ftdi_private));
+ if (!priv)
return -ENOMEM;
- }
- kref_init(&priv->kref);
mutex_init(&priv->cfg_lock);
- init_waitqueue_head(&priv->delta_msr_wait);
priv->flags = ASYNC_LOW_LATENCY;
if (quirk && quirk->port_probe)
quirk->port_probe(priv);
- priv->port = port;
usb_set_serial_port_data(port, priv);
ftdi_determine_type(port);
@@ -1604,8 +1766,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
/* Called from usbserial:serial_probe */
static void ftdi_USB_UIRT_setup(struct ftdi_private *priv)
{
- dbg("%s", __func__);
-
priv->flags |= ASYNC_SPD_CUST;
priv->custom_divisor = 77;
priv->force_baud = 38400;
@@ -1616,8 +1776,6 @@ static void ftdi_USB_UIRT_setup(struct ftdi_private *priv)
static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv)
{
- dbg("%s", __func__);
-
priv->flags |= ASYNC_SPD_CUST;
priv->custom_divisor = 240;
priv->force_baud = 38400;
@@ -1626,7 +1784,8 @@ static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv)
/*
* Module parameter to control latency timer for NDI FTDI-based USB devices.
- * If this value is not set in modprobe.conf.local its value will be set to 1ms.
+ * If this value is not set in /etc/modprobe.d/ its value will be set
+ * to 1ms.
*/
static int ndi_latency_timer = 1;
@@ -1645,8 +1804,8 @@ static int ftdi_NDI_device_setup(struct usb_serial *serial)
if (latency > 99)
latency = 99;
- dbg("%s setting NDI device latency to %d", __func__, latency);
- dev_info(&udev->dev, "NDI device with a latency value of %d", latency);
+ dev_dbg(&udev->dev, "%s setting NDI device latency to %d\n", __func__, latency);
+ dev_info(&udev->dev, "NDI device with a latency value of %d\n", latency);
/* FIXME: errors are not returned */
usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
@@ -1666,8 +1825,6 @@ static int ftdi_jtag_probe(struct usb_serial *serial)
struct usb_device *udev = serial->dev;
struct usb_interface *interface = serial->interface;
- dbg("%s", __func__);
-
if (interface == udev->actconfig->interface[0]) {
dev_info(&udev->dev,
"Ignoring serial port reserved for JTAG\n");
@@ -1677,6 +1834,38 @@ static int ftdi_jtag_probe(struct usb_serial *serial)
return 0;
}
+static int ftdi_8u2232c_probe(struct usb_serial *serial)
+{
+ struct usb_device *udev = serial->dev;
+
+ if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ||
+ (udev->product && !strcmp(udev->product, "BeagleBone/XDS100V2")))
+ return ftdi_jtag_probe(serial);
+
+ return 0;
+}
+
+/*
+ * First two ports on JTAG adaptors using an FT4232 such as STMicroelectronics's
+ * ST Micro Connect Lite are reserved for JTAG or other non-UART interfaces and
+ * can be accessed from userspace.
+ * The next two ports are enabled as UARTs by default, where port 2 is
+ * a conventional RS-232 UART.
+ */
+static int ftdi_stmclite_probe(struct usb_serial *serial)
+{
+ struct usb_device *udev = serial->dev;
+ struct usb_interface *interface = serial->interface;
+
+ if (interface == udev->actconfig->interface[0] ||
+ interface == udev->actconfig->interface[1]) {
+ dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
/*
* The Matrix Orbital VK204-25-USB has an invalid IN endpoint.
* We have to correct it if we want to read from it.
@@ -1695,22 +1884,13 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
return 0;
}
-static void ftdi_sio_priv_release(struct kref *k)
-{
- struct ftdi_private *priv = container_of(k, struct ftdi_private, kref);
-
- kfree(priv);
-}
-
static int ftdi_sio_port_remove(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
- dbg("%s", __func__);
-
remove_sysfs_attrs(port);
- kref_put(&priv->kref, ftdi_sio_priv_release);
+ kfree(priv);
return 0;
}
@@ -1719,9 +1899,6 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct usb_device *dev = port->serial->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port);
- int result;
-
- dbg("%s", __func__);
/* No error checking for this (will get errors later anyway) */
/* See ftdi_sio.h for description of what is reset */
@@ -1736,53 +1913,31 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
/* ftdi_set_termios will send usb control messages */
if (tty)
- ftdi_set_termios(tty, port, tty->termios);
+ ftdi_set_termios(tty, port, NULL);
- /* Start reading from the device */
- result = usb_serial_generic_open(tty, port);
- if (!result)
- kref_get(&priv->kref);
-
- return result;
+ return usb_serial_generic_open(tty, port);
}
static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
- mutex_lock(&port->serial->disc_mutex);
- if (!port->serial->disconnected) {
- /* Disable flow control */
- if (!on && usb_control_msg(port->serial->dev,
+ /* Disable flow control */
+ if (!on) {
+ if (usb_control_msg(port->serial->dev,
usb_sndctrlpipe(port->serial->dev, 0),
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
0, priv->interface, NULL, 0,
WDR_TIMEOUT) < 0) {
- dev_err(&port->dev, "error from flowcontrol urb\n");
+ dev_err(&port->dev, "error from flowcontrol urb\n");
}
- /* drop RTS and DTR */
- if (on)
- set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
- else
- clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
}
- mutex_unlock(&port->serial->disc_mutex);
-}
-
-/*
- * usbserial:__serial_close only calls ftdi_close if the point is open
- *
- * This only gets called when it is the last close
- */
-static void ftdi_close(struct usb_serial_port *port)
-{
- struct ftdi_private *priv = usb_get_serial_port_data(port);
-
- dbg("%s", __func__);
-
- usb_serial_generic_close(port);
- kref_put(&priv->kref, ftdi_sio_priv_release);
+ /* drop RTS and DTR */
+ if (on)
+ set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+ else
+ clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
}
/* The SIO requires the first byte to have:
@@ -1812,6 +1967,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
c = kfifo_out(&port->write_fifo, &buffer[i + 1], len);
if (!c)
break;
+ port->icount.tx += c;
buffer[i] = (c << 2) + 1;
count += c + 1;
}
@@ -1819,6 +1975,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
} else {
count = kfifo_out_locked(&port->write_fifo, dest, size,
&port->lock);
+ port->icount.tx += count;
}
return count;
@@ -1826,19 +1983,16 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
#define FTDI_RS_ERR_MASK (FTDI_RS_BI | FTDI_RS_PE | FTDI_RS_FE | FTDI_RS_OE)
-static int ftdi_process_packet(struct tty_struct *tty,
- struct usb_serial_port *port, struct ftdi_private *priv,
- char *packet, int len)
+static int ftdi_process_packet(struct usb_serial_port *port,
+ struct ftdi_private *priv, char *packet, int len)
{
int i;
char status;
char flag;
char *ch;
- dbg("%s - port %d", __func__, port->number);
-
if (len < 2) {
- dbg("malformed packet");
+ dev_dbg(&port->dev, "malformed packet\n");
return 0;
}
@@ -1847,8 +2001,26 @@ static int ftdi_process_packet(struct tty_struct *tty,
are only processed once. */
status = packet[0] & FTDI_STATUS_B0_MASK;
if (status != priv->prev_status) {
- priv->diff_status |= status ^ priv->prev_status;
- wake_up_interruptible(&priv->delta_msr_wait);
+ char diff_status = status ^ priv->prev_status;
+
+ if (diff_status & FTDI_RS0_CTS)
+ port->icount.cts++;
+ if (diff_status & FTDI_RS0_DSR)
+ port->icount.dsr++;
+ if (diff_status & FTDI_RS0_RI)
+ port->icount.rng++;
+ if (diff_status & FTDI_RS0_RLSD) {
+ struct tty_struct *tty;
+
+ port->icount.dcd++;
+ tty = tty_port_tty_get(&port->port);
+ if (tty)
+ usb_serial_handle_dcd_change(port, tty,
+ status & FTDI_RS0_RLSD);
+ tty_kref_put(tty);
+ }
+
+ wake_up_interruptible(&port->port.delta_msr_wait);
priv->prev_status = status;
}
@@ -1858,29 +2030,41 @@ static int ftdi_process_packet(struct tty_struct *tty,
* over framing errors */
if (packet[1] & FTDI_RS_BI) {
flag = TTY_BREAK;
+ port->icount.brk++;
usb_serial_handle_break(port);
} else if (packet[1] & FTDI_RS_PE) {
flag = TTY_PARITY;
+ port->icount.parity++;
} else if (packet[1] & FTDI_RS_FE) {
flag = TTY_FRAME;
+ port->icount.frame++;
}
/* Overrun is special, not associated with a char */
- if (packet[1] & FTDI_RS_OE)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ if (packet[1] & FTDI_RS_OE) {
+ port->icount.overrun++;
+ tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
+ }
}
+ /* save if the transmitter is empty or not */
+ if (packet[1] & FTDI_RS_TEMT)
+ priv->transmit_empty = 1;
+ else
+ priv->transmit_empty = 0;
+
len -= 2;
if (!len)
return 0; /* status only */
+ port->icount.rx += len;
ch = packet + 2;
if (port->port.console && port->sysrq) {
for (i = 0; i < len; i++, ch++) {
if (!usb_serial_handle_sysrq_char(port, *ch))
- tty_insert_flip_char(tty, *ch, flag);
+ tty_insert_flip_char(&port->port, *ch, flag);
}
} else {
- tty_insert_flip_string_fixed_flag(tty, ch, flag, len);
+ tty_insert_flip_string_fixed_flag(&port->port, ch, flag, len);
}
return len;
@@ -1889,25 +2073,19 @@ static int ftdi_process_packet(struct tty_struct *tty,
static void ftdi_process_read_urb(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
- struct tty_struct *tty;
struct ftdi_private *priv = usb_get_serial_port_data(port);
char *data = (char *)urb->transfer_buffer;
int i;
int len;
int count = 0;
- tty = tty_port_tty_get(&port->port);
- if (!tty)
- return;
-
for (i = 0; i < urb->actual_length; i += priv->max_packet_size) {
len = min_t(int, urb->actual_length - i, priv->max_packet_size);
- count += ftdi_process_packet(tty, port, priv, &data[i], len);
+ count += ftdi_process_packet(port, priv, &data[i], len);
}
if (count)
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
+ tty_flip_buffer_push(&port->port);
}
static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
@@ -1931,15 +2109,29 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
FTDI_SIO_SET_DATA_REQUEST_TYPE,
urb_value , priv->interface,
NULL, 0, WDR_TIMEOUT) < 0) {
- dev_err(&port->dev, "%s FAILED to enable/disable break state "
- "(state was %d)\n", __func__, break_state);
+ dev_err(&port->dev, "%s FAILED to enable/disable break state (state was %d)\n",
+ __func__, break_state);
}
- dbg("%s break state is %d - urb is %d", __func__,
- break_state, urb_value);
+ dev_dbg(&port->dev, "%s break state is %d - urb is %d\n", __func__,
+ break_state, urb_value);
}
+static bool ftdi_tx_empty(struct usb_serial_port *port)
+{
+ unsigned char buf[2];
+ int ret;
+
+ ret = ftdi_get_modem_status(port, buf);
+ if (ret == 2) {
+ if (!(buf[1] & FTDI_RS_TEMT))
+ return false;
+ }
+
+ return true;
+}
+
/* old_termios contains the original termios settings and tty->termios contains
* the new setting to be used
* WARNING: set_termios calls this with old_termios in kernel space
@@ -1948,8 +2140,9 @@ static void ftdi_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_device *dev = port->serial->dev;
+ struct device *ddev = &port->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port);
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
unsigned int cflag = termios->c_cflag;
__u16 urb_value; /* will hold the new flags */
@@ -1958,31 +2151,63 @@ static void ftdi_set_termios(struct tty_struct *tty,
unsigned char vstop;
unsigned char vstart;
- dbg("%s", __func__);
-
/* Force baud rate if this device requires it, unless it is set to
B0. */
if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) {
- dbg("%s: forcing baud rate for this device", __func__);
+ dev_dbg(ddev, "%s: forcing baud rate for this device\n", __func__);
tty_encode_baud_rate(tty, priv->force_baud,
priv->force_baud);
}
/* Force RTS-CTS if this device requires it. */
if (priv->force_rtscts) {
- dbg("%s: forcing rtscts for this device", __func__);
+ dev_dbg(ddev, "%s: forcing rtscts for this device\n", __func__);
termios->c_cflag |= CRTSCTS;
}
+ /*
+ * All FTDI UART chips are limited to CS7/8. We shouldn't pretend to
+ * support CS5/6 and revert the CSIZE setting instead.
+ *
+ * CS5 however is used to control some smartcard readers which abuse
+ * this limitation to switch modes. Original FTDI chips fall back to
+ * eight data bits.
+ *
+ * TODO: Implement a quirk to only allow this with mentioned
+ * readers. One I know of (Argolis Smartreader V1)
+ * returns "USB smartcard server" as iInterface string.
+ * The vendor didn't bother with a custom VID/PID of
+ * course.
+ */
+ if (C_CSIZE(tty) == CS6) {
+ dev_warn(ddev, "requested CSIZE setting not supported\n");
+
+ termios->c_cflag &= ~CSIZE;
+ if (old_termios)
+ termios->c_cflag |= old_termios->c_cflag & CSIZE;
+ else
+ termios->c_cflag |= CS8;
+ }
+
cflag = termios->c_cflag;
- /* FIXME -For this cut I don't care if the line is really changing or
- not - so just do the change regardless - should be able to
- compare old_termios and tty->termios */
+ if (!old_termios)
+ goto no_skip;
+
+ if (old_termios->c_cflag == termios->c_cflag
+ && old_termios->c_ispeed == termios->c_ispeed
+ && old_termios->c_ospeed == termios->c_ospeed)
+ goto no_c_cflag_changes;
+
/* NOTE These routines can get interrupted by
ftdi_sio_read_bulk_callback - need to examine what this means -
don't see any problems yet */
+ if ((old_termios->c_cflag & (CSIZE|PARODD|PARENB|CMSPAR|CSTOPB)) ==
+ (termios->c_cflag & (CSIZE|PARODD|PARENB|CMSPAR|CSTOPB)))
+ goto no_data_parity_stop_changes;
+
+no_skip:
/* Set number of data bits, parity, stop bits */
urb_value = 0;
@@ -2000,13 +2225,19 @@ static void ftdi_set_termios(struct tty_struct *tty,
} else {
urb_value |= FTDI_SIO_SET_DATA_PARITY_NONE;
}
- if (cflag & CSIZE) {
- switch (cflag & CSIZE) {
- case CS7: urb_value |= 7; dbg("Setting CS7"); break;
- case CS8: urb_value |= 8; dbg("Setting CS8"); break;
- default:
- dev_err(&port->dev, "CSIZE was set but not CS7-CS8\n");
- }
+ switch (cflag & CSIZE) {
+ case CS5:
+ dev_dbg(ddev, "Setting CS5 quirk\n");
+ break;
+ case CS7:
+ urb_value |= 7;
+ dev_dbg(ddev, "Setting CS7\n");
+ break;
+ default:
+ case CS8:
+ urb_value |= 8;
+ dev_dbg(ddev, "Setting CS8\n");
+ break;
}
/* This is needed by the break command since it uses the same command
@@ -2018,11 +2249,12 @@ static void ftdi_set_termios(struct tty_struct *tty,
FTDI_SIO_SET_DATA_REQUEST_TYPE,
urb_value , priv->interface,
NULL, 0, WDR_SHORT_TIMEOUT) < 0) {
- dev_err(&port->dev, "%s FAILED to set "
- "databits/stopbits/parity\n", __func__);
+ dev_err(ddev, "%s FAILED to set databits/stopbits/parity\n",
+ __func__);
}
/* Now do the baudrate */
+no_data_parity_stop_changes:
if ((cflag & CBAUD) == B0) {
/* Disable flow control */
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -2030,8 +2262,7 @@ static void ftdi_set_termios(struct tty_struct *tty,
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
0, priv->interface,
NULL, 0, WDR_TIMEOUT) < 0) {
- dev_err(&port->dev,
- "%s error from disable flowcontrol urb\n",
+ dev_err(ddev, "%s error from disable flowcontrol urb\n",
__func__);
}
/* Drop RTS and DTR */
@@ -2040,28 +2271,26 @@ static void ftdi_set_termios(struct tty_struct *tty,
/* set the baudrate determined before */
mutex_lock(&priv->cfg_lock);
if (change_speed(tty, port))
- dev_err(&port->dev, "%s urb failed to set baudrate\n",
- __func__);
+ dev_err(ddev, "%s urb failed to set baudrate\n", __func__);
mutex_unlock(&priv->cfg_lock);
/* Ensure RTS and DTR are raised when baudrate changed from 0 */
- if (!old_termios || (old_termios->c_cflag & CBAUD) == B0)
+ if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
}
/* Set flow control */
/* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
+no_c_cflag_changes:
if (cflag & CRTSCTS) {
- dbg("%s Setting to CRTSCTS flow control", __func__);
+ dev_dbg(ddev, "%s Setting to CRTSCTS flow control\n", __func__);
if (usb_control_msg(dev,
usb_sndctrlpipe(dev, 0),
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
0 , (FTDI_SIO_RTS_CTS_HS | priv->interface),
NULL, 0, WDR_TIMEOUT) < 0) {
- dev_err(&port->dev,
- "urb failed to set to rts/cts flow control\n");
+ dev_err(ddev, "urb failed to set to rts/cts flow control\n");
}
-
} else {
/*
* Xon/Xoff code
@@ -2071,8 +2300,8 @@ static void ftdi_set_termios(struct tty_struct *tty,
* code is executed.
*/
if (iflag & IXOFF) {
- dbg("%s request to enable xonxoff iflag=%04x",
- __func__, iflag);
+ dev_dbg(ddev, "%s request to enable xonxoff iflag=%04x\n",
+ __func__, iflag);
/* Try to enable the XON/XOFF on the ftdi_sio
* Set the vstart and vstop -- could have been done up
* above where a lot of other dereferencing is done but
@@ -2097,31 +2326,33 @@ static void ftdi_set_termios(struct tty_struct *tty,
/* else clause to only run if cflag ! CRTSCTS and iflag
* ! XOFF. CHECKME Assuming XON/XOFF handled by tty
* stack - not by device */
- dbg("%s Turning off hardware flow control", __func__);
+ dev_dbg(ddev, "%s Turning off hardware flow control\n", __func__);
if (usb_control_msg(dev,
usb_sndctrlpipe(dev, 0),
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
0, priv->interface,
NULL, 0, WDR_TIMEOUT) < 0) {
- dev_err(&port->dev,
- "urb failed to clear flow control\n");
+ dev_err(ddev, "urb failed to clear flow control\n");
}
}
-
}
}
-static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
+/*
+ * Get modem-control status.
+ *
+ * Returns the number of status bytes retrieved (device dependant), or
+ * negative error code.
+ */
+static int ftdi_get_modem_status(struct usb_serial_port *port,
+ unsigned char status[2])
{
- struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
unsigned char *buf;
int len;
int ret;
- dbg("%s TIOCMGET", __func__);
-
buf = kmalloc(2, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -2139,6 +2370,8 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
case FT232RL:
case FT2232H:
case FT4232H:
+ case FT232H:
+ case FTX:
len = 2;
break;
default:
@@ -2152,34 +2385,58 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
0, priv->interface,
buf, len, WDR_TIMEOUT);
- if (ret < 0)
+ if (ret < 0) {
+ dev_err(&port->dev, "failed to get modem status: %d\n", ret);
+ ret = usb_translate_errors(ret);
goto out;
+ }
- ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
- (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
- (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
- (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) |
- priv->last_dtr_rts;
+ status[0] = buf[0];
+ if (ret > 1)
+ status[1] = buf[1];
+ else
+ status[1] = 0;
+
+ dev_dbg(&port->dev, "%s - 0x%02x%02x\n", __func__, status[0],
+ status[1]);
out:
kfree(buf);
+
+ return ret;
+}
+
+static int ftdi_tiocmget(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ unsigned char buf[2];
+ int ret;
+
+ ret = ftdi_get_modem_status(port, buf);
+ if (ret < 0)
+ return ret;
+
+ ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
+ (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
+ (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
+ (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) |
+ priv->last_dtr_rts;
+
return ret;
}
-static int ftdi_tiocmset(struct tty_struct *tty, struct file *file,
+static int ftdi_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s TIOCMSET", __func__);
+
return update_mctrl(port, set, clear);
}
-static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
+static int ftdi_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
- struct ftdi_private *priv = usb_get_serial_port_data(port);
-
- dbg("%s cmd 0x%04x", __func__, cmd);
/* Based on code from acm.c and others */
switch (cmd) {
@@ -2191,110 +2448,21 @@ static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
case TIOCSSERIAL: /* sets serial port data */
return set_serial_info(tty, port,
(struct serial_struct __user *) arg);
-
- /*
- * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
- * - mask passed in arg for lines of interest
- * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
- * Caller should use TIOCGICOUNT to see which one it was.
- * (except that the driver doesn't support it !)
- *
- * This code is borrowed from linux/drivers/char/serial.c
- */
- case TIOCMIWAIT:
- while (priv != NULL) {
- interruptible_sleep_on(&priv->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- else {
- char diff = priv->diff_status;
-
- if (diff == 0)
- return -EIO; /* no change => error */
-
- /* Consume all events */
- priv->diff_status = 0;
-
- /* Return 0 if caller wanted to know about
- these bits */
- if (((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) ||
- ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) ||
- ((arg & TIOCM_CD) && (diff & FTDI_RS0_RLSD)) ||
- ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS))) {
- return 0;
- }
- /*
- * Otherwise caller can't care less about what
- * happened,and so we continue to wait for more
- * events.
- */
- }
- }
- return 0;
+ case TIOCSERGETLSR:
+ return get_lsr_info(port, (struct serial_struct __user *)arg);
+ break;
default:
break;
}
- /* This is not necessarily an error - turns out the higher layers
- * will do some ioctls themselves (see comment above)
- */
- dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __func__, cmd);
- return -ENOIOCTLCMD;
-}
-static int __init ftdi_init(void)
-{
- int retval;
-
- dbg("%s", __func__);
- if (vendor > 0 && product > 0) {
- /* Add user specified VID/PID to reserved element of table. */
- int i;
- for (i = 0; id_table_combined[i].idVendor; i++)
- ;
- id_table_combined[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
- id_table_combined[i].idVendor = vendor;
- id_table_combined[i].idProduct = product;
- }
- retval = usb_serial_register(&ftdi_sio_device);
- if (retval)
- goto failed_sio_register;
- retval = usb_register(&ftdi_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&ftdi_sio_device);
-failed_sio_register:
- return retval;
-}
-
-static void __exit ftdi_exit(void)
-{
- dbg("%s", __func__);
-
- usb_deregister(&ftdi_driver);
- usb_serial_deregister(&ftdi_sio_device);
+ return -ENOIOCTLCMD;
}
-
-module_init(ftdi_init);
-module_exit(ftdi_exit);
+module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-module_param(vendor, ushort, 0);
-MODULE_PARM_DESC(vendor, "User specified vendor ID (default="
- __MODULE_STRING(FTDI_VID)")");
-module_param(product, ushort, 0);
-MODULE_PARM_DESC(product, "User specified product ID");
-
module_param(ndi_latency_timer, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ndi_latency_timer, "NDI device latency timer override");
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 213fe3d6128..ed58c6fa8db 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -156,7 +156,9 @@ enum ftdi_chip_type {
FT2232C = 4,
FT232RL = 5,
FT2232H = 6,
- FT4232H = 7
+ FT4232H = 7,
+ FT232H = 8,
+ FTX = 9,
};
enum ftdi_sio_baudrate {
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 263f6255119..c4777bc6aee 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -2,7 +2,7 @@
* vendor/product IDs (VID/PID) of devices using FTDI USB serial converters.
* Please keep numerically sorted within individual areas, thanks!
*
- * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais
+ * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais
* from Rudolf Gugler
*
*/
@@ -22,12 +22,16 @@
#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
#define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
+#define FTDI_232H_PID 0x6014 /* Single channel hi-speed device */
+#define FTDI_FTX_PID 0x6015 /* FT-X series (FT201X, FT230X, FT231X, etc) */
#define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */
#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */
/*** third-party PIDs (using FTDI_VID) ***/
+#define FTDI_LUMEL_PD12_PID 0x6002
+
/*
* Marvell OpenRD Base, Client
* http://www.open-rd.org
@@ -38,7 +42,15 @@
/* www.candapter.com Ewert Energy Systems CANdapter device */
#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */
+/*
+ * Texas Instruments XDS100v2 JTAG / BeagleBone A3
+ * http://processors.wiki.ti.com/index.php/XDS100
+ * http://beagleboard.org/bone
+ */
+#define TI_XDS100V2_PID 0xa6d0
+
#define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */
+#define FTDI_EV3CON_PID 0xABB9 /* Mindstorms EV3 Console Adapter */
/* US Interface Navigator (http://www.usinterface.com/) */
#define FTDI_USINT_CAT_PID 0xb810 /* Navigator CAT and 2nd PTT lines */
@@ -53,6 +65,7 @@
/* FTDI 2332C Dual channel device, side A=245 FIFO (JTAG), Side B=RS232 UART */
#define LMI_LM3S_DEVEL_BOARD_PID 0xbcd8
#define LMI_LM3S_EVAL_BOARD_PID 0xbcd9
+#define LMI_LM3S_ICDI_BOARD_PID 0xbcda
#define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmbH */
@@ -62,6 +75,10 @@
#define FTDI_OPENDCC_THROTTLE_PID 0xBFDA
#define FTDI_OPENDCC_GATEWAY_PID 0xBFDB
#define FTDI_OPENDCC_GBM_PID 0xBFDC
+#define FTDI_OPENDCC_GBM_BOOST_PID 0xBFDD
+
+/* NZR SEM 16+ USB (http://www.nzr.de) */
+#define FTDI_NZR_SEM_USB_PID 0xC1E0 /* NZR SEM-LOG16+ */
/*
* RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
@@ -76,7 +93,7 @@
*/
#define FTDI_ASK_RDR400_PID 0xC991 /* ASK RDR 400 series card reader */
-/* www.starting-point-systems.com µChameleon device */
+/* www.starting-point-systems.com µChameleon device */
#define FTDI_MICRO_CHAMELEON_PID 0xCAA0 /* Product Id */
/*
@@ -88,6 +105,8 @@
#define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */
#define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */
+#define FTDI_DISTORTEC_JTAG_LOCK_PICK_PID 0xCFF8
+
/* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */
/* the VID is the standard ftdi vid (FTDI_VID) */
#define FTDI_SCS_DEVICE_0_PID 0xD010 /* SCS PTC-IIusb */
@@ -110,10 +129,14 @@
/* Propox devices */
#define FTDI_PROPOX_JTAGCABLEII_PID 0xD738
+#define FTDI_PROPOX_ISPCABLEIII_PID 0xD739
/* Lenz LI-USB Computer Interface. */
#define FTDI_LENZ_LIUSB_PID 0xD780
+/* Vardaan Enterprises Serial Interface VEUSB422R3 */
+#define FTDI_VARDAAN_PID 0xF070
+
/*
* Xsens Technologies BV products (http://www.xsens.com).
*/
@@ -126,6 +149,11 @@
#define XSENS_CONVERTER_6_PID 0xD38E
#define XSENS_CONVERTER_7_PID 0xD38F
+/**
+ * Zolix (www.zolix.com.cb) product ids
+ */
+#define FTDI_OMNI1509 0xD491 /* Omni1509 embedded USB-serial */
+
/*
* NDI (www.ndigital.com) product ids
*/
@@ -183,7 +211,7 @@
/*
* ELV USB devices submitted by Christian Abt of ELV (www.elv.de).
- * All of these devices use FTDI's vendor ID (0x0403).
+ * Almost all of these devices use FTDI's vendor ID (0x0403).
* Further IDs taken from ELV Windows .inf file.
*
* The previously included PID for the UO 100 module was incorrect.
@@ -191,6 +219,8 @@
*
* Armin Laeuger originally sent the PID for the UM 100 module.
*/
+#define FTDI_ELV_VID 0x1B1F /* ELV AG */
+#define FTDI_ELV_WS300_PID 0xC006 /* eQ3 WS 300 PC II */
#define FTDI_ELV_USR_PID 0xE000 /* ELV Universal-Sound-Recorder */
#define FTDI_ELV_MSM1_PID 0xE001 /* ELV Mini-Sound-Modul */
#define FTDI_ELV_KL100_PID 0xE002 /* ELV Kfz-Leistungsmesser KL 100 */
@@ -285,7 +315,7 @@
/*
* Teratronik product ids.
- * Submitted by O. Wölfelschneider.
+ * Submitted by O. Wƶlfelschneider.
*/
#define FTDI_TERATRONIK_VCP_PID 0xEC88 /* Teratronik device (preferring VCP driver on windows) */
#define FTDI_TERATRONIK_D2XX_PID 0xEC89 /* Teratronik device (preferring D2XX driver on windows) */
@@ -297,6 +327,8 @@
* Hameg HO820 and HO870 interface (using VID 0x0403)
*/
#define HAMEG_HO820_PID 0xed74
+#define HAMEG_HO730_PID 0xed73
+#define HAMEG_HO720_PID 0xed72
#define HAMEG_HO870_PID 0xed71
/*
@@ -332,6 +364,12 @@
/* Sprog II (Andrew Crosland's SprogII DCC interface) */
#define FTDI_SPROG_II 0xF0C8
+/*
+ * Two of the Tagsys RFID Readers
+ */
+#define FTDI_TAGSYS_LP101_PID 0xF0E9 /* Tagsys L-P101 RFID*/
+#define FTDI_TAGSYS_P200X_PID 0xF0EE /* Tagsys Medio P200x RFID*/
+
/* an infrared receiver for user access control with IR tags */
#define FTDI_PIEGROUP_PID 0xF208 /* Product Id */
@@ -346,6 +384,7 @@
*/
#define FTDI_4N_GALAXY_DE_1_PID 0xF3C0
#define FTDI_4N_GALAXY_DE_2_PID 0xF3C1
+#define FTDI_4N_GALAXY_DE_3_PID 0xF3C2
/*
* Linx Technologies product ids
@@ -413,9 +452,11 @@
#define PROTEGO_SPECIAL_4 0xFC73 /* special/unknown device */
/*
- * DSS-20 Sync Station for Sony Ericsson P800
+ * Sony Ericsson product ids
*/
-#define FTDI_DSS20_PID 0xFC82
+#define FTDI_DSS20_PID 0xFC82 /* DSS-20 Sync Station for Sony Ericsson P800 */
+#define FTDI_URBAN_0_PID 0xFC8A /* Sony Ericsson Urban, uart #0 */
+#define FTDI_URBAN_1_PID 0xFC8B /* Sony Ericsson Urban, uart #1 */
/* www.irtrans.de device */
#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
@@ -486,6 +527,21 @@
/* www.canusb.com Lawicel CANUSB device (FTDI_VID) */
#define FTDI_CANUSB_PID 0xFFA8 /* Product Id */
+/*
+ * TavIR AVR product ids (FTDI_VID)
+ */
+#define FTDI_TAVIR_STK500_PID 0xFA33 /* STK500 AVR programmer */
+
+/*
+ * TIAO product ids (FTDI_VID)
+ * http://www.tiaowiki.com/w/Main_Page
+ */
+#define FTDI_TIAO_UMPA_PID 0x8a98 /* TIAO/DIYGADGET USB Multi-Protocol Adapter */
+
+/*
+ * NovaTech product ids (FTDI_VID)
+ */
+#define FTDI_NT_ORIONLXM_PID 0x7c90 /* OrionLXm Substation Automation Platform */
/********************************/
@@ -509,12 +565,37 @@
#define ADI_GNICEPLUS_PID 0xF001
/*
+ * Microchip Technology, Inc.
+ *
+ * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are
+ * used by single function CDC ACM class based firmware demo
+ * applications. The VID/PID has also been used in firmware
+ * emulating FTDI serial chips by:
+ * Hornby Elite - Digital Command Control Console
+ * http://www.hornby.com/hornby-dcc/controllers/
+ */
+#define MICROCHIP_VID 0x04D8
+#define MICROCHIP_USB_BOARD_PID 0x000A /* CDC RS-232 Emulation Demo */
+
+/*
* RATOC REX-USB60F
*/
#define RATOC_VENDOR_ID 0x0584
#define RATOC_PRODUCT_ID_USB60F 0xb020
/*
+ * Infineon Technologies
+ */
+#define INFINEON_VID 0x058b
+#define INFINEON_TRIBOARD_PID 0x0028 /* DAS JTAG TriBoard TC1798 V1.0 */
+
+/*
+ * Acton Research Corp.
+ */
+#define ACTON_VID 0x0647 /* Vendor ID */
+#define ACTON_SPECTRAPRO_PID 0x0100
+
+/*
* Contec products (http://www.contec.com)
* Submitted by Daniel Sangorrin
*/
@@ -522,6 +603,13 @@
#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
/*
+ * Mitsubishi Electric Corp. (http://www.meau.com)
+ * Submitted by Konstantin Holoborodko
+ */
+#define MITSUBISHI_VID 0x06D3
+#define MITSUBISHI_FXUSB_PID 0x0284 /* USB/RS422 converters: FX-USB-AW/-BD */
+
+/*
* Definitions for B&B Electronics products.
*/
#define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */
@@ -563,14 +651,27 @@
/* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */
/* Also rebadged as Dick Smith Electronics (Aus) XH6451 */
/* Also rebadged as SIIG Inc. model US2308 hardware version 1 */
+#define OCT_DK201_PID 0x0103 /* OCT DK201 USB docking station */
#define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */
/*
- * Icom ID-1 digital transceiver
+ * Definitions for Icom Inc. devices
*/
-
-#define ICOM_ID1_VID 0x0C26
-#define ICOM_ID1_PID 0x0004
+#define ICOM_VID 0x0C26 /* Icom vendor ID */
+/* Note: ID-1 is a communications tranceiver for HAM-radio operators */
+#define ICOM_ID_1_PID 0x0004 /* ID-1 USB to RS-232 */
+/* Note: OPC is an Optional cable to connect an Icom Tranceiver */
+#define ICOM_OPC_U_UC_PID 0x0018 /* OPC-478UC, OPC-1122U cloning cable */
+/* Note: ID-RP* devices are Icom Repeater Devices for HAM-radio */
+#define ICOM_ID_RP2C1_PID 0x0009 /* ID-RP2C Asset 1 to RS-232 */
+#define ICOM_ID_RP2C2_PID 0x000A /* ID-RP2C Asset 2 to RS-232 */
+#define ICOM_ID_RP2D_PID 0x000B /* ID-RP2D configuration port*/
+#define ICOM_ID_RP2VT_PID 0x000C /* ID-RP2V Transmit config port */
+#define ICOM_ID_RP2VR_PID 0x000D /* ID-RP2V Receive config port */
+#define ICOM_ID_RP4KVT_PID 0x0010 /* ID-RP4000V Transmit config port */
+#define ICOM_ID_RP4KVR_PID 0x0011 /* ID-RP4000V Receive config port */
+#define ICOM_ID_RP2KVT_PID 0x0012 /* ID-RP2000V Transmit config port */
+#define ICOM_ID_RP2KVR_PID 0x0013 /* ID-RP2000V Receive config port */
/*
* GN Otometrics (http://www.otometrics.com)
@@ -632,6 +733,10 @@
#define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */
#define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */
#define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */
+#define SEALEVEL_2803R_1_PID 0Xa02a /* SeaLINK+8 (2803-ROHS) Port 1+2 */
+#define SEALEVEL_2803R_2_PID 0Xa02b /* SeaLINK+8 (2803-ROHS) Port 3+4 */
+#define SEALEVEL_2803R_3_PID 0Xa02c /* SeaLINK+8 (2803-ROHS) Port 5+6 */
+#define SEALEVEL_2803R_4_PID 0Xa02d /* SeaLINK+8 (2803-ROHS) Port 7+8 */
/*
* JETI SPECTROMETER SPECBOS 1201
@@ -680,6 +785,14 @@
#define TTI_VID 0x103E /* Vendor Id */
#define TTI_QL355P_PID 0x03E8 /* TTi QL355P power supply */
+/*
+ * Newport Cooperation (www.newport.com)
+ */
+#define NEWPORT_VID 0x104D
+#define NEWPORT_AGILIS_PID 0x3000
+#define NEWPORT_CONEX_CC_PID 0x3002
+#define NEWPORT_CONEX_AGP_PID 0x3006
+
/* Interbiometrics USB I/O Board */
/* Developed for Interbiometrics by Rudolf Gugler */
#define INTERBIOMETRICS_VID 0x1209
@@ -691,7 +804,8 @@
* Submitted by Colin Leroy
*/
#define TESTO_VID 0x128D
-#define TESTO_USB_INTERFACE_PID 0x0001
+#define TESTO_1_PID 0x0001
+#define TESTO_3_PID 0x0003
/*
* Mobility Electronics products.
@@ -709,6 +823,7 @@
/* Olimex */
#define OLIMEX_VID 0x15BA
#define OLIMEX_ARM_USB_OCD_PID 0x0003
+#define OLIMEX_ARM_USB_OCD_H_PID 0x002b
/*
* Telldus Technologies
@@ -719,8 +834,68 @@
/*
* RT Systems programming cables for various ham radios
*/
-#define RTSYSTEMS_VID 0x2100 /* Vendor ID */
-#define RTSYSTEMS_SERIAL_VX7_PID 0x9e52 /* Serial converter for VX-7 Radios using FT232RL */
+#define RTSYSTEMS_VID 0x2100 /* Vendor ID */
+#define RTSYSTEMS_USB_S03_PID 0x9001 /* RTS-03 USB to Serial Adapter */
+#define RTSYSTEMS_USB_59_PID 0x9e50 /* USB-59 USB to 8 pin plug */
+#define RTSYSTEMS_USB_57A_PID 0x9e51 /* USB-57A USB to 4pin 3.5mm plug */
+#define RTSYSTEMS_USB_57B_PID 0x9e52 /* USB-57B USB to extended 4pin 3.5mm plug */
+#define RTSYSTEMS_USB_29A_PID 0x9e53 /* USB-29A USB to 3.5mm stereo plug */
+#define RTSYSTEMS_USB_29B_PID 0x9e54 /* USB-29B USB to 6 pin mini din */
+#define RTSYSTEMS_USB_29F_PID 0x9e55 /* USB-29F USB to 6 pin modular plug */
+#define RTSYSTEMS_USB_62B_PID 0x9e56 /* USB-62B USB to 8 pin mini din plug*/
+#define RTSYSTEMS_USB_S01_PID 0x9e57 /* USB-RTS01 USB to 3.5 mm stereo plug*/
+#define RTSYSTEMS_USB_63_PID 0x9e58 /* USB-63 USB to 9 pin female*/
+#define RTSYSTEMS_USB_29C_PID 0x9e59 /* USB-29C USB to 4 pin modular plug*/
+#define RTSYSTEMS_USB_81B_PID 0x9e5A /* USB-81 USB to 8 pin mini din plug*/
+#define RTSYSTEMS_USB_82B_PID 0x9e5B /* USB-82 USB to 2.5 mm stereo plug*/
+#define RTSYSTEMS_USB_K5D_PID 0x9e5C /* USB-K5D USB to 8 pin modular plug*/
+#define RTSYSTEMS_USB_K4Y_PID 0x9e5D /* USB-K4Y USB to 2.5/3.5 mm plugs*/
+#define RTSYSTEMS_USB_K5G_PID 0x9e5E /* USB-K5G USB to 8 pin modular plug*/
+#define RTSYSTEMS_USB_S05_PID 0x9e5F /* USB-RTS05 USB to 2.5 mm stereo plug*/
+#define RTSYSTEMS_USB_60_PID 0x9e60 /* USB-60 USB to 6 pin din*/
+#define RTSYSTEMS_USB_61_PID 0x9e61 /* USB-61 USB to 6 pin mini din*/
+#define RTSYSTEMS_USB_62_PID 0x9e62 /* USB-62 USB to 8 pin mini din*/
+#define RTSYSTEMS_USB_63B_PID 0x9e63 /* USB-63 USB to 9 pin female*/
+#define RTSYSTEMS_USB_64_PID 0x9e64 /* USB-64 USB to 9 pin male*/
+#define RTSYSTEMS_USB_65_PID 0x9e65 /* USB-65 USB to 9 pin female null modem*/
+#define RTSYSTEMS_USB_92_PID 0x9e66 /* USB-92 USB to 12 pin plug*/
+#define RTSYSTEMS_USB_92D_PID 0x9e67 /* USB-92D USB to 12 pin plug data*/
+#define RTSYSTEMS_USB_W5R_PID 0x9e68 /* USB-W5R USB to 8 pin modular plug*/
+#define RTSYSTEMS_USB_A5R_PID 0x9e69 /* USB-A5R USB to 8 pin modular plug*/
+#define RTSYSTEMS_USB_PW1_PID 0x9e6A /* USB-PW1 USB to 8 pin modular plug*/
+
+/*
+ * Physik Instrumente
+ * http://www.physikinstrumente.com/en/products/
+ */
+/* These two devices use the VID of FTDI */
+#define PI_C865_PID 0xe0a0 /* PI C-865 Piezomotor Controller */
+#define PI_C857_PID 0xe0a1 /* PI Encoder Trigger Box */
+
+#define PI_VID 0x1a72 /* Vendor ID */
+#define PI_C866_PID 0x1000 /* PI C-866 Piezomotor Controller */
+#define PI_C663_PID 0x1001 /* PI C-663 Mercury-Step */
+#define PI_C725_PID 0x1002 /* PI C-725 Piezomotor Controller */
+#define PI_E517_PID 0x1005 /* PI E-517 Digital Piezo Controller Operation Module */
+#define PI_C863_PID 0x1007 /* PI C-863 */
+#define PI_E861_PID 0x1008 /* PI E-861 Piezomotor Controller */
+#define PI_C867_PID 0x1009 /* PI C-867 Piezomotor Controller */
+#define PI_E609_PID 0x100D /* PI E-609 Digital Piezo Controller */
+#define PI_E709_PID 0x100E /* PI E-709 Digital Piezo Controller */
+#define PI_100F_PID 0x100F /* PI Digital Piezo Controller */
+#define PI_1011_PID 0x1011 /* PI Digital Piezo Controller */
+#define PI_1012_PID 0x1012 /* PI Motion Controller */
+#define PI_1013_PID 0x1013 /* PI Motion Controller */
+#define PI_1014_PID 0x1014 /* PI Device */
+#define PI_1015_PID 0x1015 /* PI Device */
+#define PI_1016_PID 0x1016 /* PI Digital Servo Module */
+
+/*
+ * Kondo Kagaku Co.Ltd.
+ * http://www.kondo-robot.com/EN
+ */
+#define KONDO_VID 0x165c
+#define KONDO_USB_SERIAL_PID 0x0002
/*
* Bayer Ascensia Contour blood glucose meter USB-converter cable.
@@ -1018,6 +1193,13 @@
#define WHT_PID 0x0004 /* Wireless Handheld Terminal */
/*
+ * STMicroelectonics
+ */
+#define ST_VID 0x0483
+#define ST_STMCLT_2232_PID 0x3746
+#define ST_STMCLT_4232_PID 0x3747
+
+/*
* Papouch products (http://www.papouch.com/)
* Submitted by Folkert van Heusden
*/
@@ -1077,6 +1259,11 @@
#define MJSG_HD_RADIO_PID 0x937C
/*
+ * D.O.Tec products (http://www.directout.eu)
+ */
+#define FTDI_DOTEC_PID 0x9868
+
+/*
* Xverve Signalyzer tools (http://www.signalyzer.com/)
*/
#define XVERVE_SIGNALYZER_ST_PID 0xBCA0
@@ -1107,3 +1294,84 @@
#define QIHARDWARE_VID 0x20B7
#define MILKYMISTONE_JTAGSERIAL_PID 0x0713
+/*
+ * CTI GmbH RS485 Converter http://www.cti-lean.com/
+ */
+/* USB-485-Mini*/
+#define FTDI_CTI_MINI_PID 0xF608
+/* USB-Nano-485*/
+#define FTDI_CTI_NANO_PID 0xF60B
+
+/*
+ * ZeitControl cardsystems GmbH rfid-readers http://zeitconrol.de
+ */
+/* TagTracer MIFARE*/
+#define FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID 0xF7C0
+
+/*
+ * Rainforest Automation
+ */
+/* ZigBee controller */
+#define FTDI_RF_R106 0x8A28
+
+/*
+ * Product: HCP HIT GPRS modem
+ * Manufacturer: HCP d.o.o.
+ * ATI command output: Cinterion MC55i
+ */
+#define FTDI_CINTERION_MC55I_PID 0xA951
+
+/*
+ * Product: Comet Caller ID decoder
+ * Manufacturer: Crucible Technologies
+ */
+#define FTDI_CT_COMET_PID 0x8e08
+
+/*
+ * Product: Z3X Box
+ * Manufacturer: Smart GSM Team
+ */
+#define FTDI_Z3X_PID 0x0011
+
+/*
+ * Product: Cressi PC Interface
+ * Manufacturer: Cressi
+ */
+#define FTDI_CRESSI_PID 0x87d0
+
+/*
+ * Brainboxes devices
+ */
+#define BRAINBOXES_VID 0x05d1
+#define BRAINBOXES_VX_001_PID 0x1001 /* VX-001 ExpressCard 1 Port RS232 */
+#define BRAINBOXES_VX_012_PID 0x1002 /* VX-012 ExpressCard 2 Port RS232 */
+#define BRAINBOXES_VX_023_PID 0x1003 /* VX-023 ExpressCard 1 Port RS422/485 */
+#define BRAINBOXES_VX_034_PID 0x1004 /* VX-034 ExpressCard 2 Port RS422/485 */
+#define BRAINBOXES_US_101_PID 0x1011 /* US-101 1xRS232 */
+#define BRAINBOXES_US_324_PID 0x1013 /* US-324 1xRS422/485 1Mbaud */
+#define BRAINBOXES_US_606_1_PID 0x2001 /* US-606 6 Port RS232 Serial Port 1 and 2 */
+#define BRAINBOXES_US_606_2_PID 0x2002 /* US-606 6 Port RS232 Serial Port 3 and 4 */
+#define BRAINBOXES_US_606_3_PID 0x2003 /* US-606 6 Port RS232 Serial Port 4 and 6 */
+#define BRAINBOXES_US_701_1_PID 0x2011 /* US-701 4xRS232 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_701_2_PID 0x2012 /* US-701 4xRS422 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_279_1_PID 0x2021 /* US-279 8xRS422 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_279_2_PID 0x2022 /* US-279 8xRS422 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_279_3_PID 0x2023 /* US-279 8xRS422 1Mbaud Port 5 and 6 */
+#define BRAINBOXES_US_279_4_PID 0x2024 /* US-279 8xRS422 1Mbaud Port 7 and 8 */
+#define BRAINBOXES_US_346_1_PID 0x3011 /* US-346 4xRS422/485 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_346_2_PID 0x3012 /* US-346 4xRS422/485 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_257_PID 0x5001 /* US-257 2xRS232 1Mbaud */
+#define BRAINBOXES_US_313_PID 0x6001 /* US-313 2xRS422/485 1Mbaud */
+#define BRAINBOXES_US_357_PID 0x7001 /* US_357 1xRS232/422/485 */
+#define BRAINBOXES_US_842_1_PID 0x8001 /* US-842 8xRS422/485 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_842_2_PID 0x8002 /* US-842 8xRS422/485 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_842_3_PID 0x8003 /* US-842 8xRS422/485 1Mbaud Port 5 and 6 */
+#define BRAINBOXES_US_842_4_PID 0x8004 /* US-842 8xRS422/485 1Mbaud Port 7 and 8 */
+#define BRAINBOXES_US_160_1_PID 0x9001 /* US-160 16xRS232 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_160_2_PID 0x9002 /* US-160 16xRS232 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_160_3_PID 0x9003 /* US-160 16xRS232 1Mbaud Port 5 and 6 */
+#define BRAINBOXES_US_160_4_PID 0x9004 /* US-160 16xRS232 1Mbaud Port 7 and 8 */
+#define BRAINBOXES_US_160_5_PID 0x9005 /* US-160 16xRS232 1Mbaud Port 9 and 10 */
+#define BRAINBOXES_US_160_6_PID 0x9006 /* US-160 16xRS232 1Mbaud Port 11 and 12 */
+#define BRAINBOXES_US_160_7_PID 0x9007 /* US-160 16xRS232 1Mbaud Port 13 and 14 */
+#define BRAINBOXES_US_160_8_PID 0x9008 /* US-160 16xRS232 1Mbaud Port 15 and 16 */
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
deleted file mode 100644
index e21ce9ddfc6..00000000000
--- a/drivers/usb/serial/funsoft.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Funsoft Serial USB driver
- *
- * Copyright (C) 2006 Greg Kroah-Hartman <gregkh@suse.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-#include <linux/uaccess.h>
-
-static int debug;
-
-static const struct usb_device_id id_table[] = {
- { USB_DEVICE(0x1404, 0xcddc) },
- { },
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static struct usb_driver funsoft_driver = {
- .name = "funsoft",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
-static struct usb_serial_driver funsoft_device = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "funsoft",
- },
- .id_table = id_table,
- .usb_driver = &funsoft_driver,
- .num_ports = 1,
-};
-
-static int __init funsoft_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&funsoft_device);
- if (retval)
- return retval;
- retval = usb_register(&funsoft_driver);
- if (retval)
- usb_serial_deregister(&funsoft_device);
- return retval;
-}
-
-static void __exit funsoft_exit(void)
-{
- usb_deregister(&funsoft_driver);
- usb_serial_deregister(&funsoft_device);
-}
-
-module_init(funsoft_init);
-module_exit(funsoft_exit);
-MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 26710b18991..db591d19d41 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1,7 +1,7 @@
/*
* Garmin GPS driver
*
- * Copyright (C) 2006-2009 Hermann Kneissel herkne@users.sourceforge.net
+ * Copyright (C) 2006-2011 Hermann Kneissel herkne@gmx.de
*
* The latest version of the driver can be found at
* http://sourceforge.net/projects/garmin-gps/
@@ -25,7 +25,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/tty.h>
@@ -34,16 +33,13 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
/* the mode to be set when the port ist opened */
static int initial_mode = 1;
-/* debug flag */
-static int debug;
-
#define GARMIN_VENDOR_ID 0x091E
/*
@@ -51,7 +47,7 @@ static int debug;
*/
#define VERSION_MAJOR 0
-#define VERSION_MINOR 33
+#define VERSION_MINOR 36
#define _STR(s) #s
#define _DRIVER_VERSION(a, b) "v" _STR(a) "." _STR(b)
@@ -216,17 +212,8 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(GARMIN_VENDOR_ID, 3) },
{ } /* Terminating entry */
};
-
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver garmin_driver = {
- .name = "garmin_gps",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
static inline int getLayerId(const __u8 *usbPacket)
{
@@ -264,17 +251,11 @@ static inline int isAbortTrfCmnd(const unsigned char *buf)
static void send_to_tty(struct usb_serial_port *port,
char *data, unsigned int actual_length)
{
- struct tty_struct *tty = tty_port_tty_get(&port->port);
-
- if (tty && actual_length) {
-
- usb_serial_debug_data(debug, &port->dev,
- __func__, actual_length, data);
-
- tty_insert_flip_string(tty, data, actual_length);
- tty_flip_buffer_push(tty);
+ if (actual_length) {
+ usb_serial_debug_data(&port->dev, __func__, actual_length, data);
+ tty_insert_flip_string(&port->port, data, actual_length);
+ tty_flip_buffer_push(&port->port);
}
- tty_kref_put(tty);
}
@@ -293,14 +274,13 @@ static int pkt_add(struct garmin_data *garmin_data_p,
unsigned long flags;
struct garmin_packet *pkt;
- /* process only packets containg data ... */
+ /* process only packets containing data ... */
if (data_length) {
pkt = kmalloc(sizeof(struct garmin_packet)+data_length,
GFP_ATOMIC);
- if (pkt == NULL) {
- dev_err(&garmin_data_p->port->dev, "out of memory\n");
+ if (!pkt)
return 0;
- }
+
pkt->size = data_length;
memcpy(pkt->data, data, data_length);
@@ -312,8 +292,9 @@ static int pkt_add(struct garmin_data *garmin_data_p,
state = garmin_data_p->state;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
- dbg("%s - added: pkt: %d - %d bytes",
- __func__, pkt->seq, data_length);
+ dev_dbg(&garmin_data_p->port->dev,
+ "%s - added: pkt: %d - %d bytes\n", __func__,
+ pkt->seq, data_length);
/* in serial mode, if someone is waiting for data from
the device, convert and send the next packet to tty. */
@@ -346,8 +327,6 @@ static void pkt_clear(struct garmin_data *garmin_data_p)
unsigned long flags;
struct garmin_packet *result = NULL;
- dbg("%s", __func__);
-
spin_lock_irqsave(&garmin_data_p->lock, flags);
while (!list_empty(&garmin_data_p->pktlist)) {
result = (struct garmin_packet *)garmin_data_p->pktlist.next;
@@ -370,7 +349,8 @@ static int gsp_send_ack(struct garmin_data *garmin_data_p, __u8 pkt_id)
__u8 *ptr = pkt;
unsigned l = 0;
- dbg("%s - pkt-id: 0x%X.", __func__, 0xFF & pkt_id);
+ dev_dbg(&garmin_data_p->port->dev, "%s - pkt-id: 0x%X.\n", __func__,
+ 0xFF & pkt_id);
*ptr++ = DLE;
*ptr++ = ACK;
@@ -410,19 +390,20 @@ static int gsp_send_ack(struct garmin_data *garmin_data_p, __u8 pkt_id)
*/
static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count)
{
+ struct device *dev = &garmin_data_p->port->dev;
+ unsigned long flags;
const __u8 *recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
__le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
-
int cksum = 0;
int n = 0;
int pktid = recpkt[0];
int size = recpkt[1];
- usb_serial_debug_data(debug, &garmin_data_p->port->dev,
- __func__, count-GSP_INITIAL_OFFSET, recpkt);
+ usb_serial_debug_data(&garmin_data_p->port->dev, __func__,
+ count-GSP_INITIAL_OFFSET, recpkt);
if (size != (count-GSP_INITIAL_OFFSET-3)) {
- dbg("%s - invalid size, expected %d bytes, got %d",
+ dev_dbg(dev, "%s - invalid size, expected %d bytes, got %d\n",
__func__, size, (count-GSP_INITIAL_OFFSET-3));
return -EINVPKT;
}
@@ -432,8 +413,8 @@ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count)
/* sanity check, remove after test ... */
if ((__u8 *)&(usbdata[3]) != recpkt) {
- dbg("%s - ptr mismatch %p - %p",
- __func__, &(usbdata[4]), recpkt);
+ dev_dbg(dev, "%s - ptr mismatch %p - %p\n", __func__,
+ &(usbdata[4]), recpkt);
return -EINVPKT;
}
@@ -443,7 +424,7 @@ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count)
}
if ((0xff & (cksum + *recpkt)) != 0) {
- dbg("%s - invalid checksum, expected %02x, got %02x",
+ dev_dbg(dev, "%s - invalid checksum, expected %02x, got %02x\n",
__func__, 0xff & -cksum, 0xff & *recpkt);
return -EINVPKT;
}
@@ -458,7 +439,9 @@ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count)
/* if this was an abort-transfer command, flush all
queued data. */
if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags |= FLAGS_DROP_DATA;
+ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
pkt_clear(garmin_data_p);
}
@@ -488,6 +471,7 @@ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count)
static int gsp_receive(struct garmin_data *garmin_data_p,
const unsigned char *buf, int count)
{
+ struct device *dev = &garmin_data_p->port->dev;
unsigned long flags;
int offs = 0;
int ack_or_nak_seen = 0;
@@ -508,7 +492,7 @@ static int gsp_receive(struct garmin_data *garmin_data_p,
skip = garmin_data_p->flags & FLAGS_GSP_SKIP;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
- /* dbg("%s - dle=%d skip=%d size=%d count=%d",
+ /* dev_dbg(dev, "%s - dle=%d skip=%d size=%d count=%d\n",
__func__, dleSeen, skip, size, count); */
if (size == 0)
@@ -538,12 +522,12 @@ static int gsp_receive(struct garmin_data *garmin_data_p,
if (data == ACK) {
ack_or_nak_seen = ACK;
- dbg("ACK packet complete.");
+ dev_dbg(dev, "ACK packet complete.\n");
} else if (data == NAK) {
ack_or_nak_seen = NAK;
- dbg("NAK packet complete.");
+ dev_dbg(dev, "NAK packet complete.\n");
} else {
- dbg("packet complete - id=0x%X.",
+ dev_dbg(dev, "packet complete - id=0x%X.\n",
0xFF & data);
gsp_rec_packet(garmin_data_p, size);
}
@@ -565,7 +549,7 @@ static int gsp_receive(struct garmin_data *garmin_data_p,
}
if (size >= GPS_IN_BUFSIZ) {
- dbg("%s - packet too large.", __func__);
+ dev_dbg(dev, "%s - packet too large.\n", __func__);
skip = 1;
size = GSP_INITIAL_OFFSET;
dleSeen = 0;
@@ -610,6 +594,7 @@ static int gsp_receive(struct garmin_data *garmin_data_p,
static int gsp_send(struct garmin_data *garmin_data_p,
const unsigned char *buf, int count)
{
+ struct device *dev = &garmin_data_p->port->dev;
const unsigned char *src;
unsigned char *dst;
int pktid = 0;
@@ -618,12 +603,12 @@ static int gsp_send(struct garmin_data *garmin_data_p,
int i = 0;
int k;
- dbg("%s - state %d - %d bytes.", __func__,
- garmin_data_p->state, count);
+ dev_dbg(dev, "%s - state %d - %d bytes.\n", __func__,
+ garmin_data_p->state, count);
k = garmin_data_p->outsize;
if ((k+count) > GPS_OUT_BUFSIZ) {
- dbg("packet too large");
+ dev_dbg(dev, "packet too large\n");
garmin_data_p->outsize = 0;
return -4;
}
@@ -642,28 +627,28 @@ static int gsp_send(struct garmin_data *garmin_data_p,
return 0;
}
- dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__, k, i);
+ dev_dbg(dev, "%s - %d bytes in buffer, %d bytes in pkt.\n", __func__, k, i);
/* garmin_data_p->outbuffer now contains a complete packet */
- usb_serial_debug_data(debug, &garmin_data_p->port->dev,
- __func__, k, garmin_data_p->outbuffer);
+ usb_serial_debug_data(&garmin_data_p->port->dev, __func__, k,
+ garmin_data_p->outbuffer);
garmin_data_p->outsize = 0;
if (GARMIN_LAYERID_APPL != getLayerId(garmin_data_p->outbuffer)) {
- dbg("not an application packet (%d)",
+ dev_dbg(dev, "not an application packet (%d)\n",
getLayerId(garmin_data_p->outbuffer));
return -1;
}
if (pktid > 255) {
- dbg("packet-id %d too large", pktid);
+ dev_dbg(dev, "packet-id %d too large\n", pktid);
return -2;
}
if (datalen > 255) {
- dbg("packet-size %d too large", datalen);
+ dev_dbg(dev, "packet-size %d too large\n", datalen);
return -3;
}
@@ -730,7 +715,7 @@ static int gsp_next_packet(struct garmin_data *garmin_data_p)
struct garmin_packet *pkt = NULL;
while ((pkt = pkt_pop(garmin_data_p)) != NULL) {
- dbg("%s - next pkt: %d", __func__, pkt->seq);
+ dev_dbg(&garmin_data_p->port->dev, "%s - next pkt: %d\n", __func__, pkt->seq);
result = gsp_send(garmin_data_p, pkt->data, pkt->size);
if (result > 0) {
kfree(pkt);
@@ -776,7 +761,9 @@ static int nat_receive(struct garmin_data *garmin_data_p,
if (len >= GPS_IN_BUFSIZ) {
/* seems to be an invalid packet, ignore rest
of input */
- dbg("%s - packet size too large: %d", __func__, len);
+ dev_dbg(&garmin_data_p->port->dev,
+ "%s - packet size too large: %d\n",
+ __func__, len);
garmin_data_p->insize = 0;
count = 0;
result = -EINVPKT;
@@ -857,10 +844,10 @@ static int process_resetdev_request(struct usb_serial_port *port)
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
usb_kill_urb(port->interrupt_in_urb);
- dbg("%s - usb_reset_device", __func__);
+ dev_dbg(&port->dev, "%s - usb_reset_device\n", __func__);
status = usb_reset_device(port->serial->dev);
if (status)
- dbg("%s - usb_reset_device failed: %d",
+ dev_dbg(&port->dev, "%s - usb_reset_device failed: %d\n",
__func__, status);
return status;
}
@@ -897,8 +884,7 @@ static int garmin_init_session(struct usb_serial_port *port)
if (status == 0) {
usb_kill_urb(port->interrupt_in_urb);
- dbg("%s - adding interrupt input", __func__);
- port->interrupt_in_urb->dev = serial->dev;
+ dev_dbg(&serial->dev->dev, "%s - adding interrupt input\n", __func__);
status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (status)
dev_err(&serial->dev->dev,
@@ -911,7 +897,7 @@ static int garmin_init_session(struct usb_serial_port *port)
* gpsbabel/jeeps/gpslibusb.c gusb_reset_toggles()
*/
if (status == 0) {
- dbg("%s - starting session ...", __func__);
+ dev_dbg(&serial->dev->dev, "%s - starting session ...\n", __func__);
garmin_data_p->state = STATE_ACTIVE;
for (i = 0; i < 3; i++) {
@@ -938,12 +924,10 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port)
int status = 0;
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->mode = initial_mode;
garmin_data_p->count = 0;
- garmin_data_p->flags = 0;
+ garmin_data_p->flags &= FLAGS_SESSION_REPLY1_SEEN;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
/* shutdown any bulk reads that might be going on */
@@ -960,20 +944,13 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port)
static void garmin_close(struct usb_serial_port *port)
{
- struct usb_serial *serial = port->serial;
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
- dbg("%s - port %d - mode=%d state=%d flags=0x%X", __func__,
- port->number, garmin_data_p->mode,
- garmin_data_p->state, garmin_data_p->flags);
+ dev_dbg(&port->dev, "%s - mode=%d state=%d flags=0x%X\n",
+ __func__, garmin_data_p->mode, garmin_data_p->state,
+ garmin_data_p->flags);
- if (!serial)
- return;
-
- mutex_lock(&port->serial->disc_mutex);
-
- if (!port->serial->disconnected)
- garmin_clear(garmin_data_p);
+ garmin_clear(garmin_data_p);
/* shutdown our urbs */
usb_kill_urb(port->read_urb);
@@ -982,8 +959,6 @@ static void garmin_close(struct usb_serial_port *port)
/* keep reset state so we know that we must start a new session */
if (garmin_data_p->state != STATE_RESET)
garmin_data_p->state = STATE_DISCONNECTED;
-
- mutex_unlock(&port->serial->disc_mutex);
}
@@ -995,8 +970,6 @@ static void garmin_write_bulk_callback(struct urb *urb)
struct garmin_data *garmin_data_p =
usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
-
if (GARMIN_LAYERID_APPL == getLayerId(urb->transfer_buffer)) {
if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
@@ -1026,29 +999,23 @@ static int garmin_write_bulk(struct usb_serial_port *port,
unsigned char *buffer;
int status;
- dbg("%s - port %d, state %d", __func__, port->number,
- garmin_data_p->state);
-
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags &= ~FLAGS_DROP_DATA;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
buffer = kmalloc(count, GFP_ATOMIC);
- if (!buffer) {
- dev_err(&port->dev, "out of memory\n");
+ if (!buffer)
return -ENOMEM;
- }
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
- dev_err(&port->dev, "no more free urbs\n");
kfree(buffer);
return -ENOMEM;
}
memcpy(buffer, buf, count);
- usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+ usb_serial_debug_data(&port->dev, __func__, count, buffer);
usb_fill_bulk_urb(urb, serial->dev,
usb_sndbulkpipe(serial->dev,
@@ -1089,11 +1056,12 @@ static int garmin_write_bulk(struct usb_serial_port *port,
static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
+ struct device *dev = &port->dev;
int pktid, pktsiz, len;
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
__le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
- usb_serial_debug_data(debug, &port->dev, __func__, count, buf);
+ usb_serial_debug_data(dev, __func__, count, buf);
if (garmin_data_p->state == STATE_RESET)
return -EIO;
@@ -1113,27 +1081,18 @@ static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port,
&& GARMIN_LAYERID_PRIVATE ==
getLayerId(garmin_data_p->privpkt)) {
- dbg("%s - processing private request %d",
+ dev_dbg(dev, "%s - processing private request %d\n",
__func__, pktid);
/* drop all unfinished transfers */
garmin_clear(garmin_data_p);
switch (pktid) {
-
- case PRIV_PKTID_SET_DEBUG:
- if (pktsiz != 4)
- return -EINVPKT;
- debug = __le32_to_cpu(privpkt[3]);
- dbg("%s - debug level set to 0x%X",
- __func__, debug);
- break;
-
case PRIV_PKTID_SET_MODE:
if (pktsiz != 4)
return -EINVPKT;
garmin_data_p->mode = __le32_to_cpu(privpkt[3]);
- dbg("%s - mode set to %d",
+ dev_dbg(dev, "%s - mode set to %d\n",
__func__, garmin_data_p->mode);
break;
@@ -1149,7 +1108,7 @@ static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port,
if (pktsiz != 4)
return -EINVPKT;
initial_mode = __le32_to_cpu(privpkt[3]);
- dbg("%s - initial_mode set to %d",
+ dev_dbg(dev, "%s - initial_mode set to %d\n",
__func__,
garmin_data_p->mode);
break;
@@ -1178,13 +1137,14 @@ static int garmin_write_room(struct tty_struct *tty)
static void garmin_read_process(struct garmin_data *garmin_data_p,
- unsigned char *data, unsigned data_length)
+ unsigned char *data, unsigned data_length,
+ int bulk_data)
{
unsigned long flags;
if (garmin_data_p->flags & FLAGS_DROP_DATA) {
- /* abort-transfer cmd is actice */
- dbg("%s - pkt dropped", __func__);
+ /* abort-transfer cmd is active */
+ dev_dbg(&garmin_data_p->port->dev, "%s - pkt dropped\n", __func__);
} else if (garmin_data_p->state != STATE_DISCONNECTED &&
garmin_data_p->state != STATE_RESET) {
@@ -1193,7 +1153,8 @@ static void garmin_read_process(struct garmin_data *garmin_data_p,
send it directly to the tty port */
if (garmin_data_p->flags & FLAGS_QUEUING) {
pkt_add(garmin_data_p, data, data_length);
- } else if (getLayerId(data) == GARMIN_LAYERID_APPL) {
+ } else if (bulk_data ||
+ getLayerId(data) == GARMIN_LAYERID_APPL) {
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags |= APP_RESP_SEEN;
@@ -1215,29 +1176,20 @@ static void garmin_read_bulk_callback(struct urb *urb)
{
unsigned long flags;
struct usb_serial_port *port = urb->context;
- struct usb_serial *serial = port->serial;
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
int retval;
- dbg("%s - port %d", __func__, port->number);
-
- if (!serial) {
- dbg("%s - bad serial pointer, exiting", __func__);
- return;
- }
-
if (status) {
- dbg("%s - nonzero read bulk status received: %d",
+ dev_dbg(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n",
__func__, status);
return;
}
- usb_serial_debug_data(debug, &port->dev,
- __func__, urb->actual_length, data);
+ usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
- garmin_read_process(garmin_data_p, data, urb->actual_length);
+ garmin_read_process(garmin_data_p, data, urb->actual_length, 1);
if (urb->actual_length == 0 &&
0 != (garmin_data_p->flags & FLAGS_BULK_IN_RESTART)) {
@@ -1255,11 +1207,11 @@ static void garmin_read_bulk_callback(struct urb *urb)
retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (retval)
dev_err(&port->dev,
- "%s - failed resubmitting read urb, "
- "error %d\n", __func__, retval);
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, retval);
}
} else {
- dbg("%s - end of bulk data", __func__);
+ dev_dbg(&port->dev, "%s - end of bulk data\n", __func__);
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags &= ~FLAGS_BULK_IN_ACTIVE;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
@@ -1272,7 +1224,6 @@ static void garmin_read_int_callback(struct urb *urb)
unsigned long flags;
int retval;
struct usb_serial_port *port = urb->context;
- struct usb_serial *serial = port->serial;
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
@@ -1285,33 +1236,27 @@ static void garmin_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
+ dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n",
__func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
+ dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d\n",
__func__, status);
return;
}
- usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, urb->transfer_buffer);
+ usb_serial_debug_data(&port->dev, __func__, urb->actual_length,
+ urb->transfer_buffer);
if (urb->actual_length == sizeof(GARMIN_BULK_IN_AVAIL_REPLY) &&
0 == memcmp(data, GARMIN_BULK_IN_AVAIL_REPLY,
sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) {
- dbg("%s - bulk data available.", __func__);
+ dev_dbg(&port->dev, "%s - bulk data available.\n", __func__);
if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
/* bulk data available */
- usb_fill_bulk_urb(port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev,
- port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer,
- port->read_urb->transfer_buffer_length,
- garmin_read_bulk_callback, port);
retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (retval) {
dev_err(&port->dev,
@@ -1342,13 +1287,12 @@ static void garmin_read_int_callback(struct urb *urb)
garmin_data_p->serial_num = __le32_to_cpup(
(__le32 *)(data+GARMIN_PKTHDR_LENGTH));
- dbg("%s - start-of-session reply seen - serial %u.",
+ dev_dbg(&port->dev, "%s - start-of-session reply seen - serial %u.\n",
__func__, garmin_data_p->serial_num);
}
- garmin_read_process(garmin_data_p, data, urb->actual_length);
+ garmin_read_process(garmin_data_p, data, urb->actual_length, 0);
- port->interrupt_in_urb->dev = port->serial->dev;
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
dev_err(&urb->dev->dev,
@@ -1389,7 +1333,6 @@ static void garmin_throttle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
/* set flag, data received will be put into a queue
for later processing */
spin_lock_irq(&garmin_data_p->lock);
@@ -1404,7 +1347,6 @@ static void garmin_unthrottle(struct tty_struct *tty)
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
int status;
- dbg("%s - port %d", __func__, port->number);
spin_lock_irq(&garmin_data_p->lock);
garmin_data_p->flags &= ~FLAGS_THROTTLED;
spin_unlock_irq(&garmin_data_p->lock);
@@ -1440,19 +1382,15 @@ static void timeout_handler(unsigned long data)
-static int garmin_attach(struct usb_serial *serial)
+static int garmin_port_probe(struct usb_serial_port *port)
{
- int status = 0;
- struct usb_serial_port *port = serial->port[0];
- struct garmin_data *garmin_data_p = NULL;
-
- dbg("%s", __func__);
+ int status;
+ struct garmin_data *garmin_data_p;
garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
- if (garmin_data_p == NULL) {
- dev_err(&port->dev, "%s - Out of memory\n", __func__);
+ if (!garmin_data_p)
return -ENOMEM;
- }
+
init_timer(&garmin_data_p->timer);
spin_lock_init(&garmin_data_p->lock);
INIT_LIST_HEAD(&garmin_data_p->pktlist);
@@ -1461,6 +1399,7 @@ static int garmin_attach(struct usb_serial *serial)
garmin_data_p->timer.function = timeout_handler;
garmin_data_p->port = port;
garmin_data_p->state = 0;
+ garmin_data_p->flags = 0;
garmin_data_p->count = 0;
usb_set_serial_port_data(port, garmin_data_p);
@@ -1470,26 +1409,14 @@ static int garmin_attach(struct usb_serial *serial)
}
-static void garmin_disconnect(struct usb_serial *serial)
+static int garmin_port_remove(struct usb_serial_port *port)
{
- struct usb_serial_port *port = serial->port[0];
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
- dbg("%s", __func__);
-
usb_kill_urb(port->interrupt_in_urb);
del_timer_sync(&garmin_data_p->timer);
-}
-
-
-static void garmin_release(struct usb_serial *serial)
-{
- struct usb_serial_port *port = serial->port[0];
- struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
-
- dbg("%s", __func__);
-
kfree(garmin_data_p);
+ return 0;
}
@@ -1500,16 +1427,14 @@ static struct usb_serial_driver garmin_device = {
.name = "garmin_gps",
},
.description = "Garmin GPS usb/tty",
- .usb_driver = &garmin_driver,
.id_table = id_table,
.num_ports = 1,
.open = garmin_open,
.close = garmin_close,
.throttle = garmin_throttle,
.unthrottle = garmin_unthrottle,
- .attach = garmin_attach,
- .disconnect = garmin_disconnect,
- .release = garmin_release,
+ .port_probe = garmin_port_probe,
+ .port_remove = garmin_port_remove,
.write = garmin_write,
.write_room = garmin_write_room,
.write_bulk_callback = garmin_write_bulk_callback,
@@ -1517,47 +1442,15 @@ static struct usb_serial_driver garmin_device = {
.read_int_callback = garmin_read_int_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &garmin_device, NULL
+};
-
-static int __init garmin_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&garmin_device);
- if (retval)
- goto failed_garmin_register;
- retval = usb_register(&garmin_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-failed_usb_register:
- usb_serial_deregister(&garmin_device);
-failed_garmin_register:
- return retval;
-}
-
-
-static void __exit garmin_exit(void)
-{
- usb_deregister(&garmin_driver);
- usb_serial_deregister(&garmin_device);
-}
-
-
-
-
-module_init(garmin_init);
-module_exit(garmin_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-module_param(debug, bool, S_IWUSR | S_IRUGO);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
module_param(initial_mode, int, S_IRUGO);
MODULE_PARM_DESC(initial_mode, "Initial mode");
-
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index e6833e216fc..1bd192290b0 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -1,13 +1,12 @@
/*
* USB Serial Converter Generic functions
*
- * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com)
+ * Copyright (C) 2010 - 2013 Johan Hovold (jhovold@gmail.com)
* Copyright (C) 1999 - 2002 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 version
* 2 as published by the Free Software Foundation.
- *
*/
#include <linux/kernel.h>
@@ -24,13 +23,8 @@
#include <linux/kfifo.h>
#include <linux/serial.h>
-static int debug;
-
#ifdef CONFIG_USB_SERIAL_GENERIC
-static int generic_probe(struct usb_interface *interface,
- const struct usb_device_id *id);
-
static __u16 vendor = 0x05f9;
static __u16 product = 0xffff;
@@ -42,68 +36,36 @@ MODULE_PARM_DESC(product, "User specified USB idProduct");
static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
-/* we want to look at all devices, as the vendor/product id can change
- * depending on the command line argument */
-static const struct usb_device_id generic_serial_ids[] = {
- {.driver_info = 42},
- {}
-};
-
-static struct usb_driver generic_driver = {
- .name = "usbserial_generic",
- .probe = generic_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = generic_serial_ids,
- .no_dynamic_id = 1,
-};
-
-/* All of the device info needed for the Generic Serial Converter */
struct usb_serial_driver usb_serial_generic_device = {
.driver = {
.owner = THIS_MODULE,
.name = "generic",
},
.id_table = generic_device_ids,
- .usb_driver = &generic_driver,
.num_ports = 1,
- .disconnect = usb_serial_generic_disconnect,
- .release = usb_serial_generic_release,
.throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle,
.resume = usb_serial_generic_resume,
};
-static int generic_probe(struct usb_interface *interface,
- const struct usb_device_id *id)
-{
- const struct usb_device_id *id_pattern;
+static struct usb_serial_driver * const serial_drivers[] = {
+ &usb_serial_generic_device, NULL
+};
- id_pattern = usb_match_id(interface, generic_device_ids);
- if (id_pattern != NULL)
- return usb_serial_probe(interface, id);
- return -ENODEV;
-}
#endif
-int usb_serial_generic_register(int _debug)
+int usb_serial_generic_register(void)
{
int retval = 0;
- debug = _debug;
#ifdef CONFIG_USB_SERIAL_GENERIC
generic_device_ids[0].idVendor = vendor;
generic_device_ids[0].idProduct = product;
generic_device_ids[0].match_flags =
USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
- /* register our generic driver with ourselves */
- retval = usb_serial_register(&usb_serial_generic_device);
- if (retval)
- goto exit;
- retval = usb_register(&generic_driver);
- if (retval)
- usb_serial_deregister(&usb_serial_generic_device);
-exit:
+ retval = usb_serial_register_drivers(serial_drivers,
+ "usbserial_generic", generic_device_ids);
#endif
return retval;
}
@@ -111,9 +73,7 @@ exit:
void usb_serial_generic_deregister(void)
{
#ifdef CONFIG_USB_SERIAL_GENERIC
- /* remove our generic driver */
- usb_deregister(&generic_driver);
- usb_serial_deregister(&usb_serial_generic_device);
+ usb_serial_deregister_drivers(serial_drivers);
#endif
}
@@ -122,50 +82,35 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port
int result = 0;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
- /* clear the throttle flags */
spin_lock_irqsave(&port->lock, flags);
port->throttled = 0;
port->throttle_req = 0;
spin_unlock_irqrestore(&port->lock, flags);
- /* if we have a bulk endpoint, start reading from it */
if (port->bulk_in_size)
- result = usb_serial_generic_submit_read_urb(port, GFP_KERNEL);
+ result = usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);
return result;
}
EXPORT_SYMBOL_GPL(usb_serial_generic_open);
-static void generic_cleanup(struct usb_serial_port *port)
+void usb_serial_generic_close(struct usb_serial_port *port)
{
- struct usb_serial *serial = port->serial;
unsigned long flags;
int i;
- dbg("%s - port %d", __func__, port->number);
-
- if (serial->dev) {
- /* shutdown any bulk transfers that might be going on */
- if (port->bulk_out_size) {
- usb_kill_urb(port->write_urb);
- for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
- usb_kill_urb(port->write_urbs[i]);
+ if (port->bulk_out_size) {
+ for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
+ usb_kill_urb(port->write_urbs[i]);
- spin_lock_irqsave(&port->lock, flags);
- kfifo_reset_out(&port->write_fifo);
- spin_unlock_irqrestore(&port->lock, flags);
- }
- if (port->bulk_in_size)
- usb_kill_urb(port->read_urb);
+ spin_lock_irqsave(&port->lock, flags);
+ kfifo_reset_out(&port->write_fifo);
+ spin_unlock_irqrestore(&port->lock, flags);
+ }
+ if (port->bulk_in_size) {
+ for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
+ usb_kill_urb(port->read_urbs[i]);
}
-}
-
-void usb_serial_generic_close(struct usb_serial_port *port)
-{
- dbg("%s - port %d", __func__, port->number);
- generic_cleanup(port);
}
EXPORT_SYMBOL_GPL(usb_serial_generic_close);
@@ -176,12 +121,16 @@ int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port,
}
/**
- * usb_serial_generic_write_start - kick off an URB write
- * @port: Pointer to the &struct usb_serial_port data
+ * usb_serial_generic_write_start - start writing buffered data
+ * @port: usb-serial port
+ * @mem_flags: flags to use for memory allocations
*
- * Returns zero on success, or a negative errno value
+ * Serialised using USB_SERIAL_WRITE_BUSY flag.
+ *
+ * Return: Zero on success or if busy, otherwise a negative errno value.
*/
-static int usb_serial_generic_write_start(struct usb_serial_port *port)
+int usb_serial_generic_write_start(struct usb_serial_port *port,
+ gfp_t mem_flags)
{
struct urb *urb;
int count, result;
@@ -206,16 +155,15 @@ retry:
urb->transfer_buffer,
port->bulk_out_size);
urb->transfer_buffer_length = count;
- usb_serial_debug_data(debug, &port->dev, __func__, count,
- urb->transfer_buffer);
+ usb_serial_debug_data(&port->dev, __func__, count, urb->transfer_buffer);
spin_lock_irqsave(&port->lock, flags);
port->tx_bytes += count;
spin_unlock_irqrestore(&port->lock, flags);
clear_bit(i, &port->write_urbs_free);
- result = usb_submit_urb(urb, GFP_ATOMIC);
+ result = usb_submit_urb(urb, mem_flags);
if (result) {
- dev_err(&port->dev, "%s - error submitting urb: %d\n",
+ dev_err_console(port, "%s - error submitting urb: %d\n",
__func__, result);
set_bit(i, &port->write_urbs_free);
spin_lock_irqsave(&port->lock, flags);
@@ -226,35 +174,25 @@ retry:
return result;
}
- /* Try sending off another urb, unless in irq context (in which case
- * there will be no free urb). */
- if (!in_irq())
- goto retry;
-
- clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags);
-
- return 0;
+ goto retry; /* try sending off another urb */
}
+EXPORT_SYMBOL_GPL(usb_serial_generic_write_start);
/**
- * usb_serial_generic_write - generic write function for serial USB devices
- * @tty: Pointer to &struct tty_struct for the device
- * @port: Pointer to the &usb_serial_port structure for the device
- * @buf: Pointer to the data to write
- * @count: Number of bytes to write
+ * usb_serial_generic_write - generic write function
+ * @tty: tty for the port
+ * @port: usb-serial port
+ * @buf: data to write
+ * @count: number of bytes to write
*
- * Returns the number of characters actually written, which may be anything
- * from zero to @count. If an error occurs, it returns the negative errno
- * value.
+ * Return: The number of characters buffered, which may be anything from
+ * zero to @count, or a negative errno value.
*/
int usb_serial_generic_write(struct tty_struct *tty,
struct usb_serial_port *port, const unsigned char *buf, int count)
{
int result;
- dbg("%s - port %d", __func__, port->number);
-
- /* only do something if we have a bulk out endpoint */
if (!port->bulk_out_size)
return -ENODEV;
@@ -262,7 +200,7 @@ int usb_serial_generic_write(struct tty_struct *tty,
return 0;
count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock);
- result = usb_serial_generic_write_start(port);
+ result = usb_serial_generic_write_start(port, GFP_ATOMIC);
if (result)
return result;
@@ -276,8 +214,6 @@ int usb_serial_generic_write_room(struct tty_struct *tty)
unsigned long flags;
int room;
- dbg("%s - port %d", __func__, port->number);
-
if (!port->bulk_out_size)
return 0;
@@ -285,7 +221,7 @@ int usb_serial_generic_write_room(struct tty_struct *tty)
room = kfifo_avail(&port->write_fifo);
spin_unlock_irqrestore(&port->lock, flags);
- dbg("%s - returns %d", __func__, room);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, room);
return room;
}
@@ -295,8 +231,6 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
unsigned long flags;
int chars;
- dbg("%s - port %d", __func__, port->number);
-
if (!port->bulk_out_size)
return 0;
@@ -304,51 +238,109 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
chars = kfifo_len(&port->write_fifo) + port->tx_bytes;
spin_unlock_irqrestore(&port->lock, flags);
- dbg("%s - returns %d", __func__, chars);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
return chars;
}
+EXPORT_SYMBOL_GPL(usb_serial_generic_chars_in_buffer);
-int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
+void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ unsigned int bps;
+ unsigned long period;
+ unsigned long expire;
+
+ bps = tty_get_baud_rate(tty);
+ if (!bps)
+ bps = 9600; /* B0 */
+ /*
+ * Use a poll-period of roughly the time it takes to send one
+ * character or at least one jiffy.
+ */
+ period = max_t(unsigned long, (10 * HZ / bps), 1);
+ period = min_t(unsigned long, period, timeout);
+
+ dev_dbg(&port->dev, "%s - timeout = %u ms, period = %u ms\n",
+ __func__, jiffies_to_msecs(timeout),
+ jiffies_to_msecs(period));
+ expire = jiffies + timeout;
+ while (!port->serial->type->tx_empty(port)) {
+ schedule_timeout_interruptible(period);
+ if (signal_pending(current))
+ break;
+ if (time_after(jiffies, expire))
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(usb_serial_generic_wait_until_sent);
+
+static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
+ int index, gfp_t mem_flags)
+{
+ int res;
+
+ if (!test_and_clear_bit(index, &port->read_urbs_free))
+ return 0;
+
+ dev_dbg(&port->dev, "%s - urb %d\n", __func__, index);
+
+ res = usb_submit_urb(port->read_urbs[index], mem_flags);
+ if (res) {
+ if (res != -EPERM) {
+ dev_err(&port->dev,
+ "%s - usb_submit_urb failed: %d\n",
+ __func__, res);
+ }
+ set_bit(index, &port->read_urbs_free);
+ return res;
+ }
+
+ return 0;
+}
+
+int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port,
gfp_t mem_flags)
{
- int result;
+ int res;
+ int i;
- result = usb_submit_urb(port->read_urb, mem_flags);
- if (result && result != -EPERM) {
- dev_err(&port->dev, "%s - error submitting urb: %d\n",
- __func__, result);
+ for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
+ res = usb_serial_generic_submit_read_urb(port, i, mem_flags);
+ if (res)
+ goto err;
}
- return result;
+
+ return 0;
+err:
+ for (; i >= 0; --i)
+ usb_kill_urb(port->read_urbs[i]);
+
+ return res;
}
-EXPORT_SYMBOL_GPL(usb_serial_generic_submit_read_urb);
+EXPORT_SYMBOL_GPL(usb_serial_generic_submit_read_urbs);
void usb_serial_generic_process_read_urb(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
- struct tty_struct *tty;
char *ch = (char *)urb->transfer_buffer;
int i;
if (!urb->actual_length)
return;
-
- tty = tty_port_tty_get(&port->port);
- if (!tty)
- return;
-
- /* The per character mucking around with sysrq path it too slow for
- stuff like 3G modems, so shortcircuit it in the 99.9999999% of cases
- where the USB serial is not a console anyway */
- if (!port->port.console || !port->sysrq)
- tty_insert_flip_string(tty, ch, urb->actual_length);
- else {
+ /*
+ * The per character mucking around with sysrq path it too slow for
+ * stuff like 3G modems, so shortcircuit it in the 99.9999999% of
+ * cases where the USB serial is not a console anyway.
+ */
+ if (!port->port.console || !port->sysrq) {
+ tty_insert_flip_string(&port->port, ch, urb->actual_length);
+ } else {
for (i = 0; i < urb->actual_length; i++, ch++) {
if (!usb_serial_handle_sysrq_char(port, *ch))
- tty_insert_flip_char(tty, *ch, TTY_NORMAL);
+ tty_insert_flip_char(&port->port, *ch, TTY_NORMAL);
}
}
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
+ tty_flip_buffer_push(&port->port);
}
EXPORT_SYMBOL_GPL(usb_serial_generic_process_read_urb);
@@ -356,29 +348,49 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
- int status = urb->status;
unsigned long flags;
+ int i;
- dbg("%s - port %d", __func__, port->number);
-
- if (unlikely(status != 0)) {
- dbg("%s - nonzero read bulk status received: %d",
- __func__, status);
+ for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
+ if (urb == port->read_urbs[i])
+ break;
+ }
+ set_bit(i, &port->read_urbs_free);
+
+ dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i,
+ urb->actual_length);
+ switch (urb->status) {
+ case 0:
+ break;
+ case -ENOENT:
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ dev_dbg(&port->dev, "%s - urb stopped: %d\n",
+ __func__, urb->status);
+ return;
+ case -EPIPE:
+ dev_err(&port->dev, "%s - urb stopped: %d\n",
+ __func__, urb->status);
return;
+ default:
+ dev_err(&port->dev, "%s - nonzero urb status: %d\n",
+ __func__, urb->status);
+ goto resubmit;
}
- usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, data);
+ usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
port->serial->type->process_read_urb(urb);
+resubmit:
/* Throttle the device if requested by tty */
spin_lock_irqsave(&port->lock, flags);
port->throttled = port->throttle_req;
if (!port->throttled) {
spin_unlock_irqrestore(&port->lock, flags);
- usb_serial_generic_submit_read_urb(port, GFP_ATOMIC);
- } else
+ usb_serial_generic_submit_read_urb(port, i, GFP_ATOMIC);
+ } else {
spin_unlock_irqrestore(&port->lock, flags);
+ }
}
EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
@@ -386,30 +398,38 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)
{
unsigned long flags;
struct usb_serial_port *port = urb->context;
- int status = urb->status;
int i;
- dbg("%s - port %d", __func__, port->number);
-
- for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
+ for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) {
if (port->write_urbs[i] == urb)
break;
-
+ }
spin_lock_irqsave(&port->lock, flags);
port->tx_bytes -= urb->transfer_buffer_length;
set_bit(i, &port->write_urbs_free);
spin_unlock_irqrestore(&port->lock, flags);
- if (status) {
- dbg("%s - non-zero urb status: %d", __func__, status);
-
- spin_lock_irqsave(&port->lock, flags);
- kfifo_reset_out(&port->write_fifo);
- spin_unlock_irqrestore(&port->lock, flags);
- } else {
- usb_serial_generic_write_start(port);
+ switch (urb->status) {
+ case 0:
+ break;
+ case -ENOENT:
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ dev_dbg(&port->dev, "%s - urb stopped: %d\n",
+ __func__, urb->status);
+ return;
+ case -EPIPE:
+ dev_err_console(port, "%s - urb stopped: %d\n",
+ __func__, urb->status);
+ return;
+ default:
+ dev_err_console(port, "%s - nonzero urb status: %d\n",
+ __func__, urb->status);
+ goto resubmit;
}
+resubmit:
+ usb_serial_generic_write_start(port, GFP_ATOMIC);
usb_serial_port_softint(port);
}
EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
@@ -419,10 +439,6 @@ void usb_serial_generic_throttle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
- /* Set the throttle request flag. It will be picked up
- * by usb_serial_generic_read_bulk_callback(). */
spin_lock_irqsave(&port->lock, flags);
port->throttle_req = 1;
spin_unlock_irqrestore(&port->lock, flags);
@@ -434,19 +450,92 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
int was_throttled;
- dbg("%s - port %d", __func__, port->number);
-
- /* Clear the throttle flags */
spin_lock_irq(&port->lock);
was_throttled = port->throttled;
port->throttled = port->throttle_req = 0;
spin_unlock_irq(&port->lock);
if (was_throttled)
- usb_serial_generic_submit_read_urb(port, GFP_KERNEL);
+ usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);
}
EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle);
+static bool usb_serial_generic_msr_changed(struct tty_struct *tty,
+ unsigned long arg, struct async_icount *cprev)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct async_icount cnow;
+ unsigned long flags;
+ bool ret;
+
+ /*
+ * Use tty-port initialised flag to detect all hangups including the
+ * one generated at USB-device disconnect.
+ */
+ if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+ return true;
+
+ spin_lock_irqsave(&port->lock, flags);
+ cnow = port->icount; /* atomic copy*/
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ ret = ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev->dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts));
+
+ *cprev = cnow;
+
+ return ret;
+}
+
+int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct async_icount cnow;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&port->lock, flags);
+ cnow = port->icount; /* atomic copy */
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ ret = wait_event_interruptible(port->port.delta_msr_wait,
+ usb_serial_generic_msr_changed(tty, arg, &cnow));
+ if (!ret && !test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+ ret = -EIO;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(usb_serial_generic_tiocmiwait);
+
+int usb_serial_generic_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct async_icount cnow;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ cnow = port->icount; /* atomic copy */
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->tx = cnow.tx;
+ icount->rx = cnow.rx;
+ icount->frame = cnow.frame;
+ icount->parity = cnow.parity;
+ icount->overrun = cnow.overrun;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_serial_generic_get_icount);
+
#ifdef CONFIG_MAGIC_SYSRQ
int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
{
@@ -479,6 +568,36 @@ int usb_serial_handle_break(struct usb_serial_port *port)
}
EXPORT_SYMBOL_GPL(usb_serial_handle_break);
+/**
+ * usb_serial_handle_dcd_change - handle a change of carrier detect state
+ * @port: usb-serial port
+ * @tty: tty for the port
+ * @status: new carrier detect status, nonzero if active
+ */
+void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
+ struct tty_struct *tty, unsigned int status)
+{
+ struct tty_port *port = &usb_port->port;
+
+ dev_dbg(&usb_port->dev, "%s - status %d\n", __func__, status);
+
+ if (tty) {
+ struct tty_ldisc *ld = tty_ldisc_ref(tty);
+
+ if (ld) {
+ if (ld->ops->dcd_change)
+ ld->ops->dcd_change(tty, status);
+ tty_ldisc_deref(ld);
+ }
+ }
+
+ if (status)
+ wake_up_interruptible(&port->open_wait);
+ else if (tty && !C_CLOCAL(tty))
+ tty_hangup(tty);
+}
+EXPORT_SYMBOL_GPL(usb_serial_handle_dcd_change);
+
int usb_serial_generic_resume(struct usb_serial *serial)
{
struct usb_serial_port *port;
@@ -489,14 +608,15 @@ int usb_serial_generic_resume(struct usb_serial *serial)
if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
continue;
- if (port->read_urb) {
- r = usb_submit_urb(port->read_urb, GFP_NOIO);
+ if (port->bulk_in_size) {
+ r = usb_serial_generic_submit_read_urbs(port,
+ GFP_NOIO);
if (r < 0)
c++;
}
if (port->bulk_out_size) {
- r = usb_serial_generic_write_start(port);
+ r = usb_serial_generic_write_start(port, GFP_NOIO);
if (r < 0)
c++;
}
@@ -505,20 +625,3 @@ int usb_serial_generic_resume(struct usb_serial *serial)
return c ? -EIO : 0;
}
EXPORT_SYMBOL_GPL(usb_serial_generic_resume);
-
-void usb_serial_generic_disconnect(struct usb_serial *serial)
-{
- int i;
-
- dbg("%s", __func__);
-
- /* stop reads and writes on all ports */
- for (i = 0; i < serial->num_ports; ++i)
- generic_cleanup(serial->port[i]);
-}
-EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect);
-
-void usb_serial_generic_release(struct usb_serial *serial)
-{
- dbg("%s", __func__);
-}
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
deleted file mode 100644
index 809379159b0..00000000000
--- a/drivers/usb/serial/hp4x.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * HP4x Calculators Serial USB driver
- *
- * Copyright (C) 2005 Arthur Huillet (ahuillet@users.sf.net)
- * Copyright (C) 2001-2005 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.
- *
- * See Documentation/usb/usb-serial.txt for more information on using this
- * driver
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.00"
-#define DRIVER_DESC "HP4x (48/49) Generic Serial driver"
-
-#define HP_VENDOR_ID 0x03f0
-#define HP49GP_PRODUCT_ID 0x0121
-
-static const struct usb_device_id id_table[] = {
- { USB_DEVICE(HP_VENDOR_ID, HP49GP_PRODUCT_ID) },
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static struct usb_driver hp49gp_driver = {
- .name = "hp4X",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
-static struct usb_serial_driver hp49gp_device = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "hp4X",
- },
- .id_table = id_table,
- .usb_driver = &hp49gp_driver,
- .num_ports = 1,
-};
-
-static int __init hp49gp_init(void)
-{
- int retval;
- retval = usb_serial_register(&hp49gp_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&hp49gp_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&hp49gp_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit hp49gp_exit(void)
-{
- usb_deregister(&hp49gp_driver);
- usb_serial_deregister(&hp49gp_device);
-}
-
-module_init(hp49gp_init);
-module_exit(hp49gp_exit);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index cd769ef24f8..c0866971db2 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -32,7 +32,6 @@
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -51,18 +50,12 @@
#include "io_ionsp.h" /* info for the iosp messages */
#include "io_16654.h" /* 16654 UART defines */
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v2.7"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
#define DRIVER_DESC "Edgeport USB Serial Driver"
#define MAX_NAME_LEN 64
-#define CHASE_TIMEOUT (5*HZ) /* 5 seconds */
#define OPEN_TIMEOUT (5*HZ) /* 5 seconds */
-#define COMMAND_TIMEOUT (5*HZ) /* 5 seconds */
/* receive port state */
enum RXSTATE {
@@ -114,9 +107,7 @@ struct edgeport_port {
wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */
wait_queue_head_t wait_open; /* for handling sleeping while waiting for open to finish */
wait_queue_head_t wait_command; /* for handling sleeping while waiting for command to finish */
- wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */
- struct async_icount icount;
struct usb_serial_port *port; /* loop back to the owner of this object */
};
@@ -190,10 +181,8 @@ static const struct divisor_table_entry divisor_table[] = {
{ 230400, 1},
};
-/* local variables */
-static int debug;
-
-static atomic_t CmdUrbs; /* Number of outstanding Command Write Urbs */
+/* Number of outstanding Command Write Urbs */
+static atomic_t CmdUrbs = ATOMIC_INIT(0);
/* local function prototypes */
@@ -216,17 +205,17 @@ static void edge_unthrottle(struct tty_struct *tty);
static void edge_set_termios(struct tty_struct *tty,
struct usb_serial_port *port,
struct ktermios *old_termios);
-static int edge_ioctl(struct tty_struct *tty, struct file *file,
+static int edge_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
static void edge_break(struct tty_struct *tty, int break_state);
-static int edge_tiocmget(struct tty_struct *tty, struct file *file);
-static int edge_tiocmset(struct tty_struct *tty, struct file *file,
+static int edge_tiocmget(struct tty_struct *tty);
+static int edge_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
-static int edge_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount);
static int edge_startup(struct usb_serial *serial);
static void edge_disconnect(struct usb_serial *serial);
static void edge_release(struct usb_serial *serial);
+static int edge_port_probe(struct usb_serial_port *port);
+static int edge_port_remove(struct usb_serial_port *port);
#include "io_tables.h" /* all of the devices that this driver supports */
@@ -236,14 +225,14 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
unsigned char *buffer, __u16 bufferLength);
static void process_rcvd_status(struct edgeport_serial *edge_serial,
__u8 byte2, __u8 byte3);
-static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
- unsigned char *data, int length);
+static void edge_tty_recv(struct usb_serial_port *port, unsigned char *data,
+ int length);
static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr);
static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
__u8 lsr, __u8 data);
static int send_iosp_ext_cmd(struct edgeport_port *edge_port, __u8 command,
__u8 param);
-static int calc_baud_rate_divisor(int baud_rate, int *divisor);
+static int calc_baud_rate_divisor(struct device *dev, int baud_rate, int *divisor);
static int send_cmd_write_baud_rate(struct edgeport_port *edge_port,
int baudRate);
static void change_port_settings(struct tty_struct *tty,
@@ -285,6 +274,7 @@ static void unicode_to_ascii(char *string, int buflen,
************************************************************************/
static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial)
{
+ struct device *dev = &edge_serial->serial->dev->dev;
__u32 BootCurVer;
__u32 BootNewVer;
__u8 BootMajorVersion;
@@ -310,7 +300,7 @@ static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial)
response = request_ihex_firmware(&fw, fw_name,
&edge_serial->serial->dev->dev);
if (response) {
- printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+ dev_err(dev, "Failed to load image \"%s\" err %d\n",
fw_name, response);
return;
}
@@ -329,20 +319,20 @@ static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial)
(BootMinorVersion << 16) +
BootBuildNumber;
- dbg("Current Boot Image version %d.%d.%d",
+ dev_dbg(dev, "Current Boot Image version %d.%d.%d\n",
edge_serial->boot_descriptor.MajorVersion,
edge_serial->boot_descriptor.MinorVersion,
le16_to_cpu(edge_serial->boot_descriptor.BuildNumber));
if (BootNewVer > BootCurVer) {
- dbg("**Update Boot Image from %d.%d.%d to %d.%d.%d",
+ dev_dbg(dev, "**Update Boot Image from %d.%d.%d to %d.%d.%d\n",
edge_serial->boot_descriptor.MajorVersion,
edge_serial->boot_descriptor.MinorVersion,
le16_to_cpu(edge_serial->boot_descriptor.BuildNumber),
BootMajorVersion, BootMinorVersion, BootBuildNumber);
- dbg("Downloading new Boot Image");
+ dev_dbg(dev, "Downloading new Boot Image\n");
for (rec = ihex_next_binrec(rec); rec;
rec = ihex_next_binrec(rec)) {
@@ -361,7 +351,7 @@ static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial)
}
}
} else {
- dbg("Boot Image -- already up to date");
+ dev_dbg(dev, "Boot Image -- already up to date\n");
}
release_firmware(fw);
}
@@ -378,7 +368,7 @@ static int get_string_desc(struct usb_device *dev, int Id,
struct usb_string_descriptor StringDesc;
struct usb_string_descriptor *pStringDesc;
- dbg("%s - USB String ID = %d", __func__, Id);
+ dev_dbg(&dev->dev, "%s - USB String ID = %d\n", __func__, Id);
if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc,
sizeof(StringDesc)))
@@ -399,34 +389,39 @@ static int get_string_desc(struct usb_device *dev, int Id,
}
#endif
-static void dump_product_info(struct edgeport_product_info *product_info)
+static void dump_product_info(struct edgeport_serial *edge_serial,
+ struct edgeport_product_info *product_info)
{
+ struct device *dev = &edge_serial->serial->dev->dev;
+
/* Dump Product Info structure */
- dbg("**Product Information:");
- dbg(" ProductId %x", product_info->ProductId);
- dbg(" NumPorts %d", product_info->NumPorts);
- dbg(" ProdInfoVer %d", product_info->ProdInfoVer);
- dbg(" IsServer %d", product_info->IsServer);
- dbg(" IsRS232 %d", product_info->IsRS232);
- dbg(" IsRS422 %d", product_info->IsRS422);
- dbg(" IsRS485 %d", product_info->IsRS485);
- dbg(" RomSize %d", product_info->RomSize);
- dbg(" RamSize %d", product_info->RamSize);
- dbg(" CpuRev %x", product_info->CpuRev);
- dbg(" BoardRev %x", product_info->BoardRev);
- dbg(" BootMajorVersion %d.%d.%d", product_info->BootMajorVersion,
- product_info->BootMinorVersion,
- le16_to_cpu(product_info->BootBuildNumber));
- dbg(" FirmwareMajorVersion %d.%d.%d",
- product_info->FirmwareMajorVersion,
- product_info->FirmwareMinorVersion,
- le16_to_cpu(product_info->FirmwareBuildNumber));
- dbg(" ManufactureDescDate %d/%d/%d",
- product_info->ManufactureDescDate[0],
- product_info->ManufactureDescDate[1],
- product_info->ManufactureDescDate[2]+1900);
- dbg(" iDownloadFile 0x%x", product_info->iDownloadFile);
- dbg(" EpicVer %d", product_info->EpicVer);
+ dev_dbg(dev, "**Product Information:\n");
+ dev_dbg(dev, " ProductId %x\n", product_info->ProductId);
+ dev_dbg(dev, " NumPorts %d\n", product_info->NumPorts);
+ dev_dbg(dev, " ProdInfoVer %d\n", product_info->ProdInfoVer);
+ dev_dbg(dev, " IsServer %d\n", product_info->IsServer);
+ dev_dbg(dev, " IsRS232 %d\n", product_info->IsRS232);
+ dev_dbg(dev, " IsRS422 %d\n", product_info->IsRS422);
+ dev_dbg(dev, " IsRS485 %d\n", product_info->IsRS485);
+ dev_dbg(dev, " RomSize %d\n", product_info->RomSize);
+ dev_dbg(dev, " RamSize %d\n", product_info->RamSize);
+ dev_dbg(dev, " CpuRev %x\n", product_info->CpuRev);
+ dev_dbg(dev, " BoardRev %x\n", product_info->BoardRev);
+ dev_dbg(dev, " BootMajorVersion %d.%d.%d\n",
+ product_info->BootMajorVersion,
+ product_info->BootMinorVersion,
+ le16_to_cpu(product_info->BootBuildNumber));
+ dev_dbg(dev, " FirmwareMajorVersion %d.%d.%d\n",
+ product_info->FirmwareMajorVersion,
+ product_info->FirmwareMinorVersion,
+ le16_to_cpu(product_info->FirmwareBuildNumber));
+ dev_dbg(dev, " ManufactureDescDate %d/%d/%d\n",
+ product_info->ManufactureDescDate[0],
+ product_info->ManufactureDescDate[1],
+ product_info->ManufactureDescDate[2]+1900);
+ dev_dbg(dev, " iDownloadFile 0x%x\n",
+ product_info->iDownloadFile);
+ dev_dbg(dev, " EpicVer %d\n", product_info->EpicVer);
}
static void get_product_info(struct edgeport_serial *edge_serial)
@@ -461,7 +456,7 @@ static void get_product_info(struct edgeport_serial *edge_serial)
product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_80251;
else
product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_I930;
-
+
/* Determine Product type and set appropriate flags */
switch (DEVICE_ID_FROM_USB_PRODUCT_ID(product_info->ProductId)) {
case ION_DEVICE_ID_EDGEPORT_COMPATIBLE:
@@ -489,7 +484,7 @@ static void get_product_info(struct edgeport_serial *edge_serial)
break;
}
- dump_product_info(product_info);
+ dump_product_info(edge_serial, product_info);
}
static int get_epic_descriptor(struct edgeport_serial *ep)
@@ -499,6 +494,7 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
struct edgeport_product_info *product_info = &ep->product_info;
struct edge_compatibility_descriptor *epic = &ep->epic_descriptor;
struct edge_compatibility_bits *bits;
+ struct device *dev = &serial->dev->dev;
ep->is_epic = 0;
result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
@@ -508,8 +504,6 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
sizeof(struct edge_compatibility_descriptor),
300);
- dbg("%s result = %d", __func__, result);
-
if (result > 0) {
ep->is_epic = 1;
memset(product_info, 0, sizeof(struct edgeport_product_info));
@@ -523,23 +517,23 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
product_info->EpicVer = epic->EpicVer;
product_info->Epic = epic->Supports;
product_info->ProductId = ION_DEVICE_ID_EDGEPORT_COMPATIBLE;
- dump_product_info(product_info);
+ dump_product_info(ep, product_info);
bits = &ep->epic_descriptor.Supports;
- dbg("**EPIC descriptor:");
- dbg(" VendEnableSuspend: %s", bits->VendEnableSuspend ? "TRUE": "FALSE");
- dbg(" IOSPOpen : %s", bits->IOSPOpen ? "TRUE": "FALSE");
- dbg(" IOSPClose : %s", bits->IOSPClose ? "TRUE": "FALSE");
- dbg(" IOSPChase : %s", bits->IOSPChase ? "TRUE": "FALSE");
- dbg(" IOSPSetRxFlow : %s", bits->IOSPSetRxFlow ? "TRUE": "FALSE");
- dbg(" IOSPSetTxFlow : %s", bits->IOSPSetTxFlow ? "TRUE": "FALSE");
- dbg(" IOSPSetXChar : %s", bits->IOSPSetXChar ? "TRUE": "FALSE");
- dbg(" IOSPRxCheck : %s", bits->IOSPRxCheck ? "TRUE": "FALSE");
- dbg(" IOSPSetClrBreak : %s", bits->IOSPSetClrBreak ? "TRUE": "FALSE");
- dbg(" IOSPWriteMCR : %s", bits->IOSPWriteMCR ? "TRUE": "FALSE");
- dbg(" IOSPWriteLCR : %s", bits->IOSPWriteLCR ? "TRUE": "FALSE");
- dbg(" IOSPSetBaudRate : %s", bits->IOSPSetBaudRate ? "TRUE": "FALSE");
- dbg(" TrueEdgeport : %s", bits->TrueEdgeport ? "TRUE": "FALSE");
+ dev_dbg(dev, "**EPIC descriptor:\n");
+ dev_dbg(dev, " VendEnableSuspend: %s\n", bits->VendEnableSuspend ? "TRUE": "FALSE");
+ dev_dbg(dev, " IOSPOpen : %s\n", bits->IOSPOpen ? "TRUE": "FALSE");
+ dev_dbg(dev, " IOSPClose : %s\n", bits->IOSPClose ? "TRUE": "FALSE");
+ dev_dbg(dev, " IOSPChase : %s\n", bits->IOSPChase ? "TRUE": "FALSE");
+ dev_dbg(dev, " IOSPSetRxFlow : %s\n", bits->IOSPSetRxFlow ? "TRUE": "FALSE");
+ dev_dbg(dev, " IOSPSetTxFlow : %s\n", bits->IOSPSetTxFlow ? "TRUE": "FALSE");
+ dev_dbg(dev, " IOSPSetXChar : %s\n", bits->IOSPSetXChar ? "TRUE": "FALSE");
+ dev_dbg(dev, " IOSPRxCheck : %s\n", bits->IOSPRxCheck ? "TRUE": "FALSE");
+ dev_dbg(dev, " IOSPSetClrBreak : %s\n", bits->IOSPSetClrBreak ? "TRUE": "FALSE");
+ dev_dbg(dev, " IOSPWriteMCR : %s\n", bits->IOSPWriteMCR ? "TRUE": "FALSE");
+ dev_dbg(dev, " IOSPWriteLCR : %s\n", bits->IOSPWriteLCR ? "TRUE": "FALSE");
+ dev_dbg(dev, " IOSPSetBaudRate : %s\n", bits->IOSPSetBaudRate ? "TRUE": "FALSE");
+ dev_dbg(dev, " TrueEdgeport : %s\n", bits->TrueEdgeport ? "TRUE": "FALSE");
}
return result;
@@ -560,10 +554,10 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
*****************************************************************************/
static void edge_interrupt_callback(struct urb *urb)
{
- struct edgeport_serial *edge_serial = urb->context;
+ struct edgeport_serial *edge_serial = urb->context;
+ struct device *dev;
struct edgeport_port *edge_port;
struct usb_serial_port *port;
- struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int length = urb->actual_length;
int bytes_avail;
@@ -573,8 +567,6 @@ static void edge_interrupt_callback(struct urb *urb)
int result;
int status = urb->status;
- dbg("%s", __func__);
-
switch (status) {
case 0:
/* success */
@@ -583,37 +575,42 @@ static void edge_interrupt_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n", __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __func__, status);
+ dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __func__, status);
goto exit;
}
+ dev = &edge_serial->serial->dev->dev;
+
/* process this interrupt-read even if there are no ports open */
if (length) {
- usb_serial_debug_data(debug, &edge_serial->serial->dev->dev,
- __func__, length, data);
+ usb_serial_debug_data(dev, __func__, length, data);
if (length > 1) {
bytes_avail = data[0] | (data[1] << 8);
if (bytes_avail) {
spin_lock(&edge_serial->es_lock);
edge_serial->rxBytesAvail += bytes_avail;
- dbg("%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d", __func__, bytes_avail, edge_serial->rxBytesAvail, edge_serial->read_in_progress);
+ dev_dbg(dev,
+ "%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d\n",
+ __func__, bytes_avail,
+ edge_serial->rxBytesAvail,
+ edge_serial->read_in_progress);
if (edge_serial->rxBytesAvail > 0 &&
!edge_serial->read_in_progress) {
- dbg("%s - posting a read", __func__);
+ dev_dbg(dev, "%s - posting a read\n", __func__);
edge_serial->read_in_progress = true;
/* we have pending bytes on the
bulk in pipe, send a request */
- edge_serial->read_urb->dev = edge_serial->serial->dev;
result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
if (result) {
- dev_err(&edge_serial->serial->dev->dev, "%s - usb_submit_urb(read bulk) failed with result = %d\n", __func__, result);
+ dev_err(dev,
+ "%s - usb_submit_urb(read bulk) failed with result = %d\n",
+ __func__, result);
edge_serial->read_in_progress = false;
}
}
@@ -633,18 +630,13 @@ static void edge_interrupt_callback(struct urb *urb)
spin_lock(&edge_port->ep_lock);
edge_port->txCredits += txCredits;
spin_unlock(&edge_port->ep_lock);
- dbg("%s - txcredits for port%d = %d",
- __func__, portNumber,
- edge_port->txCredits);
+ dev_dbg(dev, "%s - txcredits for port%d = %d\n",
+ __func__, portNumber,
+ edge_port->txCredits);
/* tell the tty driver that something
has changed */
- tty = tty_port_tty_get(
- &edge_port->port->port);
- if (tty) {
- tty_wakeup(tty);
- tty_kref_put(tty);
- }
+ tty_port_tty_wakeup(&edge_port->port->port);
/* Since we have more credit, check
if more data can be sent */
send_more_port_data(edge_serial,
@@ -673,50 +665,48 @@ exit:
static void edge_bulk_in_callback(struct urb *urb)
{
struct edgeport_serial *edge_serial = urb->context;
+ struct device *dev;
unsigned char *data = urb->transfer_buffer;
int retval;
__u16 raw_data_length;
int status = urb->status;
- dbg("%s", __func__);
-
if (status) {
- dbg("%s - nonzero read bulk status received: %d",
- __func__, status);
+ dev_dbg(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n",
+ __func__, status);
edge_serial->read_in_progress = false;
return;
}
if (urb->actual_length == 0) {
- dbg("%s - read bulk callback with no data", __func__);
+ dev_dbg(&urb->dev->dev, "%s - read bulk callback with no data\n", __func__);
edge_serial->read_in_progress = false;
return;
}
+ dev = &edge_serial->serial->dev->dev;
raw_data_length = urb->actual_length;
- usb_serial_debug_data(debug, &edge_serial->serial->dev->dev,
- __func__, raw_data_length, data);
+ usb_serial_debug_data(dev, __func__, raw_data_length, data);
spin_lock(&edge_serial->es_lock);
/* decrement our rxBytes available by the number that we just got */
edge_serial->rxBytesAvail -= raw_data_length;
- dbg("%s - Received = %d, rxBytesAvail %d", __func__,
- raw_data_length, edge_serial->rxBytesAvail);
+ dev_dbg(dev, "%s - Received = %d, rxBytesAvail %d\n", __func__,
+ raw_data_length, edge_serial->rxBytesAvail);
process_rcvd_data(edge_serial, data, urb->actual_length);
/* check to see if there's any more data for us to read */
if (edge_serial->rxBytesAvail > 0) {
- dbg("%s - posting a read", __func__);
- edge_serial->read_urb->dev = edge_serial->serial->dev;
+ dev_dbg(dev, "%s - posting a read\n", __func__);
retval = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
if (retval) {
- dev_err(&urb->dev->dev,
- "%s - usb_submit_urb(read bulk) failed, "
- "retval = %d\n", __func__, retval);
+ dev_err(dev,
+ "%s - usb_submit_urb(read bulk) failed, retval = %d\n",
+ __func__, retval);
edge_serial->read_in_progress = false;
}
} else {
@@ -735,24 +725,16 @@ static void edge_bulk_in_callback(struct urb *urb)
static void edge_bulk_out_data_callback(struct urb *urb)
{
struct edgeport_port *edge_port = urb->context;
- struct tty_struct *tty;
int status = urb->status;
- dbg("%s", __func__);
-
if (status) {
- dbg("%s - nonzero write bulk status received: %d",
- __func__, status);
+ dev_dbg(&urb->dev->dev,
+ "%s - nonzero write bulk status received: %d\n",
+ __func__, status);
}
- tty = tty_port_tty_get(&edge_port->port->port);
-
- if (tty && edge_port->open) {
- /* let the tty driver wakeup if it has a special
- write_wakeup function */
- tty_wakeup(tty);
- }
- tty_kref_put(tty);
+ if (edge_port->open)
+ tty_port_tty_wakeup(&edge_port->port->port);
/* Release the Write URB */
edge_port->write_in_progress = false;
@@ -771,14 +753,11 @@ static void edge_bulk_out_data_callback(struct urb *urb)
static void edge_bulk_out_cmd_callback(struct urb *urb)
{
struct edgeport_port *edge_port = urb->context;
- struct tty_struct *tty;
int status = urb->status;
- dbg("%s", __func__);
-
atomic_dec(&CmdUrbs);
- dbg("%s - FREE URB %p (outstanding %d)", __func__,
- urb, atomic_read(&CmdUrbs));
+ dev_dbg(&urb->dev->dev, "%s - FREE URB %p (outstanding %d)\n",
+ __func__, urb, atomic_read(&CmdUrbs));
/* clean up the transfer buffer */
@@ -788,18 +767,15 @@ static void edge_bulk_out_cmd_callback(struct urb *urb)
usb_free_urb(urb);
if (status) {
- dbg("%s - nonzero write bulk status received: %d",
- __func__, status);
+ dev_dbg(&urb->dev->dev,
+ "%s - nonzero write bulk status received: %d\n",
+ __func__, status);
return;
}
- /* Get pointer to tty */
- tty = tty_port_tty_get(&edge_port->port->port);
-
/* tell the tty driver that something has changed */
- if (tty && edge_port->open)
- tty_wakeup(tty);
- tty_kref_put(tty);
+ if (edge_port->open)
+ tty_port_tty_wakeup(&edge_port->port->port);
/* we have completed the command */
edge_port->commandPending = false;
@@ -820,12 +796,11 @@ static void edge_bulk_out_cmd_callback(struct urb *urb)
static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ struct device *dev = &port->dev;
struct usb_serial *serial;
struct edgeport_serial *edge_serial;
int response;
- dbg("%s - port %d", __func__, port->number);
-
if (edge_port == NULL)
return -ENODEV;
@@ -876,21 +851,16 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
response = usb_submit_urb(edge_serial->interrupt_read_urb,
GFP_KERNEL);
if (response) {
- dev_err(&port->dev,
- "%s - Error %d submitting control urb\n",
- __func__, response);
+ dev_err(dev, "%s - Error %d submitting control urb\n",
+ __func__, response);
}
}
/* initialize our wait queues */
init_waitqueue_head(&edge_port->wait_open);
init_waitqueue_head(&edge_port->wait_chase);
- init_waitqueue_head(&edge_port->delta_msr_wait);
init_waitqueue_head(&edge_port->wait_command);
- /* initialize our icount structure */
- memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
-
/* initialize our port settings */
edge_port->txCredits = 0; /* Can't send any data yet */
/* Must always set this bit to enable ints! */
@@ -903,8 +873,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
response = send_iosp_ext_cmd(edge_port, IOSP_CMD_OPEN_PORT, 0);
if (response < 0) {
- dev_err(&port->dev, "%s - error sending open port command\n",
- __func__);
+ dev_err(dev, "%s - error sending open port command\n", __func__);
edge_port->openPending = false;
return -ENODEV;
}
@@ -915,7 +884,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
if (!edge_port->open) {
/* open timed out */
- dbg("%s - open timedout", __func__);
+ dev_dbg(dev, "%s - open timedout\n", __func__);
edge_port->openPending = false;
return -ENODEV;
}
@@ -928,7 +897,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
edge_port->txfifo.fifo = kmalloc(edge_port->maxTxCredits, GFP_KERNEL);
if (!edge_port->txfifo.fifo) {
- dbg("%s - no memory", __func__);
edge_close(port);
return -ENOMEM;
}
@@ -938,15 +906,12 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
edge_port->write_in_progress = false;
if (!edge_port->write_urb) {
- dbg("%s - no memory", __func__);
edge_close(port);
return -ENOMEM;
}
- dbg("%s(%d) - Initialize TX fifo to %d bytes",
- __func__, port->number, edge_port->maxTxCredits);
-
- dbg("%s exited", __func__);
+ dev_dbg(dev, "%s - Initialize TX fifo to %d bytes\n",
+ __func__, edge_port->maxTxCredits);
return 0;
}
@@ -964,6 +929,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
************************************************************************/
static void block_until_chase_response(struct edgeport_port *edge_port)
{
+ struct device *dev = &edge_port->port->dev;
DEFINE_WAIT(wait);
__u16 lastCredits;
int timeout = 1*HZ;
@@ -975,11 +941,11 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
/* Did we get our Chase response */
if (!edge_port->chaseResponsePending) {
- dbg("%s - Got Chase Response", __func__);
+ dev_dbg(dev, "%s - Got Chase Response\n", __func__);
/* did we get all of our credit back? */
if (edge_port->txCredits == edge_port->maxTxCredits) {
- dbg("%s - Got all credits", __func__);
+ dev_dbg(dev, "%s - Got all credits\n", __func__);
return;
}
}
@@ -995,12 +961,12 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
loop--;
if (loop == 0) {
edge_port->chaseResponsePending = false;
- dbg("%s - Chase TIMEOUT", __func__);
+ dev_dbg(dev, "%s - Chase TIMEOUT\n", __func__);
return;
}
} else {
/* Reset timeout value back to 10 seconds */
- dbg("%s - Last %d, Current %d", __func__,
+ dev_dbg(dev, "%s - Last %d, Current %d\n", __func__,
lastCredits, edge_port->txCredits);
loop = 10;
}
@@ -1020,6 +986,7 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
************************************************************************/
static void block_until_tx_empty(struct edgeport_port *edge_port)
{
+ struct device *dev = &edge_port->port->dev;
DEFINE_WAIT(wait);
struct TxFifo *fifo = &edge_port->txfifo;
__u32 lastCount;
@@ -1032,7 +999,7 @@ static void block_until_tx_empty(struct edgeport_port *edge_port)
/* Is the Edgeport Buffer empty? */
if (lastCount == 0) {
- dbg("%s - TX Buffer Empty", __func__);
+ dev_dbg(dev, "%s - TX Buffer Empty\n", __func__);
return;
}
@@ -1042,13 +1009,13 @@ static void block_until_tx_empty(struct edgeport_port *edge_port)
schedule_timeout(timeout);
finish_wait(&edge_port->wait_chase, &wait);
- dbg("%s wait", __func__);
+ dev_dbg(dev, "%s wait\n", __func__);
if (lastCount == fifo->count) {
/* No activity.. count down. */
loop--;
if (loop == 0) {
- dbg("%s - TIMEOUT", __func__);
+ dev_dbg(dev, "%s - TIMEOUT\n", __func__);
return;
}
} else {
@@ -1069,8 +1036,6 @@ static void edge_close(struct usb_serial_port *port)
struct edgeport_port *edge_port;
int status;
- dbg("%s - port %d", __func__, port->number);
-
edge_serial = usb_get_serial_data(port->serial);
edge_port = usb_get_serial_port_data(port);
if (edge_serial == NULL || edge_port == NULL)
@@ -1087,7 +1052,7 @@ static void edge_close(struct usb_serial_port *port)
/* flush and chase */
edge_port->chaseResponsePending = true;
- dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__);
+ dev_dbg(&port->dev, "%s - Sending IOSP_CMD_CHASE_PORT\n", __func__);
status = send_iosp_ext_cmd(edge_port, IOSP_CMD_CHASE_PORT, 0);
if (status == 0)
/* block until chase finished */
@@ -1100,7 +1065,7 @@ static void edge_close(struct usb_serial_port *port)
((edge_serial->is_epic) &&
(edge_serial->epic_descriptor.Supports.IOSPClose))) {
/* close the port */
- dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __func__);
+ dev_dbg(&port->dev, "%s - Sending IOSP_CMD_CLOSE_PORT\n", __func__);
send_iosp_ext_cmd(edge_port, IOSP_CMD_CLOSE_PORT, 0);
}
@@ -1120,8 +1085,6 @@ static void edge_close(struct usb_serial_port *port)
}
kfree(edge_port->txfifo.fifo);
edge_port->txfifo.fifo = NULL;
-
- dbg("%s exited", __func__);
}
/*****************************************************************************
@@ -1142,8 +1105,6 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
int secondhalf;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
if (edge_port == NULL)
return -ENODEV;
@@ -1156,14 +1117,13 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
copySize = min((unsigned int)count,
(edge_port->txCredits - fifo->count));
- dbg("%s(%d) of %d byte(s) Fifo room %d -- will copy %d bytes",
- __func__, port->number, count,
- edge_port->txCredits - fifo->count, copySize);
+ dev_dbg(&port->dev, "%s of %d byte(s) Fifo room %d -- will copy %d bytes\n",
+ __func__, count, edge_port->txCredits - fifo->count, copySize);
/* catch writes of 0 bytes which the tty driver likes to give us,
and when txCredits is empty */
if (copySize == 0) {
- dbg("%s - copySize = Zero", __func__);
+ dev_dbg(&port->dev, "%s - copySize = Zero\n", __func__);
goto finish_write;
}
@@ -1176,13 +1136,12 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
*/
bytesleft = fifo->size - fifo->head;
firsthalf = min(bytesleft, copySize);
- dbg("%s - copy %d bytes of %d into fifo ", __func__,
- firsthalf, bytesleft);
+ dev_dbg(&port->dev, "%s - copy %d bytes of %d into fifo \n", __func__,
+ firsthalf, bytesleft);
/* now copy our data */
memcpy(&fifo->fifo[fifo->head], data, firsthalf);
- usb_serial_debug_data(debug, &port->dev, __func__,
- firsthalf, &fifo->fifo[fifo->head]);
+ usb_serial_debug_data(&port->dev, __func__, firsthalf, &fifo->fifo[fifo->head]);
/* update the index and size */
fifo->head += firsthalf;
@@ -1195,10 +1154,9 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
secondhalf = copySize-firsthalf;
if (secondhalf) {
- dbg("%s - copy rest of data %d", __func__, secondhalf);
+ dev_dbg(&port->dev, "%s - copy rest of data %d\n", __func__, secondhalf);
memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf);
- usb_serial_debug_data(debug, &port->dev, __func__,
- secondhalf, &fifo->fifo[fifo->head]);
+ usb_serial_debug_data(&port->dev, __func__, secondhalf, &fifo->fifo[fifo->head]);
/* update the index and size */
fifo->count += secondhalf;
fifo->head += secondhalf;
@@ -1213,8 +1171,8 @@ finish_write:
send_more_port_data((struct edgeport_serial *)
usb_get_serial_data(port->serial), edge_port);
- dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __func__,
- copySize, edge_port->txCredits, fifo->count);
+ dev_dbg(&port->dev, "%s wrote %d byte(s) TxCredits %d, Fifo %d\n",
+ __func__, copySize, edge_port->txCredits, fifo->count);
return copySize;
}
@@ -1237,6 +1195,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
struct edgeport_port *edge_port)
{
struct TxFifo *fifo = &edge_port->txfifo;
+ struct device *dev = &edge_port->port->dev;
struct urb *urb;
unsigned char *buffer;
int status;
@@ -1246,16 +1205,13 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
int secondhalf;
unsigned long flags;
- dbg("%s(%d)", __func__, edge_port->port->number);
-
spin_lock_irqsave(&edge_port->ep_lock, flags);
if (edge_port->write_in_progress ||
!edge_port->open ||
(fifo->count == 0)) {
- dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d",
- __func__, edge_port->port->number,
- fifo->count, edge_port->write_in_progress);
+ dev_dbg(dev, "%s EXIT - fifo %d, PendingWrite = %d\n",
+ __func__, fifo->count, edge_port->write_in_progress);
goto exit_send;
}
@@ -1267,9 +1223,8 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
* it's better to wait for more credits so we can do a larger write.
*/
if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits, EDGE_FW_BULK_MAX_PACKET_SIZE)) {
- dbg("%s(%d) Not enough credit - fifo %d TxCredit %d",
- __func__, edge_port->port->number, fifo->count,
- edge_port->txCredits);
+ dev_dbg(dev, "%s Not enough credit - fifo %d TxCredit %d\n",
+ __func__, fifo->count, edge_port->txCredits);
goto exit_send;
}
@@ -1287,16 +1242,12 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
to send out */
count = fifo->count;
buffer = kmalloc(count+2, GFP_ATOMIC);
- if (buffer == NULL) {
- dev_err(&edge_port->port->dev,
- "%s - no more kernel memory...\n", __func__);
+ if (!buffer) {
edge_port->write_in_progress = false;
goto exit_send;
}
- buffer[0] = IOSP_BUILD_DATA_HDR1(edge_port->port->number
- - edge_port->port->serial->minor, count);
- buffer[1] = IOSP_BUILD_DATA_HDR2(edge_port->port->number
- - edge_port->port->serial->minor, count);
+ buffer[0] = IOSP_BUILD_DATA_HDR1(edge_port->port->port_number, count);
+ buffer[1] = IOSP_BUILD_DATA_HDR2(edge_port->port->port_number, count);
/* now copy our data */
bytesleft = fifo->size - fifo->tail;
@@ -1316,8 +1267,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
}
if (count)
- usb_serial_debug_data(debug, &edge_port->port->dev,
- __func__, count, &buffer[2]);
+ usb_serial_debug_data(&edge_port->port->dev, __func__, count, &buffer[2]);
/* fill up the urb with all of our data and submit it */
usb_fill_bulk_urb(urb, edge_serial->serial->dev,
@@ -1328,23 +1278,22 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
/* decrement the number of credits we have by the number we just sent */
edge_port->txCredits -= count;
- edge_port->icount.tx += count;
+ edge_port->port->icount.tx += count;
- urb->dev = edge_serial->serial->dev;
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
/* something went wrong */
- dev_err(&edge_port->port->dev,
+ dev_err_console(edge_port->port,
"%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n",
__func__, status);
edge_port->write_in_progress = false;
/* revert the credits as something bad happened. */
edge_port->txCredits += count;
- edge_port->icount.tx -= count;
+ edge_port->port->icount.tx -= count;
}
- dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d",
- __func__, count, edge_port->txCredits, fifo->count);
+ dev_dbg(dev, "%s wrote %d byte(s) TxCredit %d, Fifo %d\n",
+ __func__, count, edge_port->txCredits, fifo->count);
exit_send:
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
@@ -1365,17 +1314,13 @@ static int edge_write_room(struct tty_struct *tty)
int room;
unsigned long flags;
- dbg("%s", __func__);
-
if (edge_port == NULL)
return 0;
if (edge_port->closePending)
return 0;
- dbg("%s - port %d", __func__, port->number);
-
if (!edge_port->open) {
- dbg("%s - port not opened", __func__);
+ dev_dbg(&port->dev, "%s - port not opened\n", __func__);
return 0;
}
@@ -1384,7 +1329,7 @@ static int edge_write_room(struct tty_struct *tty)
room = edge_port->txCredits - edge_port->txfifo.count;
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
- dbg("%s - returns %d", __func__, room);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, room);
return room;
}
@@ -1405,15 +1350,13 @@ static int edge_chars_in_buffer(struct tty_struct *tty)
int num_chars;
unsigned long flags;
- dbg("%s", __func__);
-
if (edge_port == NULL)
return 0;
if (edge_port->closePending)
return 0;
if (!edge_port->open) {
- dbg("%s - port not opened", __func__);
+ dev_dbg(&port->dev, "%s - port not opened\n", __func__);
return 0;
}
@@ -1422,8 +1365,7 @@ static int edge_chars_in_buffer(struct tty_struct *tty)
edge_port->txfifo.count;
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
if (num_chars) {
- dbg("%s(port %d) - returns %d", __func__,
- port->number, num_chars);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, num_chars);
}
return num_chars;
@@ -1441,13 +1383,11 @@ static void edge_throttle(struct tty_struct *tty)
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int status;
- dbg("%s - port %d", __func__, port->number);
-
if (edge_port == NULL)
return;
if (!edge_port->open) {
- dbg("%s - port not opened", __func__);
+ dev_dbg(&port->dev, "%s - port not opened\n", __func__);
return;
}
@@ -1460,7 +1400,7 @@ static void edge_throttle(struct tty_struct *tty)
}
/* if we are implementing RTS/CTS, toggle that line */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
edge_port->shadowMCR &= ~MCR_RTS;
status = send_cmd_write_uart_register(edge_port, MCR,
edge_port->shadowMCR);
@@ -1481,13 +1421,11 @@ static void edge_unthrottle(struct tty_struct *tty)
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int status;
- dbg("%s - port %d", __func__, port->number);
-
if (edge_port == NULL)
return;
if (!edge_port->open) {
- dbg("%s - port not opened", __func__);
+ dev_dbg(&port->dev, "%s - port not opened\n", __func__);
return;
}
@@ -1499,7 +1437,7 @@ static void edge_unthrottle(struct tty_struct *tty)
return;
}
/* if we are implementing RTS/CTS, toggle that line */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
edge_port->shadowMCR |= MCR_RTS;
send_cmd_write_uart_register(edge_port, MCR,
edge_port->shadowMCR);
@@ -1518,19 +1456,15 @@ static void edge_set_termios(struct tty_struct *tty,
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int cflag;
- cflag = tty->termios->c_cflag;
- dbg("%s - clfag %08x iflag %08x", __func__,
- tty->termios->c_cflag, tty->termios->c_iflag);
- dbg("%s - old clfag %08x old iflag %08x", __func__,
- old_termios->c_cflag, old_termios->c_iflag);
-
- dbg("%s - port %d", __func__, port->number);
+ cflag = tty->termios.c_cflag;
+ dev_dbg(&port->dev, "%s - clfag %08x iflag %08x\n", __func__, tty->termios.c_cflag, tty->termios.c_iflag);
+ dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__, old_termios->c_cflag, old_termios->c_iflag);
if (edge_port == NULL)
return;
if (!edge_port->open) {
- dbg("%s - port not opened", __func__);
+ dev_dbg(&port->dev, "%s - port not opened\n", __func__);
return;
}
@@ -1558,7 +1492,7 @@ static int get_lsr_info(struct edgeport_port *edge_port,
spin_lock_irqsave(&edge_port->ep_lock, flags);
if (edge_port->maxTxCredits == edge_port->txCredits &&
edge_port->txfifo.count == 0) {
- dbg("%s -- Empty", __func__);
+ dev_dbg(&edge_port->port->dev, "%s -- Empty\n", __func__);
result = TIOCSER_TEMT;
}
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
@@ -1568,15 +1502,13 @@ static int get_lsr_info(struct edgeport_port *edge_port,
return 0;
}
-static int edge_tiocmset(struct tty_struct *tty, struct file *file,
+static int edge_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int mcr;
- dbg("%s - port %d", __func__, port->number);
-
mcr = edge_port->shadowMCR;
if (set & TIOCM_RTS)
mcr |= MCR_RTS;
@@ -1599,7 +1531,7 @@ static int edge_tiocmset(struct tty_struct *tty, struct file *file,
return 0;
}
-static int edge_tiocmget(struct tty_struct *tty, struct file *file)
+static int edge_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
@@ -1607,8 +1539,6 @@ static int edge_tiocmget(struct tty_struct *tty, struct file *file)
unsigned int msr;
unsigned int mcr;
- dbg("%s - port %d", __func__, port->number);
-
msr = edge_port->shadowMSR;
mcr = edge_port->shadowMCR;
result = ((mcr & MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */
@@ -1618,37 +1548,9 @@ static int edge_tiocmget(struct tty_struct *tty, struct file *file)
| ((msr & EDGEPORT_MSR_RI) ? TIOCM_RI: 0) /* 0x080 */
| ((msr & EDGEPORT_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */
-
- dbg("%s -- %x", __func__, result);
-
return result;
}
-static int edge_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct async_icount cnow;
- cnow = edge_port->icount;
-
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
-
- dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d",
- __func__, port->number, icount->rx, icount->tx);
- return 0;
-}
-
static int get_serial_info(struct edgeport_port *edge_port,
struct serial_struct __user *retinfo)
{
@@ -1660,8 +1562,8 @@ static int get_serial_info(struct edgeport_port *edge_port,
memset(&tmp, 0, sizeof(tmp));
tmp.type = PORT_16550A;
- tmp.line = edge_port->port->serial->minor;
- tmp.port = edge_port->port->number;
+ tmp.line = edge_port->port->minor;
+ tmp.port = edge_port->port->port_number;
tmp.irq = 0;
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
tmp.xmit_fifo_size = edge_port->maxTxCredits;
@@ -1679,52 +1581,21 @@ static int get_serial_info(struct edgeport_port *edge_port,
* SerialIoctl
* this function handles any ioctl calls to the driver
*****************************************************************************/
-static int edge_ioctl(struct tty_struct *tty, struct file *file,
+static int edge_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
DEFINE_WAIT(wait);
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct async_icount cnow;
- struct async_icount cprev;
-
- dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
switch (cmd) {
case TIOCSERGETLSR:
- dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
+ dev_dbg(&port->dev, "%s TIOCSERGETLSR\n", __func__);
return get_lsr_info(edge_port, (unsigned int __user *) arg);
case TIOCGSERIAL:
- dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
+ dev_dbg(&port->dev, "%s TIOCGSERIAL\n", __func__);
return get_serial_info(edge_port, (struct serial_struct __user *) arg);
-
- case TIOCMIWAIT:
- dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
- cprev = edge_port->icount;
- while (1) {
- prepare_to_wait(&edge_port->delta_msr_wait,
- &wait, TASK_INTERRUPTIBLE);
- schedule();
- finish_wait(&edge_port->delta_msr_wait, &wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = edge_port->icount;
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
- return 0;
- }
- cprev = cnow;
- }
- /* NOTREACHED */
- break;
-
}
return -ENOIOCTLCMD;
}
@@ -1747,7 +1618,7 @@ static void edge_break(struct tty_struct *tty, int break_state)
/* flush and chase */
edge_port->chaseResponsePending = true;
- dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__);
+ dev_dbg(&port->dev, "%s - Sending IOSP_CMD_CHASE_PORT\n", __func__);
status = send_iosp_ext_cmd(edge_port, IOSP_CMD_CHASE_PORT, 0);
if (status == 0) {
/* block until chase finished */
@@ -1761,16 +1632,16 @@ static void edge_break(struct tty_struct *tty, int break_state)
((edge_serial->is_epic) &&
(edge_serial->epic_descriptor.Supports.IOSPSetClrBreak))) {
if (break_state == -1) {
- dbg("%s - Sending IOSP_CMD_SET_BREAK", __func__);
+ dev_dbg(&port->dev, "%s - Sending IOSP_CMD_SET_BREAK\n", __func__);
status = send_iosp_ext_cmd(edge_port,
IOSP_CMD_SET_BREAK, 0);
} else {
- dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __func__);
+ dev_dbg(&port->dev, "%s - Sending IOSP_CMD_CLEAR_BREAK\n", __func__);
status = send_iosp_ext_cmd(edge_port,
IOSP_CMD_CLEAR_BREAK, 0);
}
if (status)
- dbg("%s - error sending break set/clear command.",
+ dev_dbg(&port->dev, "%s - error sending break set/clear command.\n",
__func__);
}
}
@@ -1783,20 +1654,18 @@ static void edge_break(struct tty_struct *tty, int break_state)
static void process_rcvd_data(struct edgeport_serial *edge_serial,
unsigned char *buffer, __u16 bufferLength)
{
+ struct device *dev = &edge_serial->serial->dev->dev;
struct usb_serial_port *port;
struct edgeport_port *edge_port;
- struct tty_struct *tty;
__u16 lastBufferLength;
__u16 rxLen;
- dbg("%s", __func__);
-
lastBufferLength = bufferLength + 1;
while (bufferLength > 0) {
/* failsafe incase we get a message that we don't understand */
if (lastBufferLength == bufferLength) {
- dbg("%s - stuck in loop, exiting it.", __func__);
+ dev_dbg(dev, "%s - stuck in loop, exiting it.\n", __func__);
break;
}
lastBufferLength = bufferLength;
@@ -1817,8 +1686,8 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
++buffer;
--bufferLength;
- dbg("%s - Hdr1=%02X Hdr2=%02X", __func__,
- edge_serial->rxHeader1, edge_serial->rxHeader2);
+ dev_dbg(dev, "%s - Hdr1=%02X Hdr2=%02X\n", __func__,
+ edge_serial->rxHeader1, edge_serial->rxHeader2);
/* Process depending on whether this header is
* data or status */
@@ -1857,10 +1726,10 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
IOSP_GET_HDR_DATA_LEN(
edge_serial->rxHeader1,
edge_serial->rxHeader2);
- dbg("%s - Data for Port %u Len %u",
- __func__,
- edge_serial->rxPort,
- edge_serial->rxBytesRemaining);
+ dev_dbg(dev, "%s - Data for Port %u Len %u\n",
+ __func__,
+ edge_serial->rxPort,
+ edge_serial->rxBytesRemaining);
/* ASSERT(DevExt->RxPort < DevExt->NumPorts);
* ASSERT(DevExt->RxBytesRemaining <
@@ -1895,15 +1764,12 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
edge_serial->rxPort];
edge_port = usb_get_serial_port_data(port);
if (edge_port->open) {
- tty = tty_port_tty_get(
- &edge_port->port->port);
- if (tty) {
- dbg("%s - Sending %d bytes to TTY for port %d",
- __func__, rxLen, edge_serial->rxPort);
- edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen);
- tty_kref_put(tty);
- }
- edge_port->icount.rx += rxLen;
+ dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n",
+ __func__, rxLen,
+ edge_serial->rxPort);
+ edge_tty_recv(edge_port->port, buffer,
+ rxLen);
+ edge_port->port->icount.rx += rxLen;
}
buffer += rxLen;
}
@@ -1937,6 +1803,7 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
struct usb_serial_port *port;
struct edgeport_port *edge_port;
struct tty_struct *tty;
+ struct device *dev;
__u8 code = edge_serial->rxStatusCode;
/* switch the port pointer to the one being currently talked about */
@@ -1948,16 +1815,15 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
__func__, edge_serial->rxPort);
return;
}
-
- dbg("%s - port %d", __func__, edge_serial->rxPort);
+ dev = &port->dev;
if (code == IOSP_EXT_STATUS) {
switch (byte2) {
case IOSP_EXT_STATUS_CHASE_RSP:
/* we want to do EXT status regardless of port
* open/closed */
- dbg("%s - Port %u EXT CHASE_RSP Data = %02x",
- __func__, edge_serial->rxPort, byte3);
+ dev_dbg(dev, "%s - Port %u EXT CHASE_RSP Data = %02x\n",
+ __func__, edge_serial->rxPort, byte3);
/* Currently, the only EXT_STATUS is Chase, so process
* here instead of one more call to one more subroutine
* If/when more EXT_STATUS, there'll be more work to do
@@ -1972,7 +1838,8 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
return;
case IOSP_EXT_STATUS_RX_CHECK_RSP:
- dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============", __func__, edge_serial->rxPort, byte3);
+ dev_dbg(dev, "%s ========== Port %u CHECK_RSP Sequence = %02x =============\n",
+ __func__, edge_serial->rxPort, byte3);
/* Port->RxCheckRsp = true; */
return;
}
@@ -1981,7 +1848,8 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
if (code == IOSP_STATUS_OPEN_RSP) {
edge_port->txCredits = GET_TX_BUFFER_SIZE(byte3);
edge_port->maxTxCredits = edge_port->txCredits;
- dbg("%s - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", __func__, edge_serial->rxPort, byte2, edge_port->txCredits);
+ dev_dbg(dev, "%s - Port %u Open Response Initial MSR = %02x TxBufferSize = %d\n",
+ __func__, edge_serial->rxPort, byte2, edge_port->txCredits);
handle_new_msr(edge_port, byte2);
/* send the current line settings to the port so we are
@@ -1989,7 +1857,7 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
tty = tty_port_tty_get(&edge_port->port->port);
if (tty) {
change_port_settings(tty,
- edge_port, tty->termios);
+ edge_port, &tty->termios);
tty_kref_put(tty);
}
@@ -2010,27 +1878,27 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
switch (code) {
/* Not currently sent by Edgeport */
case IOSP_STATUS_LSR:
- dbg("%s - Port %u LSR Status = %02x",
- __func__, edge_serial->rxPort, byte2);
+ dev_dbg(dev, "%s - Port %u LSR Status = %02x\n",
+ __func__, edge_serial->rxPort, byte2);
handle_new_lsr(edge_port, false, byte2, 0);
break;
case IOSP_STATUS_LSR_DATA:
- dbg("%s - Port %u LSR Status = %02x, Data = %02x",
- __func__, edge_serial->rxPort, byte2, byte3);
+ dev_dbg(dev, "%s - Port %u LSR Status = %02x, Data = %02x\n",
+ __func__, edge_serial->rxPort, byte2, byte3);
/* byte2 is LSR Register */
/* byte3 is broken data byte */
handle_new_lsr(edge_port, true, byte2, byte3);
break;
/*
* case IOSP_EXT_4_STATUS:
- * dbg("%s - Port %u LSR Status = %02x Data = %02x",
+ * dev_dbg(dev, "%s - Port %u LSR Status = %02x Data = %02x\n",
* __func__, edge_serial->rxPort, byte2, byte3);
* break;
*/
case IOSP_STATUS_MSR:
- dbg("%s - Port %u MSR Status = %02x",
- __func__, edge_serial->rxPort, byte2);
+ dev_dbg(dev, "%s - Port %u MSR Status = %02x\n",
+ __func__, edge_serial->rxPort, byte2);
/*
* Process this new modem status and generate appropriate
* events, etc, based on the new status. This routine
@@ -2040,7 +1908,7 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
break;
default:
- dbg("%s - Unrecognized IOSP status code %u", __func__, code);
+ dev_dbg(dev, "%s - Unrecognized IOSP status code %u\n", __func__, code);
break;
}
}
@@ -2050,20 +1918,20 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
* edge_tty_recv
* this function passes data on to the tty flip buffer
*****************************************************************************/
-static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
- unsigned char *data, int length)
+static void edge_tty_recv(struct usb_serial_port *port, unsigned char *data,
+ int length)
{
int cnt;
- cnt = tty_insert_flip_string(tty, data, length);
+ cnt = tty_insert_flip_string(&port->port, data, length);
if (cnt < length) {
- dev_err(dev, "%s - dropping data, %d bytes lost\n",
+ dev_err(&port->dev, "%s - dropping data, %d bytes lost\n",
__func__, length - cnt);
}
data += cnt;
length -= cnt;
- tty_flip_buffer_push(tty);
+ tty_flip_buffer_push(&port->port);
}
@@ -2075,11 +1943,9 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
{
struct async_icount *icount;
- dbg("%s %02x", __func__, newMsr);
-
if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |
EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
- icount = &edge_port->icount;
+ icount = &edge_port->port->icount;
/* update input line counters */
if (newMsr & EDGEPORT_MSR_DELTA_CTS)
@@ -2090,7 +1956,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
icount->dcd++;
if (newMsr & EDGEPORT_MSR_DELTA_RI)
icount->rng++;
- wake_up_interruptible(&edge_port->delta_msr_wait);
+ wake_up_interruptible(&edge_port->port->port.delta_msr_wait);
}
/* Save the new modem status */
@@ -2109,8 +1975,6 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
struct async_icount *icount;
- dbg("%s - %02x", __func__, newLsr);
-
edge_port->shadowLSR = lsr;
if (newLsr & LSR_BREAK) {
@@ -2123,16 +1987,11 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
}
/* Place LSR data byte into Rx buffer */
- if (lsrData) {
- struct tty_struct *tty =
- tty_port_tty_get(&edge_port->port->port);
- if (tty) {
- edge_tty_recv(&edge_port->port->dev, tty, &data, 1);
- tty_kref_put(tty);
- }
- }
+ if (lsrData)
+ edge_tty_recv(edge_port->port, &data, 1);
+
/* update input line counters */
- icount = &edge_port->icount;
+ icount = &edge_port->port->icount;
if (newLsr & LSR_BREAK)
icount->brk++;
if (newLsr & LSR_OVER_ERR)
@@ -2158,14 +2017,11 @@ static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
__u16 current_length;
unsigned char *transfer_buffer;
- dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
+ dev_dbg(&serial->dev->dev, "%s - %x, %x, %d\n", __func__, extAddr, addr, length);
transfer_buffer = kmalloc(64, GFP_KERNEL);
- if (!transfer_buffer) {
- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n",
- __func__, 64);
+ if (!transfer_buffer)
return -ENOMEM;
- }
/* need to split these writes up into 64 byte chunks */
result = 0;
@@ -2175,8 +2031,7 @@ static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
else
current_length = length;
-/* dbg("%s - writing %x, %x, %d", __func__,
- extAddr, addr, current_length); */
+/* dev_dbg(&serial->dev->dev, "%s - writing %x, %x, %d\n", __func__, extAddr, addr, current_length); */
memcpy(transfer_buffer, data, current_length);
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
@@ -2209,14 +2064,9 @@ static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
__u16 current_length;
unsigned char *transfer_buffer;
-/* dbg("%s - %x, %x, %d", __func__, extAddr, addr, length); */
-
transfer_buffer = kmalloc(64, GFP_KERNEL);
- if (!transfer_buffer) {
- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n",
- __func__, 64);
+ if (!transfer_buffer)
return -ENOMEM;
- }
/* need to split these writes up into 64 byte chunks */
result = 0;
@@ -2225,8 +2075,6 @@ static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
current_length = 64;
else
current_length = length;
-/* dbg("%s - writing %x, %x, %d", __func__,
- extAddr, addr, current_length); */
memcpy(transfer_buffer, data, current_length);
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
@@ -2259,14 +2107,9 @@ static int rom_read(struct usb_serial *serial, __u16 extAddr,
__u16 current_length;
unsigned char *transfer_buffer;
- dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
-
transfer_buffer = kmalloc(64, GFP_KERNEL);
- if (!transfer_buffer) {
- dev_err(&serial->dev->dev,
- "%s - kmalloc(%d) failed.\n", __func__, 64);
+ if (!transfer_buffer)
return -ENOMEM;
- }
/* need to split these reads up into 64 byte chunks */
result = 0;
@@ -2275,8 +2118,6 @@ static int rom_read(struct usb_serial *serial, __u16 extAddr,
current_length = 64;
else
current_length = length;
-/* dbg("%s - %x, %x, %d", __func__,
- extAddr, addr, current_length); */
result = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
USB_REQUEST_ION_READ_ROM,
@@ -2307,20 +2148,14 @@ static int send_iosp_ext_cmd(struct edgeport_port *edge_port,
int length = 0;
int status = 0;
- dbg("%s - %d, %d", __func__, command, param);
-
buffer = kmalloc(10, GFP_ATOMIC);
- if (!buffer) {
- dev_err(&edge_port->port->dev,
- "%s - kmalloc(%d) failed.\n", __func__, 10);
+ if (!buffer)
return -ENOMEM;
- }
currentCommand = buffer;
- MAKE_CMD_EXT_CMD(&currentCommand, &length,
- edge_port->port->number - edge_port->port->serial->minor,
- command, param);
+ MAKE_CMD_EXT_CMD(&currentCommand, &length, edge_port->port->port_number,
+ command, param);
status = write_cmd_usb(edge_port, buffer, length);
if (status) {
@@ -2341,12 +2176,11 @@ static int write_cmd_usb(struct edgeport_port *edge_port,
{
struct edgeport_serial *edge_serial =
usb_get_serial_data(edge_port->port->serial);
+ struct device *dev = &edge_port->port->dev;
int status = 0;
struct urb *urb;
- int timeout;
- usb_serial_debug_data(debug, &edge_port->port->dev,
- __func__, length, buffer);
+ usb_serial_debug_data(dev, __func__, length, buffer);
/* Allocate our next urb */
urb = usb_alloc_urb(0, GFP_ATOMIC);
@@ -2354,8 +2188,8 @@ static int write_cmd_usb(struct edgeport_port *edge_port,
return -ENOMEM;
atomic_inc(&CmdUrbs);
- dbg("%s - ALLOCATE URB %p (outstanding %d)",
- __func__, urb, atomic_read(&CmdUrbs));
+ dev_dbg(dev, "%s - ALLOCATE URB %p (outstanding %d)\n",
+ __func__, urb, atomic_read(&CmdUrbs));
usb_fill_bulk_urb(urb, edge_serial->serial->dev,
usb_sndbulkpipe(edge_serial->serial->dev,
@@ -2367,23 +2201,20 @@ static int write_cmd_usb(struct edgeport_port *edge_port,
if (status) {
/* something went wrong */
- dev_err(&edge_port->port->dev,
- "%s - usb_submit_urb(write command) failed, status = %d\n",
- __func__, status);
+ dev_err(dev, "%s - usb_submit_urb(write command) failed, status = %d\n",
+ __func__, status);
usb_kill_urb(urb);
usb_free_urb(urb);
atomic_dec(&CmdUrbs);
return status;
}
- /* wait for command to finish */
- timeout = COMMAND_TIMEOUT;
#if 0
wait_event(&edge_port->wait_command, !edge_port->commandPending);
if (edge_port->commandPending) {
/* command timed out */
- dbg("%s - command timed out", __func__);
+ dev_dbg(dev, "%s - command timed out\n", __func__);
status = -EINVAL;
}
#endif
@@ -2401,38 +2232,34 @@ static int send_cmd_write_baud_rate(struct edgeport_port *edge_port,
{
struct edgeport_serial *edge_serial =
usb_get_serial_data(edge_port->port->serial);
+ struct device *dev = &edge_port->port->dev;
unsigned char *cmdBuffer;
unsigned char *currCmd;
int cmdLen = 0;
int divisor;
int status;
- unsigned char number =
- edge_port->port->number - edge_port->port->serial->minor;
+ u32 number = edge_port->port->port_number;
if (edge_serial->is_epic &&
!edge_serial->epic_descriptor.Supports.IOSPSetBaudRate) {
- dbg("SendCmdWriteBaudRate - NOT Setting baud rate for port = %d, baud = %d",
- edge_port->port->number, baudRate);
+ dev_dbg(dev, "SendCmdWriteBaudRate - NOT Setting baud rate for port, baud = %d\n",
+ baudRate);
return 0;
}
- dbg("%s - port = %d, baud = %d", __func__,
- edge_port->port->number, baudRate);
+ dev_dbg(dev, "%s - baud = %d\n", __func__, baudRate);
- status = calc_baud_rate_divisor(baudRate, &divisor);
+ status = calc_baud_rate_divisor(dev, baudRate, &divisor);
if (status) {
- dev_err(&edge_port->port->dev, "%s - bad baud rate\n",
- __func__);
+ dev_err(dev, "%s - bad baud rate\n", __func__);
return status;
}
/* Alloc memory for the string of commands. */
cmdBuffer = kmalloc(0x100, GFP_ATOMIC);
- if (!cmdBuffer) {
- dev_err(&edge_port->port->dev,
- "%s - kmalloc(%d) failed.\n", __func__, 0x100);
+ if (!cmdBuffer)
return -ENOMEM;
- }
+
currCmd = cmdBuffer;
/* Enable access to divisor latch */
@@ -2461,14 +2288,11 @@ static int send_cmd_write_baud_rate(struct edgeport_port *edge_port,
* this function calculates the proper baud rate divisor for the specified
* baud rate.
*****************************************************************************/
-static int calc_baud_rate_divisor(int baudrate, int *divisor)
+static int calc_baud_rate_divisor(struct device *dev, int baudrate, int *divisor)
{
int i;
__u16 custom;
-
- dbg("%s - %d", __func__, baudrate);
-
for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
if (divisor_table[i].BaudRate == baudrate) {
*divisor = divisor_table[i].Divisor;
@@ -2485,7 +2309,7 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor)
*divisor = custom;
- dbg("%s - Baud %d = %d", __func__, baudrate, custom);
+ dev_dbg(dev, "%s - Baud %d = %d\n", __func__, baudrate, custom);
return 0;
}
@@ -2502,25 +2326,26 @@ static int send_cmd_write_uart_register(struct edgeport_port *edge_port,
{
struct edgeport_serial *edge_serial =
usb_get_serial_data(edge_port->port->serial);
+ struct device *dev = &edge_port->port->dev;
unsigned char *cmdBuffer;
unsigned char *currCmd;
unsigned long cmdLen = 0;
int status;
- dbg("%s - write to %s register 0x%02x",
- (regNum == MCR) ? "MCR" : "LCR", __func__, regValue);
+ dev_dbg(dev, "%s - write to %s register 0x%02x\n",
+ (regNum == MCR) ? "MCR" : "LCR", __func__, regValue);
if (edge_serial->is_epic &&
!edge_serial->epic_descriptor.Supports.IOSPWriteMCR &&
regNum == MCR) {
- dbg("SendCmdWriteUartReg - Not writing to MCR Register");
+ dev_dbg(dev, "SendCmdWriteUartReg - Not writing to MCR Register\n");
return 0;
}
if (edge_serial->is_epic &&
!edge_serial->epic_descriptor.Supports.IOSPWriteLCR &&
regNum == LCR) {
- dbg("SendCmdWriteUartReg - Not writing to LCR Register");
+ dev_dbg(dev, "SendCmdWriteUartReg - Not writing to LCR Register\n");
return 0;
}
@@ -2532,9 +2357,8 @@ static int send_cmd_write_uart_register(struct edgeport_port *edge_port,
currCmd = cmdBuffer;
/* Build a cmd in the buffer to write the given register */
- MAKE_CMD_WRITE_REG(&currCmd, &cmdLen,
- edge_port->port->number - edge_port->port->serial->minor,
- regNum, regValue);
+ MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, edge_port->port->port_number,
+ regNum, regValue);
status = write_cmd_usb(edge_port, cmdBuffer, cmdLen);
if (status) {
@@ -2555,6 +2379,7 @@ static int send_cmd_write_uart_register(struct edgeport_port *edge_port,
static void change_port_settings(struct tty_struct *tty,
struct edgeport_port *edge_port, struct ktermios *old_termios)
{
+ struct device *dev = &edge_port->port->dev;
struct edgeport_serial *edge_serial =
usb_get_serial_data(edge_port->port->serial);
int baud;
@@ -2567,33 +2392,31 @@ static void change_port_settings(struct tty_struct *tty,
__u8 txFlow;
int status;
- dbg("%s - port %d", __func__, edge_port->port->number);
-
if (!edge_port->open &&
!edge_port->openPending) {
- dbg("%s - port not opened", __func__);
+ dev_dbg(dev, "%s - port not opened\n", __func__);
return;
}
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
switch (cflag & CSIZE) {
case CS5:
lData = LCR_BITS_5; mask = 0x1f;
- dbg("%s - data bits = 5", __func__);
+ dev_dbg(dev, "%s - data bits = 5\n", __func__);
break;
case CS6:
lData = LCR_BITS_6; mask = 0x3f;
- dbg("%s - data bits = 6", __func__);
+ dev_dbg(dev, "%s - data bits = 6\n", __func__);
break;
case CS7:
lData = LCR_BITS_7; mask = 0x7f;
- dbg("%s - data bits = 7", __func__);
+ dev_dbg(dev, "%s - data bits = 7\n", __func__);
break;
default:
case CS8:
lData = LCR_BITS_8;
- dbg("%s - data bits = 8", __func__);
+ dev_dbg(dev, "%s - data bits = 8\n", __func__);
break;
}
@@ -2602,28 +2425,28 @@ static void change_port_settings(struct tty_struct *tty,
if (cflag & CMSPAR) {
if (cflag & PARODD) {
lParity = LCR_PAR_MARK;
- dbg("%s - parity = mark", __func__);
+ dev_dbg(dev, "%s - parity = mark\n", __func__);
} else {
lParity = LCR_PAR_SPACE;
- dbg("%s - parity = space", __func__);
+ dev_dbg(dev, "%s - parity = space\n", __func__);
}
} else if (cflag & PARODD) {
lParity = LCR_PAR_ODD;
- dbg("%s - parity = odd", __func__);
+ dev_dbg(dev, "%s - parity = odd\n", __func__);
} else {
lParity = LCR_PAR_EVEN;
- dbg("%s - parity = even", __func__);
+ dev_dbg(dev, "%s - parity = even\n", __func__);
}
} else {
- dbg("%s - parity = none", __func__);
+ dev_dbg(dev, "%s - parity = none\n", __func__);
}
if (cflag & CSTOPB) {
lStop = LCR_STOP_2;
- dbg("%s - stop bits = 2", __func__);
+ dev_dbg(dev, "%s - stop bits = 2\n", __func__);
} else {
lStop = LCR_STOP_1;
- dbg("%s - stop bits = 1", __func__);
+ dev_dbg(dev, "%s - stop bits = 1\n", __func__);
}
/* figure out the flow control settings */
@@ -2631,9 +2454,9 @@ static void change_port_settings(struct tty_struct *tty,
if (cflag & CRTSCTS) {
rxFlow |= IOSP_RX_FLOW_RTS;
txFlow |= IOSP_TX_FLOW_CTS;
- dbg("%s - RTS/CTS is enabled", __func__);
+ dev_dbg(dev, "%s - RTS/CTS is enabled\n", __func__);
} else {
- dbg("%s - RTS/CTS is disabled", __func__);
+ dev_dbg(dev, "%s - RTS/CTS is disabled\n", __func__);
}
/* if we are implementing XON/XOFF, set the start and stop character
@@ -2654,19 +2477,19 @@ static void change_port_settings(struct tty_struct *tty,
/* if we are implementing INBOUND XON/XOFF */
if (I_IXOFF(tty)) {
rxFlow |= IOSP_RX_FLOW_XON_XOFF;
- dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
- __func__, start_char, stop_char);
+ dev_dbg(dev, "%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x\n",
+ __func__, start_char, stop_char);
} else {
- dbg("%s - INBOUND XON/XOFF is disabled", __func__);
+ dev_dbg(dev, "%s - INBOUND XON/XOFF is disabled\n", __func__);
}
/* if we are implementing OUTBOUND XON/XOFF */
if (I_IXON(tty)) {
txFlow |= IOSP_TX_FLOW_XON_XOFF;
- dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
- __func__, start_char, stop_char);
+ dev_dbg(dev, "%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x\n",
+ __func__, start_char, stop_char);
} else {
- dbg("%s - OUTBOUND XON/XOFF is disabled", __func__);
+ dev_dbg(dev, "%s - OUTBOUND XON/XOFF is disabled\n", __func__);
}
}
@@ -2709,7 +2532,7 @@ static void change_port_settings(struct tty_struct *tty,
baud = 9600;
}
- dbg("%s - baud rate = %d", __func__, baud);
+ dev_dbg(dev, "%s - baud rate = %d\n", __func__, baud);
status = send_cmd_write_baud_rate(edge_port, baud);
if (status == -1) {
/* Speed change was not possible - put back the old speed */
@@ -2751,9 +2574,10 @@ static void unicode_to_ascii(char *string, int buflen,
****************************************************************************/
static void get_manufacturing_desc(struct edgeport_serial *edge_serial)
{
+ struct device *dev = &edge_serial->serial->dev->dev;
int response;
- dbg("getting manufacturer descriptor");
+ dev_dbg(dev, "getting manufacturer descriptor\n");
response = rom_read(edge_serial->serial,
(EDGE_MANUF_DESC_ADDR & 0xffff0000) >> 16,
@@ -2762,42 +2586,41 @@ static void get_manufacturing_desc(struct edgeport_serial *edge_serial)
(__u8 *)(&edge_serial->manuf_descriptor));
if (response < 1)
- dev_err(&edge_serial->serial->dev->dev,
- "error in getting manufacturer descriptor\n");
+ dev_err(dev, "error in getting manufacturer descriptor\n");
else {
char string[30];
- dbg("**Manufacturer Descriptor");
- dbg(" RomSize: %dK",
+ dev_dbg(dev, "**Manufacturer Descriptor\n");
+ dev_dbg(dev, " RomSize: %dK\n",
edge_serial->manuf_descriptor.RomSize);
- dbg(" RamSize: %dK",
+ dev_dbg(dev, " RamSize: %dK\n",
edge_serial->manuf_descriptor.RamSize);
- dbg(" CpuRev: %d",
+ dev_dbg(dev, " CpuRev: %d\n",
edge_serial->manuf_descriptor.CpuRev);
- dbg(" BoardRev: %d",
+ dev_dbg(dev, " BoardRev: %d\n",
edge_serial->manuf_descriptor.BoardRev);
- dbg(" NumPorts: %d",
+ dev_dbg(dev, " NumPorts: %d\n",
edge_serial->manuf_descriptor.NumPorts);
- dbg(" DescDate: %d/%d/%d",
+ dev_dbg(dev, " DescDate: %d/%d/%d\n",
edge_serial->manuf_descriptor.DescDate[0],
edge_serial->manuf_descriptor.DescDate[1],
edge_serial->manuf_descriptor.DescDate[2]+1900);
unicode_to_ascii(string, sizeof(string),
edge_serial->manuf_descriptor.SerialNumber,
edge_serial->manuf_descriptor.SerNumLength/2);
- dbg(" SerialNumber: %s", string);
+ dev_dbg(dev, " SerialNumber: %s\n", string);
unicode_to_ascii(string, sizeof(string),
edge_serial->manuf_descriptor.AssemblyNumber,
edge_serial->manuf_descriptor.AssemblyNumLength/2);
- dbg(" AssemblyNumber: %s", string);
+ dev_dbg(dev, " AssemblyNumber: %s\n", string);
unicode_to_ascii(string, sizeof(string),
edge_serial->manuf_descriptor.OemAssyNumber,
edge_serial->manuf_descriptor.OemAssyNumLength/2);
- dbg(" OemAssyNumber: %s", string);
- dbg(" UartType: %d",
+ dev_dbg(dev, " OemAssyNumber: %s\n", string);
+ dev_dbg(dev, " UartType: %d\n",
edge_serial->manuf_descriptor.UartType);
- dbg(" IonPid: %d",
+ dev_dbg(dev, " IonPid: %d\n",
edge_serial->manuf_descriptor.IonPid);
- dbg(" IonConfig: %d",
+ dev_dbg(dev, " IonConfig: %d\n",
edge_serial->manuf_descriptor.IonConfig);
}
}
@@ -2810,9 +2633,10 @@ static void get_manufacturing_desc(struct edgeport_serial *edge_serial)
****************************************************************************/
static void get_boot_desc(struct edgeport_serial *edge_serial)
{
+ struct device *dev = &edge_serial->serial->dev->dev;
int response;
- dbg("getting boot descriptor");
+ dev_dbg(dev, "getting boot descriptor\n");
response = rom_read(edge_serial->serial,
(EDGE_BOOT_DESC_ADDR & 0xffff0000) >> 16,
@@ -2821,23 +2645,22 @@ static void get_boot_desc(struct edgeport_serial *edge_serial)
(__u8 *)(&edge_serial->boot_descriptor));
if (response < 1)
- dev_err(&edge_serial->serial->dev->dev,
- "error in getting boot descriptor\n");
+ dev_err(dev, "error in getting boot descriptor\n");
else {
- dbg("**Boot Descriptor:");
- dbg(" BootCodeLength: %d",
- le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength));
- dbg(" MajorVersion: %d",
+ dev_dbg(dev, "**Boot Descriptor:\n");
+ dev_dbg(dev, " BootCodeLength: %d\n",
+ le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength));
+ dev_dbg(dev, " MajorVersion: %d\n",
edge_serial->boot_descriptor.MajorVersion);
- dbg(" MinorVersion: %d",
+ dev_dbg(dev, " MinorVersion: %d\n",
edge_serial->boot_descriptor.MinorVersion);
- dbg(" BuildNumber: %d",
+ dev_dbg(dev, " BuildNumber: %d\n",
le16_to_cpu(edge_serial->boot_descriptor.BuildNumber));
- dbg(" Capabilities: 0x%x",
+ dev_dbg(dev, " Capabilities: 0x%x\n",
le16_to_cpu(edge_serial->boot_descriptor.Capabilities));
- dbg(" UConfig0: %d",
+ dev_dbg(dev, " UConfig0: %d\n",
edge_serial->boot_descriptor.UConfig0);
- dbg(" UConfig1: %d",
+ dev_dbg(dev, " UConfig1: %d\n",
edge_serial->boot_descriptor.UConfig1);
}
}
@@ -2849,6 +2672,7 @@ static void get_boot_desc(struct edgeport_serial *edge_serial)
****************************************************************************/
static void load_application_firmware(struct edgeport_serial *edge_serial)
{
+ struct device *dev = &edge_serial->serial->dev->dev;
const struct ihex_binrec *rec;
const struct firmware *fw;
const char *fw_name;
@@ -2869,7 +2693,7 @@ static void load_application_firmware(struct edgeport_serial *edge_serial)
break;
case EDGE_DOWNLOAD_FILE_NONE:
- dbg("No download file specified, skipping download");
+ dev_dbg(dev, "No download file specified, skipping download\n");
return;
default:
@@ -2879,7 +2703,7 @@ static void load_application_firmware(struct edgeport_serial *edge_serial)
response = request_ihex_firmware(&fw, fw_name,
&edge_serial->serial->dev->dev);
if (response) {
- printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+ dev_err(dev, "Failed to load image \"%s\" err %d\n",
fw_name, response);
return;
}
@@ -2887,10 +2711,10 @@ static void load_application_firmware(struct edgeport_serial *edge_serial)
rec = (const struct ihex_binrec *)fw->data;
build = (rec->data[2] << 8) | rec->data[3];
- dbg("%s %d.%d.%d", fw_info, rec->data[0], rec->data[1], build);
+ dev_dbg(dev, "%s %d.%d.%d\n", fw_info, rec->data[0], rec->data[1], build);
- edge_serial->product_info.FirmwareMajorVersion = fw->data[0];
- edge_serial->product_info.FirmwareMinorVersion = fw->data[1];
+ edge_serial->product_info.FirmwareMajorVersion = rec->data[0];
+ edge_serial->product_info.FirmwareMinorVersion = rec->data[1];
edge_serial->product_info.FirmwareBuildNumber = cpu_to_le16(build);
for (rec = ihex_next_binrec(rec); rec;
@@ -2910,10 +2734,10 @@ static void load_application_firmware(struct edgeport_serial *edge_serial)
}
}
- dbg("sending exec_dl_code");
- response = usb_control_msg (edge_serial->serial->dev,
- usb_sndctrlpipe(edge_serial->serial->dev, 0),
- USB_REQUEST_ION_EXEC_DL_CODE,
+ dev_dbg(dev, "sending exec_dl_code\n");
+ response = usb_control_msg (edge_serial->serial->dev,
+ usb_sndctrlpipe(edge_serial->serial->dev, 0),
+ USB_REQUEST_ION_EXEC_DL_CODE,
0x40, 0x4000, 0x0001, NULL, 0, 3000);
release_firmware(fw);
@@ -2926,9 +2750,9 @@ static void load_application_firmware(struct edgeport_serial *edge_serial)
static int edge_startup(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial;
- struct edgeport_port *edge_port;
struct usb_device *dev;
- int i, j;
+ struct device *ddev = &serial->dev->dev;
+ int i;
int response;
bool interrupt_in_found;
bool bulk_in_found;
@@ -2941,10 +2765,9 @@ static int edge_startup(struct usb_serial *serial)
/* create our private serial structure */
edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
- if (edge_serial == NULL) {
- dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ if (!edge_serial)
return -ENOMEM;
- }
+
spin_lock_init(&edge_serial->es_lock);
edge_serial->serial = serial;
usb_set_serial_data(serial, edge_serial);
@@ -2979,32 +2802,31 @@ static int edge_startup(struct usb_serial *serial)
/* serial->num_ports = serial->product_info.NumPorts; */
if ((!edge_serial->is_epic) &&
(edge_serial->product_info.NumPorts != serial->num_ports)) {
- dev_warn(&serial->dev->dev, "Device Reported %d serial ports "
- "vs. core thinking we have %d ports, email "
- "greg@kroah.com this information.\n",
+ dev_warn(ddev,
+ "Device Reported %d serial ports vs. core thinking we have %d ports, email greg@kroah.com this information.\n",
edge_serial->product_info.NumPorts,
serial->num_ports);
}
- dbg("%s - time 1 %ld", __func__, jiffies);
+ dev_dbg(ddev, "%s - time 1 %ld\n", __func__, jiffies);
/* If not an EPiC device */
if (!edge_serial->is_epic) {
/* now load the application firmware into this device */
load_application_firmware(edge_serial);
- dbg("%s - time 2 %ld", __func__, jiffies);
+ dev_dbg(ddev, "%s - time 2 %ld\n", __func__, jiffies);
/* Check current Edgeport EEPROM and update if necessary */
update_edgeport_E2PROM(edge_serial);
- dbg("%s - time 3 %ld", __func__, jiffies);
+ dev_dbg(ddev, "%s - time 3 %ld\n", __func__, jiffies);
/* set the configuration to use #1 */
-/* dbg("set_configuration 1"); */
+/* dev_dbg(ddev, "set_configuration 1\n"); */
/* usb_set_configuration (dev, 1); */
}
- dbg(" FirmwareMajorVersion %d.%d.%d",
+ dev_dbg(ddev, " FirmwareMajorVersion %d.%d.%d\n",
edge_serial->product_info.FirmwareMajorVersion,
edge_serial->product_info.FirmwareMinorVersion,
le16_to_cpu(edge_serial->product_info.FirmwareBuildNumber));
@@ -3012,26 +2834,6 @@ static int edge_startup(struct usb_serial *serial)
/* we set up the pointers to the endpoints in the edge_open function,
* as the structures aren't created yet. */
- /* set up our port private structures */
- for (i = 0; i < serial->num_ports; ++i) {
- edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
- if (edge_port == NULL) {
- dev_err(&serial->dev->dev, "%s - Out of memory\n",
- __func__);
- for (j = 0; j < i; ++j) {
- kfree(usb_get_serial_port_data(serial->port[j]));
- usb_set_serial_port_data(serial->port[j],
- NULL);
- }
- usb_set_serial_data(serial, NULL);
- kfree(edge_serial);
- return -ENOMEM;
- }
- spin_lock_init(&edge_port->ep_lock);
- edge_port->port = serial->port[i];
- usb_set_serial_port_data(serial->port[i], edge_port);
- }
-
response = 0;
if (edge_serial->is_epic) {
@@ -3045,23 +2847,21 @@ static int edge_startup(struct usb_serial *serial)
endpoint = &serial->interface->altsetting[0].
endpoint[i].desc;
- buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+ buffer_size = usb_endpoint_maxp(endpoint);
if (!interrupt_in_found &&
(usb_endpoint_is_int_in(endpoint))) {
/* we found a interrupt in endpoint */
- dbg("found interrupt in");
+ dev_dbg(ddev, "found interrupt in\n");
/* not set up yet, so do it now */
edge_serial->interrupt_read_urb =
usb_alloc_urb(0, GFP_KERNEL);
- if (!edge_serial->interrupt_read_urb) {
- dev_err(&dev->dev, "out of memory\n");
+ if (!edge_serial->interrupt_read_urb)
return -ENOMEM;
- }
+
edge_serial->interrupt_in_buffer =
kmalloc(buffer_size, GFP_KERNEL);
if (!edge_serial->interrupt_in_buffer) {
- dev_err(&dev->dev, "out of memory\n");
usb_free_urb(edge_serial->interrupt_read_urb);
return -ENOMEM;
}
@@ -3086,19 +2886,17 @@ static int edge_startup(struct usb_serial *serial)
if (!bulk_in_found &&
(usb_endpoint_is_bulk_in(endpoint))) {
/* we found a bulk in endpoint */
- dbg("found bulk in");
+ dev_dbg(ddev, "found bulk in\n");
/* not set up yet, so do it now */
edge_serial->read_urb =
usb_alloc_urb(0, GFP_KERNEL);
- if (!edge_serial->read_urb) {
- dev_err(&dev->dev, "out of memory\n");
+ if (!edge_serial->read_urb)
return -ENOMEM;
- }
+
edge_serial->bulk_in_buffer =
kmalloc(buffer_size, GFP_KERNEL);
if (!edge_serial->bulk_in_buffer) {
- dev_err(&dev->dev, "out of memory\n");
usb_free_urb(edge_serial->read_urb);
return -ENOMEM;
}
@@ -3110,7 +2908,7 @@ static int edge_startup(struct usb_serial *serial)
usb_rcvbulkpipe(dev,
endpoint->bEndpointAddress),
edge_serial->bulk_in_buffer,
- le16_to_cpu(endpoint->wMaxPacketSize),
+ usb_endpoint_maxp(endpoint),
edge_bulk_in_callback,
edge_serial);
bulk_in_found = true;
@@ -3119,7 +2917,7 @@ static int edge_startup(struct usb_serial *serial)
if (!bulk_out_found &&
(usb_endpoint_is_bulk_out(endpoint))) {
/* we found a bulk out endpoint */
- dbg("found bulk out");
+ dev_dbg(ddev, "found bulk out\n");
edge_serial->bulk_out_endpoint =
endpoint->bEndpointAddress;
bulk_out_found = true;
@@ -3127,8 +2925,7 @@ static int edge_startup(struct usb_serial *serial)
}
if (!interrupt_in_found || !bulk_in_found || !bulk_out_found) {
- dev_err(&dev->dev, "Error - the proper endpoints "
- "were not found!\n");
+ dev_err(ddev, "Error - the proper endpoints were not found!\n");
return -ENODEV;
}
@@ -3137,8 +2934,7 @@ static int edge_startup(struct usb_serial *serial)
response = usb_submit_urb(edge_serial->interrupt_read_urb,
GFP_KERNEL);
if (response)
- dev_err(&dev->dev,
- "%s - Error %d submitting control urb\n",
+ dev_err(ddev, "%s - Error %d submitting control urb\n",
__func__, response);
}
return response;
@@ -3153,8 +2949,6 @@ static void edge_disconnect(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
- dbg("%s", __func__);
-
/* stop reads and writes on all ports */
/* free up our endpoint stuff */
if (edge_serial->is_epic) {
@@ -3176,75 +2970,38 @@ static void edge_disconnect(struct usb_serial *serial)
static void edge_release(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
- int i;
-
- dbg("%s", __func__);
-
- for (i = 0; i < serial->num_ports; ++i)
- kfree(usb_get_serial_port_data(serial->port[i]));
kfree(edge_serial);
}
-
-/****************************************************************************
- * edgeport_init
- * This is called by the module subsystem, or on startup to initialize us
- ****************************************************************************/
-static int __init edgeport_init(void)
+static int edge_port_probe(struct usb_serial_port *port)
{
- int retval;
-
- retval = usb_serial_register(&edgeport_2port_device);
- if (retval)
- goto failed_2port_device_register;
- retval = usb_serial_register(&edgeport_4port_device);
- if (retval)
- goto failed_4port_device_register;
- retval = usb_serial_register(&edgeport_8port_device);
- if (retval)
- goto failed_8port_device_register;
- retval = usb_serial_register(&epic_device);
- if (retval)
- goto failed_epic_device_register;
- retval = usb_register(&io_driver);
- if (retval)
- goto failed_usb_register;
- atomic_set(&CmdUrbs, 0);
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
+ struct edgeport_port *edge_port;
-failed_usb_register:
- usb_serial_deregister(&epic_device);
-failed_epic_device_register:
- usb_serial_deregister(&edgeport_8port_device);
-failed_8port_device_register:
- usb_serial_deregister(&edgeport_4port_device);
-failed_4port_device_register:
- usb_serial_deregister(&edgeport_2port_device);
-failed_2port_device_register:
- return retval;
-}
+ edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL);
+ if (!edge_port)
+ return -ENOMEM;
+ spin_lock_init(&edge_port->ep_lock);
+ edge_port->port = port;
-/****************************************************************************
- * edgeport_exit
- * Called when the driver is about to be unloaded.
- ****************************************************************************/
-static void __exit edgeport_exit (void)
+ usb_set_serial_port_data(port, edge_port);
+
+ return 0;
+}
+
+static int edge_port_remove(struct usb_serial_port *port)
{
- usb_deregister(&io_driver);
- usb_serial_deregister(&edgeport_2port_device);
- usb_serial_deregister(&edgeport_4port_device);
- usb_serial_deregister(&edgeport_8port_device);
- usb_serial_deregister(&epic_device);
+ struct edgeport_port *edge_port;
+
+ edge_port = usb_get_serial_port_data(port);
+ kfree(edge_port);
+
+ return 0;
}
-module_init(edgeport_init);
-module_exit(edgeport_exit);
+module_usb_serial_driver(serial_drivers, id_table_combined);
-/* Module information */
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
@@ -3252,6 +3009,3 @@ MODULE_FIRMWARE("edgeport/boot.fw");
MODULE_FIRMWARE("edgeport/boot2.fw");
MODULE_FIRMWARE("edgeport/down.fw");
MODULE_FIRMWARE("edgeport/down2.fw");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/io_edgeport.h b/drivers/usb/serial/io_edgeport.h
index dced7ec6547..ad9c1d47a61 100644
--- a/drivers/usb/serial/io_edgeport.h
+++ b/drivers/usb/serial/io_edgeport.h
@@ -68,7 +68,7 @@ struct comMapper {
#define PROC_SET_COM_ENTRY 2
-/* The following sturcture is passed to the write */
+/* The following structure is passed to the write */
struct procWrite {
int Command;
union {
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index 6ab2a3f97fe..ae5fac5656c 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -95,21 +95,12 @@ static const struct usb_device_id id_table_combined[] = {
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver io_driver = {
- .name = "io_edgeport",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
- .no_dynamic_id = 1,
-};
-
static struct usb_serial_driver edgeport_2port_device = {
.driver = {
.owner = THIS_MODULE,
.name = "edgeport_2",
},
.description = "Edgeport 2 port adapter",
- .usb_driver = &io_driver,
.id_table = edgeport_2port_id_table,
.num_ports = 2,
.open = edge_open,
@@ -119,11 +110,14 @@ static struct usb_serial_driver edgeport_2port_device = {
.attach = edge_startup,
.disconnect = edge_disconnect,
.release = edge_release,
+ .port_probe = edge_port_probe,
+ .port_remove = edge_port_remove,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
- .get_icount = edge_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
@@ -139,7 +133,6 @@ static struct usb_serial_driver edgeport_4port_device = {
.name = "edgeport_4",
},
.description = "Edgeport 4 port adapter",
- .usb_driver = &io_driver,
.id_table = edgeport_4port_id_table,
.num_ports = 4,
.open = edge_open,
@@ -149,11 +142,14 @@ static struct usb_serial_driver edgeport_4port_device = {
.attach = edge_startup,
.disconnect = edge_disconnect,
.release = edge_release,
+ .port_probe = edge_port_probe,
+ .port_remove = edge_port_remove,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
- .get_icount = edge_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
@@ -169,7 +165,6 @@ static struct usb_serial_driver edgeport_8port_device = {
.name = "edgeport_8",
},
.description = "Edgeport 8 port adapter",
- .usb_driver = &io_driver,
.id_table = edgeport_8port_id_table,
.num_ports = 8,
.open = edge_open,
@@ -179,11 +174,14 @@ static struct usb_serial_driver edgeport_8port_device = {
.attach = edge_startup,
.disconnect = edge_disconnect,
.release = edge_release,
+ .port_probe = edge_port_probe,
+ .port_remove = edge_port_remove,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
- .get_icount = edge_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
@@ -208,11 +206,14 @@ static struct usb_serial_driver epic_device = {
.attach = edge_startup,
.disconnect = edge_disconnect,
.release = edge_release,
+ .port_probe = edge_port_probe,
+ .port_remove = edge_port_remove,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
- .get_icount = edge_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
@@ -222,5 +223,10 @@ static struct usb_serial_driver epic_device = {
.write_bulk_callback = edge_bulk_out_data_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &edgeport_2port_device, &edgeport_4port_device,
+ &edgeport_8port_device, &epic_device, NULL
+};
+
#endif
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 22506b095c4..c0a42e9e677 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -15,19 +15,11 @@
* For questions or problems with this driver, contact Inside Out
* Networks technical support, or Peter Berger <pberger@brimson.com>,
* or Al Borchers <alborchers@steinerpoint.com>.
- *
- * Version history:
- *
- * July 11, 2002 Removed 4 port device structure since all TI UMP
- * chips have only 2 ports
- * David Iacovelli (davidi@ionetworks.com)
- *
*/
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -36,6 +28,7 @@
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/serial.h>
+#include <linux/swab.h>
#include <linux/kfifo.h>
#include <linux/ioctl.h>
#include <linux/firmware.h>
@@ -47,10 +40,6 @@
#include "io_usbvend.h"
#include "io_ti.h"
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.7mode043006"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
#define DRIVER_DESC "Edgeport USB Serial Driver"
@@ -75,8 +64,6 @@
#define EDGE_CLOSING_WAIT 4000 /* in .01 sec */
-#define EDGE_OUT_BUF_SIZE 1024
-
/* Product information read from the Edgeport */
struct product_info {
@@ -97,17 +84,13 @@ struct edgeport_port {
int baud_rate;
int close_pending;
int lsr_event;
- struct async_icount icount;
- wait_queue_head_t delta_msr_wait; /* for handling sleeping while
- waiting for msr change to
- happen */
+
struct edgeport_serial *edge_serial;
struct usb_serial_port *port;
__u8 bUartMode; /* Port type, 0: RS232, etc. */
spinlock_t ep_lock;
int ep_read_urb_state;
int ep_write_urb_in_use;
- struct kfifo write_fifo;
};
struct edgeport_serial {
@@ -204,34 +187,23 @@ static const struct usb_device_id id_table_combined[] = {
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver io_driver = {
- .name = "io_ti",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
- .no_dynamic_id = 1,
-};
-
-
static unsigned char OperationalMajorVersion;
static unsigned char OperationalMinorVersion;
static unsigned short OperationalBuildNumber;
-static int debug;
-
static int closing_wait = EDGE_CLOSING_WAIT;
-static int ignore_cpu_rev;
+static bool ignore_cpu_rev;
static int default_uart_mode; /* RS232 */
-static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
- unsigned char *data, int length);
+static void edge_tty_recv(struct usb_serial_port *port, unsigned char *data,
+ int length);
static void stop_read(struct edgeport_port *edge_port);
static int restart_read(struct edgeport_port *edge_port);
static void edge_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios);
-static void edge_send(struct tty_struct *tty);
+static void edge_send(struct usb_serial_port *port, struct tty_struct *tty);
/* sysfs attributes */
static int edge_create_sysfs_attrs(struct usb_serial_port *port);
@@ -249,8 +221,8 @@ static int ti_vread_sync(struct usb_device *dev, __u8 request,
if (status < 0)
return status;
if (status != size) {
- dbg("%s - wanted to write %d, but only wrote %d",
- __func__, size, status);
+ dev_dbg(&dev->dev, "%s - wanted to write %d, but only wrote %d\n",
+ __func__, size, status);
return -ECOMM;
}
return 0;
@@ -267,8 +239,8 @@ static int ti_vsend_sync(struct usb_device *dev, __u8 request,
if (status < 0)
return status;
if (status != size) {
- dbg("%s - wanted to write %d, but only wrote %d",
- __func__, size, status);
+ dev_dbg(&dev->dev, "%s - wanted to write %d, but only wrote %d\n",
+ __func__, size, status);
return -ECOMM;
}
return 0;
@@ -284,9 +256,9 @@ static int send_cmd(struct usb_device *dev, __u8 command,
/* clear tx/rx buffers and fifo in TI UMP */
static int purge_port(struct usb_serial_port *port, __u16 mask)
{
- int port_number = port->number - port->serial->minor;
+ int port_number = port->port_number;
- dbg("%s - port %d, mask %x", __func__, port_number, mask);
+ dev_dbg(&port->dev, "%s - port %d, mask %x\n", __func__, port_number, mask);
return send_cmd(port->serial->dev,
UMPC_PURGE_PORT,
@@ -309,9 +281,9 @@ static int read_download_mem(struct usb_device *dev, int start_address,
{
int status = 0;
__u8 read_length;
- __be16 be_start_address;
+ u16 be_start_address;
- dbg("%s - @ %x for %d", __func__, start_address, length);
+ dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, length);
/* Read in blocks of 64 bytes
* (TI firmware can't handle more than 64 byte reads)
@@ -323,23 +295,25 @@ static int read_download_mem(struct usb_device *dev, int start_address,
read_length = (__u8)length;
if (read_length > 1) {
- dbg("%s - @ %x for %d", __func__,
- start_address, read_length);
+ dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, read_length);
}
- be_start_address = cpu_to_be16(start_address);
+ /*
+ * NOTE: Must use swab as wIndex is sent in little-endian
+ * byte order regardless of host byte order.
+ */
+ be_start_address = swab16((u16)start_address);
status = ti_vread_sync(dev, UMPC_MEMORY_READ,
(__u16)address_type,
- (__force __u16)be_start_address,
+ be_start_address,
buffer, read_length);
if (status) {
- dbg("%s - ERROR %x", __func__, status);
+ dev_dbg(&dev->dev, "%s - ERROR %x\n", __func__, status);
return status;
}
if (read_length > 1)
- usb_serial_debug_data(debug, &dev->dev, __func__,
- read_length, buffer);
+ usb_serial_debug_data(&dev->dev, __func__, read_length, buffer);
/* Update pointers/length */
start_address += read_length;
@@ -369,15 +343,14 @@ static int read_boot_mem(struct edgeport_serial *serial,
UMPC_MEMORY_READ, serial->TI_I2C_Type,
(__u16)(start_address+i), &buffer[i], 0x01);
if (status) {
- dbg("%s - ERROR %x", __func__, status);
+ dev_dbg(&serial->serial->dev->dev, "%s - ERROR %x\n", __func__, status);
return status;
}
}
- dbg("%s - start_address = %x, length = %d",
- __func__, start_address, length);
- usb_serial_debug_data(debug, &serial->serial->dev->dev,
- __func__, length, buffer);
+ dev_dbg(&serial->serial->dev->dev, "%s - start_address = %x, length = %d\n",
+ __func__, start_address, length);
+ usb_serial_debug_data(&serial->serial->dev->dev, __func__, length, buffer);
serial->TiReadI2C = 1;
@@ -395,11 +368,9 @@ static int write_boot_mem(struct edgeport_serial *serial,
/* Must do a read before write */
if (!serial->TiReadI2C) {
temp = kmalloc(1, GFP_KERNEL);
- if (!temp) {
- dev_err(&serial->serial->dev->dev,
- "%s - out of memory\n", __func__);
+ if (!temp)
return -ENOMEM;
- }
+
status = read_boot_mem(serial, 0, 1, temp);
kfree(temp);
if (status)
@@ -414,10 +385,8 @@ static int write_boot_mem(struct edgeport_serial *serial,
return status;
}
- dbg("%s - start_sddr = %x, length = %d",
- __func__, start_address, length);
- usb_serial_debug_data(debug, &serial->serial->dev->dev,
- __func__, length, buffer);
+ dev_dbg(&serial->serial->dev->dev, "%s - start_sddr = %x, length = %d\n", __func__, start_address, length);
+ usb_serial_debug_data(&serial->serial->dev->dev, __func__, length, buffer);
return status;
}
@@ -427,32 +396,37 @@ static int write_boot_mem(struct edgeport_serial *serial,
static int write_i2c_mem(struct edgeport_serial *serial,
int start_address, int length, __u8 address_type, __u8 *buffer)
{
+ struct device *dev = &serial->serial->dev->dev;
int status = 0;
int write_length;
- __be16 be_start_address;
+ u16 be_start_address;
/* We can only send a maximum of 1 aligned byte page at a time */
- /* calulate the number of bytes left in the first page */
+ /* calculate the number of bytes left in the first page */
write_length = EPROM_PAGE_SIZE -
(start_address & (EPROM_PAGE_SIZE - 1));
if (write_length > length)
write_length = length;
- dbg("%s - BytesInFirstPage Addr = %x, length = %d",
- __func__, start_address, write_length);
- usb_serial_debug_data(debug, &serial->serial->dev->dev,
- __func__, write_length, buffer);
+ dev_dbg(dev, "%s - BytesInFirstPage Addr = %x, length = %d\n",
+ __func__, start_address, write_length);
+ usb_serial_debug_data(dev, __func__, write_length, buffer);
- /* Write first page */
- be_start_address = cpu_to_be16(start_address);
+ /*
+ * Write first page.
+ *
+ * NOTE: Must use swab as wIndex is sent in little-endian byte order
+ * regardless of host byte order.
+ */
+ be_start_address = swab16((u16)start_address);
status = ti_vsend_sync(serial->serial->dev,
UMPC_MEMORY_WRITE, (__u16)address_type,
- (__force __u16)be_start_address,
+ be_start_address,
buffer, write_length);
if (status) {
- dbg("%s - ERROR %d", __func__, status);
+ dev_dbg(dev, "%s - ERROR %d\n", __func__, status);
return status;
}
@@ -468,20 +442,23 @@ static int write_i2c_mem(struct edgeport_serial *serial,
else
write_length = length;
- dbg("%s - Page Write Addr = %x, length = %d",
- __func__, start_address, write_length);
- usb_serial_debug_data(debug, &serial->serial->dev->dev,
- __func__, write_length, buffer);
+ dev_dbg(dev, "%s - Page Write Addr = %x, length = %d\n",
+ __func__, start_address, write_length);
+ usb_serial_debug_data(dev, __func__, write_length, buffer);
- /* Write next page */
- be_start_address = cpu_to_be16(start_address);
+ /*
+ * Write next page.
+ *
+ * NOTE: Must use swab as wIndex is sent in little-endian byte
+ * order regardless of host byte order.
+ */
+ be_start_address = swab16((u16)start_address);
status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE,
(__u16)address_type,
- (__force __u16)be_start_address,
+ be_start_address,
buffer, write_length);
if (status) {
- dev_err(&serial->serial->dev->dev, "%s - ERROR %d\n",
- __func__, status);
+ dev_err(dev, "%s - ERROR %d\n", __func__, status);
return status;
}
@@ -506,10 +483,8 @@ static int tx_active(struct edgeport_port *port)
int bytes_left = 0;
oedb = kmalloc(sizeof(*oedb), GFP_KERNEL);
- if (!oedb) {
- dev_err(&port->port->dev, "%s - out of memory\n", __func__);
+ if (!oedb)
return -ENOMEM;
- }
lsr = kmalloc(1, GFP_KERNEL); /* Sigh, that's right, just one byte,
as not all platforms can do DMA
@@ -524,7 +499,7 @@ static int tx_active(struct edgeport_port *port)
if (status)
goto exit_is_tx_active;
- dbg("%s - XByteCount 0x%X", __func__, oedb->XByteCount);
+ dev_dbg(&port->port->dev, "%s - XByteCount 0x%X\n", __func__, oedb->XByteCount);
/* and the LSR */
status = read_ram(port->port->serial->dev,
@@ -532,7 +507,7 @@ static int tx_active(struct edgeport_port *port)
if (status)
goto exit_is_tx_active;
- dbg("%s - LSR = 0x%X", __func__, *lsr);
+ dev_dbg(&port->port->dev, "%s - LSR = 0x%X\n", __func__, *lsr);
/* If either buffer has data or we are transmitting then return TRUE */
if ((oedb->XByteCount & 0x80) != 0)
@@ -543,68 +518,13 @@ static int tx_active(struct edgeport_port *port)
/* We return Not Active if we get any kind of error */
exit_is_tx_active:
- dbg("%s - return %d", __func__, bytes_left);
+ dev_dbg(&port->port->dev, "%s - return %d\n", __func__, bytes_left);
kfree(lsr);
kfree(oedb);
return bytes_left;
}
-static void chase_port(struct edgeport_port *port, unsigned long timeout,
- int flush)
-{
- int baud_rate;
- struct tty_struct *tty = tty_port_tty_get(&port->port->port);
- wait_queue_t wait;
- unsigned long flags;
-
- if (!timeout)
- timeout = (HZ * EDGE_CLOSING_WAIT)/100;
-
- /* wait for data to drain from the buffer */
- spin_lock_irqsave(&port->ep_lock, flags);
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&tty->write_wait, &wait);
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (kfifo_len(&port->write_fifo) == 0
- || timeout == 0 || signal_pending(current)
- || !usb_get_intfdata(port->port->serial->interface))
- /* disconnect */
- break;
- spin_unlock_irqrestore(&port->ep_lock, flags);
- timeout = schedule_timeout(timeout);
- spin_lock_irqsave(&port->ep_lock, flags);
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&tty->write_wait, &wait);
- if (flush)
- kfifo_reset_out(&port->write_fifo);
- spin_unlock_irqrestore(&port->ep_lock, flags);
- tty_kref_put(tty);
-
- /* wait for data to drain from the device */
- timeout += jiffies;
- while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
- && usb_get_intfdata(port->port->serial->interface)) {
- /* not disconnected */
- if (!tx_active(port))
- break;
- msleep(10);
- }
-
- /* disconnected */
- if (!usb_get_intfdata(port->port->serial->interface))
- return;
-
- /* wait one more character time, based on baud rate */
- /* (tx_active doesn't seem to wait for the last byte) */
- baud_rate = port->baud_rate;
- if (baud_rate == 0)
- baud_rate = 50;
- msleep(max(1, DIV_ROUND_UP(10000, baud_rate)));
-}
-
static int choose_config(struct usb_device *dev)
{
/*
@@ -614,14 +534,13 @@ static int choose_config(struct usb_device *dev)
* configuration # 1, which is Config Descriptor 0.
*/
- dbg("%s - Number of Interfaces = %d",
- __func__, dev->config->desc.bNumInterfaces);
- dbg("%s - MAX Power = %d",
- __func__, dev->config->desc.bMaxPower * 2);
+ dev_dbg(&dev->dev, "%s - Number of Interfaces = %d\n",
+ __func__, dev->config->desc.bNumInterfaces);
+ dev_dbg(&dev->dev, "%s - MAX Power = %d\n",
+ __func__, dev->config->desc.bMaxPower * 2);
if (dev->config->desc.bNumInterfaces != 1) {
- dev_err(&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n",
- __func__);
+ dev_err(&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __func__);
return -ENODEV;
}
@@ -681,8 +600,8 @@ static int get_descriptor_addr(struct edgeport_serial *serial,
if (rom_desc->Type == desc_type)
return start_address;
- start_address = start_address + sizeof(struct ti_i2c_desc)
- + rom_desc->Size;
+ start_address = start_address + sizeof(struct ti_i2c_desc) +
+ le16_to_cpu(rom_desc->Size);
} while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type);
@@ -695,11 +614,11 @@ static int valid_csum(struct ti_i2c_desc *rom_desc, __u8 *buffer)
__u16 i;
__u8 cs = 0;
- for (i = 0; i < rom_desc->Size; i++)
+ for (i = 0; i < le16_to_cpu(rom_desc->Size); i++)
cs = (__u8)(cs + buffer[i]);
if (cs != rom_desc->CheckSum) {
- dbg("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs);
+ pr_debug("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs);
return -EINVAL;
}
return 0;
@@ -716,14 +635,11 @@ static int check_i2c_image(struct edgeport_serial *serial)
__u16 ttype;
rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
- if (!rom_desc) {
- dev_err(dev, "%s - out of memory\n", __func__);
+ if (!rom_desc)
return -ENOMEM;
- }
+
buffer = kmalloc(TI_MAX_I2C_SIZE, GFP_KERNEL);
if (!buffer) {
- dev_err(dev, "%s - out of memory when allocating buffer\n",
- __func__);
kfree(rom_desc);
return -ENOMEM;
}
@@ -749,13 +665,13 @@ static int check_i2c_image(struct edgeport_serial *serial)
break;
if ((start_address + sizeof(struct ti_i2c_desc) +
- rom_desc->Size) > TI_MAX_I2C_SIZE) {
+ le16_to_cpu(rom_desc->Size)) > TI_MAX_I2C_SIZE) {
status = -ENODEV;
- dbg("%s - structure too big, erroring out.", __func__);
+ dev_dbg(dev, "%s - structure too big, erroring out.\n", __func__);
break;
}
- dbg("%s Type = 0x%x", __func__, rom_desc->Type);
+ dev_dbg(dev, "%s Type = 0x%x\n", __func__, rom_desc->Type);
/* Skip type 2 record */
ttype = rom_desc->Type & 0x0f;
@@ -764,7 +680,8 @@ static int check_i2c_image(struct edgeport_serial *serial)
/* Read the descriptor data */
status = read_rom(serial, start_address +
sizeof(struct ti_i2c_desc),
- rom_desc->Size, buffer);
+ le16_to_cpu(rom_desc->Size),
+ buffer);
if (status)
break;
@@ -773,7 +690,7 @@ static int check_i2c_image(struct edgeport_serial *serial)
break;
}
start_address = start_address + sizeof(struct ti_i2c_desc) +
- rom_desc->Size;
+ le16_to_cpu(rom_desc->Size);
} while ((rom_desc->Type != I2C_DESC_TYPE_ION) &&
(start_address < TI_MAX_I2C_SIZE));
@@ -794,37 +711,36 @@ static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer)
int start_address;
struct ti_i2c_desc *rom_desc;
struct edge_ti_manuf_descriptor *desc;
+ struct device *dev = &serial->serial->dev->dev;
rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
- if (!rom_desc) {
- dev_err(&serial->serial->dev->dev, "%s - out of memory\n",
- __func__);
+ if (!rom_desc)
return -ENOMEM;
- }
+
start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_ION,
rom_desc);
if (!start_address) {
- dbg("%s - Edge Descriptor not found in I2C", __func__);
+ dev_dbg(dev, "%s - Edge Descriptor not found in I2C\n", __func__);
status = -ENODEV;
goto exit;
}
/* Read the descriptor data */
status = read_rom(serial, start_address+sizeof(struct ti_i2c_desc),
- rom_desc->Size, buffer);
+ le16_to_cpu(rom_desc->Size), buffer);
if (status)
goto exit;
status = valid_csum(rom_desc, buffer);
desc = (struct edge_ti_manuf_descriptor *)buffer;
- dbg("%s - IonConfig 0x%x", __func__, desc->IonConfig);
- dbg("%s - Version %d", __func__, desc->Version);
- dbg("%s - Cpu/Board 0x%x", __func__, desc->CpuRev_BoardRev);
- dbg("%s - NumPorts %d", __func__, desc->NumPorts);
- dbg("%s - NumVirtualPorts %d", __func__, desc->NumVirtualPorts);
- dbg("%s - TotalPorts %d", __func__, desc->TotalPorts);
+ dev_dbg(dev, "%s - IonConfig 0x%x\n", __func__, desc->IonConfig);
+ dev_dbg(dev, "%s - Version %d\n", __func__, desc->Version);
+ dev_dbg(dev, "%s - Cpu/Board 0x%x\n", __func__, desc->CpuRev_BoardRev);
+ dev_dbg(dev, "%s - NumPorts %d\n", __func__, desc->NumPorts);
+ dev_dbg(dev, "%s - NumVirtualPorts %d\n", __func__, desc->NumVirtualPorts);
+ dev_dbg(dev, "%s - TotalPorts %d\n", __func__, desc->TotalPorts);
exit:
kfree(rom_desc);
@@ -860,18 +776,16 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev)
sizeof(struct ti_i2c_firmware_rec));
buffer = kmalloc(buffer_size, GFP_KERNEL);
- if (!buffer) {
- dev_err(dev, "%s - out of memory\n", __func__);
+ if (!buffer)
return -ENOMEM;
- }
// Set entire image of 0xffs
memset(buffer, 0xff, buffer_size);
err = request_firmware(&fw, fw_name, dev);
if (err) {
- printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
- fw_name, err);
+ dev_err(dev, "Failed to load image \"%s\" err %d\n",
+ fw_name, err);
kfree(buffer);
return err;
}
@@ -907,7 +821,7 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev)
firmware_rec = (struct ti_i2c_firmware_rec*)i2c_header->Data;
i2c_header->Type = I2C_DESC_TYPE_FIRMWARE_BLANK;
- i2c_header->Size = (__u16)buffer_size;
+ i2c_header->Size = cpu_to_le16(buffer_size);
i2c_header->CheckSum = cs;
firmware_rec->Ver_Major = OperationalMajorVersion;
firmware_rec->Ver_Minor = OperationalMinorVersion;
@@ -918,25 +832,23 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev)
/* Try to figure out what type of I2c we have */
static int i2c_type_bootmode(struct edgeport_serial *serial)
{
+ struct device *dev = &serial->serial->dev->dev;
int status;
u8 *data;
data = kmalloc(1, GFP_KERNEL);
- if (!data) {
- dev_err(&serial->serial->dev->dev,
- "%s - out of memory\n", __func__);
+ if (!data)
return -ENOMEM;
- }
/* Try to read type 2 */
status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ,
DTK_ADDR_SPACE_I2C_TYPE_II, 0, data, 0x01);
if (status)
- dbg("%s - read 2 status error = %d", __func__, status);
+ dev_dbg(dev, "%s - read 2 status error = %d\n", __func__, status);
else
- dbg("%s - read 2 data = 0x%x", __func__, *data);
+ dev_dbg(dev, "%s - read 2 data = 0x%x\n", __func__, *data);
if ((!status) && (*data == UMP5152 || *data == UMP3410)) {
- dbg("%s - ROM_TYPE_II", __func__);
+ dev_dbg(dev, "%s - ROM_TYPE_II\n", __func__);
serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
goto out;
}
@@ -945,16 +857,16 @@ static int i2c_type_bootmode(struct edgeport_serial *serial)
status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ,
DTK_ADDR_SPACE_I2C_TYPE_III, 0, data, 0x01);
if (status)
- dbg("%s - read 3 status error = %d", __func__, status);
+ dev_dbg(dev, "%s - read 3 status error = %d\n", __func__, status);
else
- dbg("%s - read 2 data = 0x%x", __func__, *data);
+ dev_dbg(dev, "%s - read 2 data = 0x%x\n", __func__, *data);
if ((!status) && (*data == UMP5152 || *data == UMP3410)) {
- dbg("%s - ROM_TYPE_III", __func__);
+ dev_dbg(dev, "%s - ROM_TYPE_III\n", __func__);
serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III;
goto out;
}
- dbg("%s - Unknown", __func__);
+ dev_dbg(dev, "%s - Unknown\n", __func__);
serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
status = -ENODEV;
out:
@@ -1065,11 +977,11 @@ static int download_fw(struct edgeport_serial *serial)
if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
struct ti_i2c_desc *rom_desc;
- dbg("%s - RUNNING IN DOWNLOAD MODE", __func__);
+ dev_dbg(dev, "%s - RUNNING IN DOWNLOAD MODE\n", __func__);
status = check_i2c_image(serial);
if (status) {
- dbg("%s - DOWNLOAD MODE -- BAD I2C", __func__);
+ dev_dbg(dev, "%s - DOWNLOAD MODE -- BAD I2C\n", __func__);
return status;
}
@@ -1077,10 +989,9 @@ static int download_fw(struct edgeport_serial *serial)
* Read Manufacturing Descriptor from TI Based Edgeport
*/
ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
- if (!ti_manuf_desc) {
- dev_err(dev, "%s - out of memory.\n", __func__);
+ if (!ti_manuf_desc)
return -ENOMEM;
- }
+
status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
if (status) {
kfree(ti_manuf_desc);
@@ -1089,7 +1000,7 @@ static int download_fw(struct edgeport_serial *serial)
/* Check version number of ION descriptor */
if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) {
- dbg("%s - Wrong CPU Rev %d (Must be 2)",
+ dev_dbg(dev, "%s - Wrong CPU Rev %d (Must be 2)\n",
__func__, ti_cpu_rev(ti_manuf_desc));
kfree(ti_manuf_desc);
return -EINVAL;
@@ -1097,7 +1008,6 @@ static int download_fw(struct edgeport_serial *serial)
rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
if (!rom_desc) {
- dev_err(dev, "%s - out of memory.\n", __func__);
kfree(ti_manuf_desc);
return -ENOMEM;
}
@@ -1109,13 +1019,11 @@ static int download_fw(struct edgeport_serial *serial)
struct ti_i2c_firmware_rec *firmware_version;
u8 *record;
- dbg("%s - Found Type FIRMWARE (Type 2) record",
- __func__);
+ dev_dbg(dev, "%s - Found Type FIRMWARE (Type 2) record\n", __func__);
firmware_version = kmalloc(sizeof(*firmware_version),
GFP_KERNEL);
if (!firmware_version) {
- dev_err(dev, "%s - out of memory.\n", __func__);
kfree(rom_desc);
kfree(ti_manuf_desc);
return -ENOMEM;
@@ -1142,27 +1050,24 @@ static int download_fw(struct edgeport_serial *serial)
download_new_ver = (OperationalMajorVersion << 8) +
(OperationalMinorVersion);
- dbg("%s - >> FW Versions Device %d.%d Driver %d.%d",
- __func__,
- firmware_version->Ver_Major,
- firmware_version->Ver_Minor,
- OperationalMajorVersion,
- OperationalMinorVersion);
+ dev_dbg(dev, "%s - >> FW Versions Device %d.%d Driver %d.%d\n",
+ __func__, firmware_version->Ver_Major,
+ firmware_version->Ver_Minor,
+ OperationalMajorVersion,
+ OperationalMinorVersion);
/* Check if we have an old version in the I2C and
update if necessary */
if (download_cur_ver < download_new_ver) {
- dbg("%s - Update I2C dld from %d.%d to %d.%d",
- __func__,
- firmware_version->Ver_Major,
- firmware_version->Ver_Minor,
- OperationalMajorVersion,
- OperationalMinorVersion);
+ dev_dbg(dev, "%s - Update I2C dld from %d.%d to %d.%d\n",
+ __func__,
+ firmware_version->Ver_Major,
+ firmware_version->Ver_Minor,
+ OperationalMajorVersion,
+ OperationalMinorVersion);
record = kmalloc(1, GFP_KERNEL);
if (!record) {
- dev_err(dev, "%s - out of memory.\n",
- __func__);
kfree(firmware_version);
kfree(rom_desc);
kfree(ti_manuf_desc);
@@ -1211,9 +1116,7 @@ static int download_fw(struct edgeport_serial *serial)
}
if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
- dev_err(dev,
- "%s - error resetting device\n",
- __func__);
+ dev_err(dev, "%s - error resetting device\n", __func__);
kfree(record);
kfree(firmware_version);
kfree(rom_desc);
@@ -1221,15 +1124,14 @@ static int download_fw(struct edgeport_serial *serial)
return -ENODEV;
}
- dbg("%s - HARDWARE RESET", __func__);
+ dev_dbg(dev, "%s - HARDWARE RESET\n", __func__);
/* Reset UMP -- Back to BOOT MODE */
status = ti_vsend_sync(serial->serial->dev,
UMPC_HARDWARE_RESET,
0, 0, NULL, 0);
- dbg("%s - HARDWARE RESET return %d",
- __func__, status);
+ dev_dbg(dev, "%s - HARDWARE RESET return %d\n", __func__, status);
/* return an error on purpose. */
kfree(record);
@@ -1249,7 +1151,6 @@ static int download_fw(struct edgeport_serial *serial)
header = kmalloc(HEADER_SIZE, GFP_KERNEL);
if (!header) {
- dev_err(dev, "%s - out of memory.\n", __func__);
kfree(rom_desc);
kfree(ti_manuf_desc);
return -ENOMEM;
@@ -1257,15 +1158,13 @@ static int download_fw(struct edgeport_serial *serial)
vheader = kmalloc(HEADER_SIZE, GFP_KERNEL);
if (!vheader) {
- dev_err(dev, "%s - out of memory.\n", __func__);
kfree(header);
kfree(rom_desc);
kfree(ti_manuf_desc);
return -ENOMEM;
}
- dbg("%s - Found Type BLANK FIRMWARE (Type F2) record",
- __func__);
+ dev_dbg(dev, "%s - Found Type BLANK FIRMWARE (Type F2) record\n", __func__);
/*
* In order to update the I2C firmware we must change
@@ -1307,7 +1206,7 @@ static int download_fw(struct edgeport_serial *serial)
HEADER_SIZE, vheader);
if (status) {
- dbg("%s - can't read header back", __func__);
+ dev_dbg(dev, "%s - can't read header back\n", __func__);
kfree(vheader);
kfree(header);
kfree(rom_desc);
@@ -1315,8 +1214,7 @@ static int download_fw(struct edgeport_serial *serial)
return status;
}
if (memcmp(vheader, header, HEADER_SIZE)) {
- dbg("%s - write download record failed",
- __func__);
+ dev_dbg(dev, "%s - write download record failed\n", __func__);
kfree(vheader);
kfree(header);
kfree(rom_desc);
@@ -1327,13 +1225,13 @@ static int download_fw(struct edgeport_serial *serial)
kfree(vheader);
kfree(header);
- dbg("%s - Start firmware update", __func__);
+ dev_dbg(dev, "%s - Start firmware update\n", __func__);
/* Tell firmware to copy download image into I2C */
status = ti_vsend_sync(serial->serial->dev,
UMPC_COPY_DNLD_TO_I2C, 0, 0, NULL, 0);
- dbg("%s - Update complete 0x%x", __func__, status);
+ dev_dbg(dev, "%s - Update complete 0x%x\n", __func__, status);
if (status) {
dev_err(dev,
"%s - UMPC_COPY_DNLD_TO_I2C failed\n",
@@ -1353,7 +1251,7 @@ static int download_fw(struct edgeport_serial *serial)
/********************************************************************/
/* Boot Mode */
/********************************************************************/
- dbg("%s - RUNNING IN BOOT MODE", __func__);
+ dev_dbg(dev, "%s - RUNNING IN BOOT MODE\n", __func__);
/* Configure the TI device so we can use the BULK pipes for download */
status = config_boot_dev(serial->serial->dev);
@@ -1362,8 +1260,8 @@ static int download_fw(struct edgeport_serial *serial)
if (le16_to_cpu(serial->serial->dev->descriptor.idVendor)
!= USB_VENDOR_ID_ION) {
- dbg("%s - VID = 0x%x", __func__,
- le16_to_cpu(serial->serial->dev->descriptor.idVendor));
+ dev_dbg(dev, "%s - VID = 0x%x\n", __func__,
+ le16_to_cpu(serial->serial->dev->descriptor.idVendor));
serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
goto stayinbootmode;
}
@@ -1388,10 +1286,9 @@ static int download_fw(struct edgeport_serial *serial)
* Read Manufacturing Descriptor from TI Based Edgeport
*/
ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
- if (!ti_manuf_desc) {
- dev_err(dev, "%s - out of memory.\n", __func__);
+ if (!ti_manuf_desc)
return -ENOMEM;
- }
+
status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
if (status) {
kfree(ti_manuf_desc);
@@ -1400,8 +1297,8 @@ static int download_fw(struct edgeport_serial *serial)
/* Check for version 2 */
if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) {
- dbg("%s - Wrong CPU Rev %d (Must be 2)",
- __func__, ti_cpu_rev(ti_manuf_desc));
+ dev_dbg(dev, "%s - Wrong CPU Rev %d (Must be 2)\n",
+ __func__, ti_cpu_rev(ti_manuf_desc));
kfree(ti_manuf_desc);
goto stayinbootmode;
}
@@ -1426,18 +1323,16 @@ static int download_fw(struct edgeport_serial *serial)
buffer_size = (((1024 * 16) - 512) +
sizeof(struct ti_i2c_image_header));
buffer = kmalloc(buffer_size, GFP_KERNEL);
- if (!buffer) {
- dev_err(dev, "%s - out of memory\n", __func__);
+ if (!buffer)
return -ENOMEM;
- }
/* Initialize the buffer to 0xff (pad the buffer) */
memset(buffer, 0xff, buffer_size);
err = request_firmware(&fw, fw_name, dev);
if (err) {
- printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
- fw_name, err);
+ dev_err(dev, "Failed to load image \"%s\" err %d\n",
+ fw_name, err);
kfree(buffer);
return err;
}
@@ -1457,23 +1352,20 @@ static int download_fw(struct edgeport_serial *serial)
header->CheckSum = cs;
/* Download the operational code */
- dbg("%s - Downloading operational code image (TI UMP)",
- __func__);
+ dev_dbg(dev, "%s - Downloading operational code image (TI UMP)\n", __func__);
status = download_code(serial, buffer, buffer_size);
kfree(buffer);
if (status) {
- dbg("%s - Error downloading operational code image",
- __func__);
+ dev_dbg(dev, "%s - Error downloading operational code image\n", __func__);
return status;
}
/* Device will reboot */
serial->product_info.TiMode = TI_MODE_TRANSITIONING;
- dbg("%s - Download successful -- Device rebooting...",
- __func__);
+ dev_dbg(dev, "%s - Download successful -- Device rebooting...\n", __func__);
/* return an error on purpose */
return -ENODEV;
@@ -1481,7 +1373,7 @@ static int download_fw(struct edgeport_serial *serial)
stayinbootmode:
/* Eprom is invalid or blank stay in boot mode */
- dbg("%s - STAYING IN BOOT MODE", __func__);
+ dev_dbg(dev, "%s - STAYING IN BOOT MODE\n", __func__);
serial->product_info.TiMode = TI_MODE_BOOT;
return 0;
@@ -1490,7 +1382,8 @@ stayinbootmode:
static int ti_do_config(struct edgeport_port *port, int feature, int on)
{
- int port_number = port->port->number - port->port->serial->minor;
+ int port_number = port->port->port_number;
+
on = !!on; /* 1 or 0 not bitmask */
return send_cmd(port->port->serial->dev,
feature, (__u8)(UMPM_UART1_PORT + port_number),
@@ -1502,7 +1395,7 @@ static int restore_mcr(struct edgeport_port *port, __u8 mcr)
{
int status = 0;
- dbg("%s - %x", __func__, mcr);
+ dev_dbg(&port->port->dev, "%s - %x\n", __func__, mcr);
status = ti_do_config(port, UMPC_SET_CLR_DTR, mcr & MCR_DTR);
if (status)
@@ -1539,11 +1432,11 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
struct async_icount *icount;
struct tty_struct *tty;
- dbg("%s - %02x", __func__, msr);
+ dev_dbg(&edge_port->port->dev, "%s - %02x\n", __func__, msr);
if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |
EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
- icount = &edge_port->icount;
+ icount = &edge_port->port->icount;
/* update input line counters */
if (msr & EDGEPORT_MSR_DELTA_CTS)
@@ -1554,7 +1447,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
icount->dcd++;
if (msr & EDGEPORT_MSR_DELTA_RI)
icount->rng++;
- wake_up_interruptible(&edge_port->delta_msr_wait);
+ wake_up_interruptible(&edge_port->port->port.delta_msr_wait);
}
/* Save the new modem status */
@@ -1579,9 +1472,8 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
struct async_icount *icount;
__u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR |
LSR_FRM_ERR | LSR_BREAK));
- struct tty_struct *tty;
- dbg("%s - %02x", __func__, new_lsr);
+ dev_dbg(&edge_port->port->dev, "%s - %02x\n", __func__, new_lsr);
edge_port->shadow_lsr = lsr;
@@ -1593,16 +1485,11 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
/* Place LSR data byte into Rx buffer */
- if (lsr_data) {
- tty = tty_port_tty_get(&edge_port->port->port);
- if (tty) {
- edge_tty_recv(&edge_port->port->dev, tty, &data, 1);
- tty_kref_put(tty);
- }
- }
+ if (lsr_data)
+ edge_tty_recv(edge_port->port, &data, 1);
/* update input line counters */
- icount = &edge_port->icount;
+ icount = &edge_port->port->icount;
if (new_lsr & LSR_BREAK)
icount->brk++;
if (new_lsr & LSR_OVER_ERR)
@@ -1619,6 +1506,7 @@ static void edge_interrupt_callback(struct urb *urb)
struct edgeport_serial *edge_serial = urb->context;
struct usb_serial_port *port;
struct edgeport_port *edge_port;
+ struct device *dev;
unsigned char *data = urb->transfer_buffer;
int length = urb->actual_length;
int port_number;
@@ -1628,8 +1516,6 @@ static void edge_interrupt_callback(struct urb *urb)
__u8 msr;
int status = urb->status;
- dbg("%s", __func__);
-
switch (status) {
case 0:
/* success */
@@ -1638,7 +1524,7 @@ static void edge_interrupt_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
+ dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n",
__func__, status);
return;
default:
@@ -1648,27 +1534,26 @@ static void edge_interrupt_callback(struct urb *urb)
}
if (!length) {
- dbg("%s - no data in urb", __func__);
+ dev_dbg(&urb->dev->dev, "%s - no data in urb\n", __func__);
goto exit;
}
- usb_serial_debug_data(debug, &edge_serial->serial->dev->dev,
- __func__, length, data);
+ dev = &edge_serial->serial->dev->dev;
+ usb_serial_debug_data(dev, __func__, length, data);
if (length != 2) {
- dbg("%s - expecting packet of size 2, got %d",
- __func__, length);
+ dev_dbg(dev, "%s - expecting packet of size 2, got %d\n", __func__, length);
goto exit;
}
port_number = TIUMP_GET_PORT_FROM_CODE(data[0]);
function = TIUMP_GET_FUNC_FROM_CODE(data[0]);
- dbg("%s - port_number %d, function %d, info 0x%x",
- __func__, port_number, function, data[1]);
+ dev_dbg(dev, "%s - port_number %d, function %d, info 0x%x\n", __func__,
+ port_number, function, data[1]);
port = edge_serial->serial->port[port_number];
edge_port = usb_get_serial_port_data(port);
if (!edge_port) {
- dbg("%s - edge_port not found", __func__);
+ dev_dbg(dev, "%s - edge_port not found\n", __func__);
return;
}
switch (function) {
@@ -1677,13 +1562,13 @@ static void edge_interrupt_callback(struct urb *urb)
if (lsr & UMP_UART_LSR_DATA_MASK) {
/* Save the LSR event for bulk read
completion routine */
- dbg("%s - LSR Event Port %u LSR Status = %02x",
- __func__, port_number, lsr);
+ dev_dbg(dev, "%s - LSR Event Port %u LSR Status = %02x\n",
+ __func__, port_number, lsr);
edge_port->lsr_event = 1;
edge_port->lsr_mask = lsr;
} else {
- dbg("%s - ===== Port %d LSR Status = %02x ======",
- __func__, port_number, lsr);
+ dev_dbg(dev, "%s - ===== Port %d LSR Status = %02x ======\n",
+ __func__, port_number, lsr);
handle_new_lsr(edge_port, 0, lsr, 0);
}
break;
@@ -1691,8 +1576,8 @@ static void edge_interrupt_callback(struct urb *urb)
case TIUMP_INTERRUPT_CODE_MSR: /* MSR */
/* Copy MSR from UMP */
msr = data[1];
- dbg("%s - ===== Port %u MSR Status = %02x ======",
- __func__, port_number, msr);
+ dev_dbg(dev, "%s - ===== Port %u MSR Status = %02x ======\n",
+ __func__, port_number, msr);
handle_new_msr(edge_port, msr);
break;
@@ -1715,14 +1600,12 @@ exit:
static void edge_bulk_in_callback(struct urb *urb)
{
struct edgeport_port *edge_port = urb->context;
+ struct device *dev = &edge_port->port->dev;
unsigned char *data = urb->transfer_buffer;
- struct tty_struct *tty;
int retval = 0;
int port_number;
int status = urb->status;
- dbg("%s", __func__);
-
switch (status) {
case 0:
/* success */
@@ -1731,13 +1614,10 @@ static void edge_bulk_in_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n", __func__, status);
return;
default:
- dev_err(&urb->dev->dev,
- "%s - nonzero read bulk status received: %d\n",
- __func__, status);
+ dev_err(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n", __func__, status);
}
if (status == -EPIPE)
@@ -1748,58 +1628,52 @@ static void edge_bulk_in_callback(struct urb *urb)
return;
}
- port_number = edge_port->port->number - edge_port->port->serial->minor;
+ port_number = edge_port->port->port_number;
if (edge_port->lsr_event) {
edge_port->lsr_event = 0;
- dbg("%s ===== Port %u LSR Status = %02x, Data = %02x ======",
- __func__, port_number, edge_port->lsr_mask, *data);
+ dev_dbg(dev, "%s ===== Port %u LSR Status = %02x, Data = %02x ======\n",
+ __func__, port_number, edge_port->lsr_mask, *data);
handle_new_lsr(edge_port, 1, edge_port->lsr_mask, *data);
/* Adjust buffer length/pointer */
--urb->actual_length;
++data;
}
- tty = tty_port_tty_get(&edge_port->port->port);
- if (tty && urb->actual_length) {
- usb_serial_debug_data(debug, &edge_port->port->dev,
- __func__, urb->actual_length, data);
+ if (urb->actual_length) {
+ usb_serial_debug_data(dev, __func__, urb->actual_length, data);
if (edge_port->close_pending)
- dbg("%s - close pending, dropping data on the floor",
+ dev_dbg(dev, "%s - close pending, dropping data on the floor\n",
__func__);
else
- edge_tty_recv(&edge_port->port->dev, tty, data,
- urb->actual_length);
- edge_port->icount.rx += urb->actual_length;
+ edge_tty_recv(edge_port->port, data,
+ urb->actual_length);
+ edge_port->port->icount.rx += urb->actual_length;
}
- tty_kref_put(tty);
exit:
/* continue read unless stopped */
spin_lock(&edge_port->ep_lock);
- if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING) {
- urb->dev = edge_port->port->serial->dev;
+ if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING)
retval = usb_submit_urb(urb, GFP_ATOMIC);
- } else if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPING) {
+ else if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPING)
edge_port->ep_read_urb_state = EDGE_READ_URB_STOPPED;
- }
+
spin_unlock(&edge_port->ep_lock);
if (retval)
- dev_err(&urb->dev->dev,
- "%s - usb_submit_urb failed with result %d\n",
- __func__, retval);
+ dev_err(dev, "%s - usb_submit_urb failed with result %d\n", __func__, retval);
}
-static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
- unsigned char *data, int length)
+static void edge_tty_recv(struct usb_serial_port *port, unsigned char *data,
+ int length)
{
int queued;
- queued = tty_insert_flip_string(tty, data, length);
+ queued = tty_insert_flip_string(&port->port, data, length);
if (queued < length)
- dev_err(dev, "%s - dropping data, %d bytes lost\n",
+ dev_err(&port->dev, "%s - dropping data, %d bytes lost\n",
__func__, length - queued);
- tty_flip_buffer_push(tty);
+ tty_flip_buffer_push(&port->port);
}
static void edge_bulk_out_callback(struct urb *urb)
@@ -1809,8 +1683,6 @@ static void edge_bulk_out_callback(struct urb *urb)
int status = urb->status;
struct tty_struct *tty;
- dbg("%s - port %d", __func__, port->number);
-
edge_port->ep_write_urb_in_use = 0;
switch (status) {
@@ -1821,17 +1693,17 @@ static void edge_bulk_out_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
+ dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n",
__func__, status);
return;
default:
- dev_err(&urb->dev->dev, "%s - nonzero write bulk status "
+ dev_err_console(port, "%s - nonzero write bulk status "
"received: %d\n", __func__, status);
}
/* send any buffered data */
tty = tty_port_tty_get(&port->port);
- edge_send(tty);
+ edge_send(port, tty);
tty_kref_put(tty);
}
@@ -1846,35 +1718,13 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
u16 open_settings;
u8 transaction_timeout;
- dbg("%s - port %d", __func__, port->number);
-
if (edge_port == NULL)
return -ENODEV;
- port_number = port->number - port->serial->minor;
- switch (port_number) {
- case 0:
- edge_port->uart_base = UMPMEM_BASE_UART1;
- edge_port->dma_address = UMPD_OEDB1_ADDRESS;
- break;
- case 1:
- edge_port->uart_base = UMPMEM_BASE_UART2;
- edge_port->dma_address = UMPD_OEDB2_ADDRESS;
- break;
- default:
- dev_err(&port->dev, "Unknown port number!!!\n");
- return -ENODEV;
- }
-
- dbg("%s - port_number = %d, uart_base = %04x, dma_address = %04x",
- __func__, port_number, edge_port->uart_base,
- edge_port->dma_address);
+ port_number = port->port_number;
dev = port->serial->dev;
- memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
- init_waitqueue_head(&edge_port->delta_msr_wait);
-
/* turn off loopback */
status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0);
if (status) {
@@ -1886,7 +1736,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
/* set up the port settings */
if (tty)
- edge_set_termios(tty, port, tty->termios);
+ edge_set_termios(tty, port, &tty->termios);
/* open up the port */
@@ -1901,7 +1751,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
UMP_PIPE_TRANS_TIMEOUT_ENA |
(transaction_timeout << 2));
- dbg("%s - Sending UMPC_OPEN_PORT", __func__);
+ dev_dbg(&port->dev, "%s - Sending UMPC_OPEN_PORT\n", __func__);
/* Tell TI to open and start the port */
status = send_cmd(dev, UMPC_OPEN_PORT,
@@ -1940,11 +1790,11 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
return status;
}
- dbg("ShadowMSR 0x%X", edge_port->shadow_msr);
+ dev_dbg(&port->dev, "ShadowMSR 0x%X\n", edge_port->shadow_msr);
/* Set Initial MCR */
edge_port->shadow_mcr = MCR_RTS | MCR_DTR;
- dbg("ShadowMCR 0x%X", edge_port->shadow_mcr);
+ dev_dbg(&port->dev, "ShadowMCR 0x%X\n", edge_port->shadow_mcr);
edge_serial = edge_port->edge_serial;
if (mutex_lock_interruptible(&edge_serial->es_lock))
@@ -1959,9 +1809,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
status = -EINVAL;
goto release_es_lock;
}
- urb->complete = edge_interrupt_callback;
urb->context = edge_serial;
- urb->dev = dev;
status = usb_submit_urb(urb, GFP_KERNEL);
if (status) {
dev_err(&port->dev,
@@ -1987,9 +1835,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
goto unlink_int_urb;
}
edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING;
- urb->complete = edge_bulk_in_callback;
urb->context = edge_port;
- urb->dev = dev;
status = usb_submit_urb(urb, GFP_KERNEL);
if (status) {
dev_err(&port->dev,
@@ -2000,8 +1846,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
++edge_serial->num_ports_open;
- dbg("%s - exited", __func__);
-
goto release_es_lock;
unlink_int_urb:
@@ -2016,10 +1860,9 @@ static void edge_close(struct usb_serial_port *port)
{
struct edgeport_serial *edge_serial;
struct edgeport_port *edge_port;
+ struct usb_serial *serial = port->serial;
+ unsigned long flags;
int port_number;
- int status;
-
- dbg("%s - port %d", __func__, port->number);
edge_serial = usb_get_serial_data(port->serial);
edge_port = usb_get_serial_port_data(port);
@@ -2030,23 +1873,18 @@ static void edge_close(struct usb_serial_port *port)
* this flag and dump add read data */
edge_port->close_pending = 1;
- /* chase the port close and flush */
- chase_port(edge_port, (HZ * closing_wait) / 100, 1);
-
usb_kill_urb(port->read_urb);
usb_kill_urb(port->write_urb);
edge_port->ep_write_urb_in_use = 0;
+ spin_lock_irqsave(&edge_port->ep_lock, flags);
+ kfifo_reset_out(&port->write_fifo);
+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+
+ dev_dbg(&port->dev, "%s - send umpc_close_port\n", __func__);
+ port_number = port->port_number;
+ send_cmd(serial->dev, UMPC_CLOSE_PORT,
+ (__u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0);
- /* assuming we can still talk to the device,
- * send a close port command to it */
- dbg("%s - send umpc_close_port", __func__);
- port_number = port->number - port->serial->minor;
- status = send_cmd(port->serial->dev,
- UMPC_CLOSE_PORT,
- (__u8)(UMPM_UART1_PORT + port_number),
- 0,
- NULL,
- 0);
mutex_lock(&edge_serial->es_lock);
--edge_port->edge_serial->num_ports_open;
if (edge_port->edge_serial->num_ports_open <= 0) {
@@ -2056,8 +1894,6 @@ static void edge_close(struct usb_serial_port *port)
}
mutex_unlock(&edge_serial->es_lock);
edge_port->close_pending = 0;
-
- dbg("%s - exited", __func__);
}
static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -2065,10 +1901,8 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
-
if (count == 0) {
- dbg("%s - write request of 0 bytes", __func__);
+ dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__);
return 0;
}
@@ -2077,23 +1911,19 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
if (edge_port->close_pending == 1)
return -ENODEV;
- count = kfifo_in_locked(&edge_port->write_fifo, data, count,
+ count = kfifo_in_locked(&port->write_fifo, data, count,
&edge_port->ep_lock);
- edge_send(tty);
+ edge_send(port, tty);
return count;
}
-static void edge_send(struct tty_struct *tty)
+static void edge_send(struct usb_serial_port *port, struct tty_struct *tty)
{
- struct usb_serial_port *port = tty->driver_data;
int count, result;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned long flags;
-
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&edge_port->ep_lock, flags);
if (edge_port->ep_write_urb_in_use) {
@@ -2101,7 +1931,7 @@ static void edge_send(struct tty_struct *tty)
return;
}
- count = kfifo_out(&edge_port->write_fifo,
+ count = kfifo_out(&port->write_fifo,
port->write_urb->transfer_buffer,
port->bulk_out_size);
@@ -2114,27 +1944,21 @@ static void edge_send(struct tty_struct *tty)
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
- usb_serial_debug_data(debug, &port->dev, __func__, count,
- port->write_urb->transfer_buffer);
+ usb_serial_debug_data(&port->dev, __func__, count, port->write_urb->transfer_buffer);
/* set up our urb */
- usb_fill_bulk_urb(port->write_urb, port->serial->dev,
- usb_sndbulkpipe(port->serial->dev,
- port->bulk_out_endpointAddress),
- port->write_urb->transfer_buffer, count,
- edge_bulk_out_callback,
- port);
+ port->write_urb->transfer_buffer_length = count;
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev,
+ dev_err_console(port,
"%s - failed submitting write urb, error %d\n",
__func__, result);
edge_port->ep_write_urb_in_use = 0;
/* TODO: reschedule edge_send */
} else
- edge_port->icount.tx += count;
+ edge_port->port->icount.tx += count;
/* wakeup any process waiting for writes to complete */
/* there is now more room in the buffer for new writes */
@@ -2149,18 +1973,16 @@ static int edge_write_room(struct tty_struct *tty)
int room = 0;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
if (edge_port == NULL)
return 0;
if (edge_port->close_pending == 1)
return 0;
spin_lock_irqsave(&edge_port->ep_lock, flags);
- room = kfifo_avail(&edge_port->write_fifo);
+ room = kfifo_avail(&port->write_fifo);
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
- dbg("%s - returns %d", __func__, room);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, room);
return room;
}
@@ -2170,30 +1992,35 @@ static int edge_chars_in_buffer(struct tty_struct *tty)
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
-
- dbg("%s - port %d", __func__, port->number);
-
if (edge_port == NULL)
return 0;
- if (edge_port->close_pending == 1)
- return 0;
spin_lock_irqsave(&edge_port->ep_lock, flags);
- chars = kfifo_len(&edge_port->write_fifo);
+ chars = kfifo_len(&port->write_fifo);
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
- dbg("%s - returns %d", __func__, chars);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
return chars;
}
+static bool edge_tx_empty(struct usb_serial_port *port)
+{
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ int ret;
+
+ ret = tx_active(edge_port);
+ if (ret > 0)
+ return false;
+
+ return true;
+}
+
static void edge_throttle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int status;
- dbg("%s - port %d", __func__, port->number);
-
if (edge_port == NULL)
return;
@@ -2219,8 +2046,6 @@ static void edge_unthrottle(struct tty_struct *tty)
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int status;
- dbg("%s - port %d", __func__, port->number);
-
if (edge_port == NULL)
return;
@@ -2267,9 +2092,6 @@ static int restart_read(struct edgeport_port *edge_port)
if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPED) {
urb = edge_port->port->read_urb;
- urb->complete = edge_bulk_in_callback;
- urb->context = edge_port;
- urb->dev = edge_port->port->serial->dev;
status = usb_submit_urb(urb, GFP_ATOMIC);
}
edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING;
@@ -2283,24 +2105,20 @@ static int restart_read(struct edgeport_port *edge_port)
static void change_port_settings(struct tty_struct *tty,
struct edgeport_port *edge_port, struct ktermios *old_termios)
{
+ struct device *dev = &edge_port->port->dev;
struct ump_uart_config *config;
int baud;
unsigned cflag;
int status;
- int port_number = edge_port->port->number -
- edge_port->port->serial->minor;
-
- dbg("%s - port %d", __func__, edge_port->port->number);
+ int port_number = edge_port->port->port_number;
config = kmalloc (sizeof (*config), GFP_KERNEL);
if (!config) {
- *tty->termios = *old_termios;
- dev_err(&edge_port->port->dev, "%s - out of memory\n",
- __func__);
+ tty->termios = *old_termios;
return;
}
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
config->wFlags = 0;
@@ -2312,20 +2130,20 @@ static void change_port_settings(struct tty_struct *tty,
switch (cflag & CSIZE) {
case CS5:
config->bDataBits = UMP_UART_CHAR5BITS;
- dbg("%s - data bits = 5", __func__);
+ dev_dbg(dev, "%s - data bits = 5\n", __func__);
break;
case CS6:
config->bDataBits = UMP_UART_CHAR6BITS;
- dbg("%s - data bits = 6", __func__);
+ dev_dbg(dev, "%s - data bits = 6\n", __func__);
break;
case CS7:
config->bDataBits = UMP_UART_CHAR7BITS;
- dbg("%s - data bits = 7", __func__);
+ dev_dbg(dev, "%s - data bits = 7\n", __func__);
break;
default:
case CS8:
config->bDataBits = UMP_UART_CHAR8BITS;
- dbg("%s - data bits = 8", __func__);
+ dev_dbg(dev, "%s - data bits = 8\n", __func__);
break;
}
@@ -2333,32 +2151,32 @@ static void change_port_settings(struct tty_struct *tty,
if (cflag & PARODD) {
config->wFlags |= UMP_MASK_UART_FLAGS_PARITY;
config->bParity = UMP_UART_ODDPARITY;
- dbg("%s - parity = odd", __func__);
+ dev_dbg(dev, "%s - parity = odd\n", __func__);
} else {
config->wFlags |= UMP_MASK_UART_FLAGS_PARITY;
config->bParity = UMP_UART_EVENPARITY;
- dbg("%s - parity = even", __func__);
+ dev_dbg(dev, "%s - parity = even\n", __func__);
}
} else {
config->bParity = UMP_UART_NOPARITY;
- dbg("%s - parity = none", __func__);
+ dev_dbg(dev, "%s - parity = none\n", __func__);
}
if (cflag & CSTOPB) {
config->bStopBits = UMP_UART_STOPBIT2;
- dbg("%s - stop bits = 2", __func__);
+ dev_dbg(dev, "%s - stop bits = 2\n", __func__);
} else {
config->bStopBits = UMP_UART_STOPBIT1;
- dbg("%s - stop bits = 1", __func__);
+ dev_dbg(dev, "%s - stop bits = 1\n", __func__);
}
/* figure out the flow control settings */
if (cflag & CRTSCTS) {
config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X_CTS_FLOW;
config->wFlags |= UMP_MASK_UART_FLAGS_RTS_FLOW;
- dbg("%s - RTS/CTS is enabled", __func__);
+ dev_dbg(dev, "%s - RTS/CTS is enabled\n", __func__);
} else {
- dbg("%s - RTS/CTS is disabled", __func__);
+ dev_dbg(dev, "%s - RTS/CTS is disabled\n", __func__);
tty->hw_stopped = 0;
restart_read(edge_port);
}
@@ -2371,20 +2189,20 @@ static void change_port_settings(struct tty_struct *tty,
/* if we are implementing INBOUND XON/XOFF */
if (I_IXOFF(tty)) {
config->wFlags |= UMP_MASK_UART_FLAGS_IN_X;
- dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
- __func__, config->cXon, config->cXoff);
+ dev_dbg(dev, "%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x\n",
+ __func__, config->cXon, config->cXoff);
} else
- dbg("%s - INBOUND XON/XOFF is disabled", __func__);
+ dev_dbg(dev, "%s - INBOUND XON/XOFF is disabled\n", __func__);
/* if we are implementing OUTBOUND XON/XOFF */
if (I_IXON(tty)) {
config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X;
- dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
- __func__, config->cXon, config->cXoff);
+ dev_dbg(dev, "%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x\n",
+ __func__, config->cXon, config->cXoff);
} else
- dbg("%s - OUTBOUND XON/XOFF is disabled", __func__);
+ dev_dbg(dev, "%s - OUTBOUND XON/XOFF is disabled\n", __func__);
- tty->termios->c_cflag &= ~CMSPAR;
+ tty->termios.c_cflag &= ~CMSPAR;
/* Round the baud rate */
baud = tty_get_baud_rate(tty);
@@ -2399,17 +2217,16 @@ static void change_port_settings(struct tty_struct *tty,
/* FIXME: Recompute actual baud from divisor here */
- dbg("%s - baud rate = %d, wBaudRate = %d", __func__, baud,
- config->wBaudRate);
+ dev_dbg(dev, "%s - baud rate = %d, wBaudRate = %d\n", __func__, baud, config->wBaudRate);
- dbg("wBaudRate: %d", (int)(461550L / config->wBaudRate));
- dbg("wFlags: 0x%x", config->wFlags);
- dbg("bDataBits: %d", config->bDataBits);
- dbg("bParity: %d", config->bParity);
- dbg("bStopBits: %d", config->bStopBits);
- dbg("cXon: %d", config->cXon);
- dbg("cXoff: %d", config->cXoff);
- dbg("bUartMode: %d", config->bUartMode);
+ dev_dbg(dev, "wBaudRate: %d\n", (int)(461550L / config->wBaudRate));
+ dev_dbg(dev, "wFlags: 0x%x\n", config->wFlags);
+ dev_dbg(dev, "bDataBits: %d\n", config->bDataBits);
+ dev_dbg(dev, "bParity: %d\n", config->bParity);
+ dev_dbg(dev, "bStopBits: %d\n", config->bStopBits);
+ dev_dbg(dev, "cXon: %d\n", config->cXon);
+ dev_dbg(dev, "cXoff: %d\n", config->cXoff);
+ dev_dbg(dev, "bUartMode: %d\n", config->bUartMode);
/* move the word values into big endian mode */
cpu_to_be16s(&config->wFlags);
@@ -2419,8 +2236,8 @@ static void change_port_settings(struct tty_struct *tty,
(__u8)(UMPM_UART1_PORT + port_number),
0, (__u8 *)config, sizeof(*config));
if (status)
- dbg("%s - error %d when trying to write config to device",
- __func__, status);
+ dev_dbg(dev, "%s - error %d when trying to write config to device\n",
+ __func__, status);
kfree(config);
}
@@ -2430,13 +2247,12 @@ static void edge_set_termios(struct tty_struct *tty,
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int cflag;
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
- dbg("%s - clfag %08x iflag %08x", __func__,
- tty->termios->c_cflag, tty->termios->c_iflag);
- dbg("%s - old clfag %08x old iflag %08x", __func__,
- old_termios->c_cflag, old_termios->c_iflag);
- dbg("%s - port %d", __func__, port->number);
+ dev_dbg(&port->dev, "%s - clfag %08x iflag %08x\n", __func__,
+ tty->termios.c_cflag, tty->termios.c_iflag);
+ dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__,
+ old_termios->c_cflag, old_termios->c_iflag);
if (edge_port == NULL)
return;
@@ -2444,7 +2260,7 @@ static void edge_set_termios(struct tty_struct *tty,
change_port_settings(tty, edge_port, old_termios);
}
-static int edge_tiocmset(struct tty_struct *tty, struct file *file,
+static int edge_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
@@ -2452,8 +2268,6 @@ static int edge_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int mcr;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&edge_port->ep_lock, flags);
mcr = edge_port->shadow_mcr;
if (set & TIOCM_RTS)
@@ -2477,7 +2291,7 @@ static int edge_tiocmset(struct tty_struct *tty, struct file *file,
return 0;
}
-static int edge_tiocmget(struct tty_struct *tty, struct file *file)
+static int edge_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
@@ -2486,8 +2300,6 @@ static int edge_tiocmget(struct tty_struct *tty, struct file *file)
unsigned int mcr;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&edge_port->ep_lock, flags);
msr = edge_port->shadow_msr;
@@ -2500,95 +2312,53 @@ static int edge_tiocmget(struct tty_struct *tty, struct file *file)
| ((msr & EDGEPORT_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */
- dbg("%s -- %x", __func__, result);
+ dev_dbg(&port->dev, "%s -- %x\n", __func__, result);
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
return result;
}
-static int edge_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct async_icount *ic = &edge_port->icount;
-
- icount->cts = ic->cts;
- icount->dsr = ic->dsr;
- icount->rng = ic->rng;
- icount->dcd = ic->dcd;
- icount->tx = ic->tx;
- icount->rx = ic->rx;
- icount->frame = ic->frame;
- icount->parity = ic->parity;
- icount->overrun = ic->overrun;
- icount->brk = ic->brk;
- icount->buf_overrun = ic->buf_overrun;
- return 0;
-}
-
static int get_serial_info(struct edgeport_port *edge_port,
struct serial_struct __user *retinfo)
{
struct serial_struct tmp;
+ unsigned cwait;
if (!retinfo)
return -EFAULT;
+ cwait = edge_port->port->port.closing_wait;
+ if (cwait != ASYNC_CLOSING_WAIT_NONE)
+ cwait = jiffies_to_msecs(cwait) / 10;
+
memset(&tmp, 0, sizeof(tmp));
tmp.type = PORT_16550A;
- tmp.line = edge_port->port->serial->minor;
- tmp.port = edge_port->port->number;
+ tmp.line = edge_port->port->minor;
+ tmp.port = edge_port->port->port_number;
tmp.irq = 0;
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
tmp.xmit_fifo_size = edge_port->port->bulk_out_size;
tmp.baud_base = 9600;
tmp.close_delay = 5*HZ;
- tmp.closing_wait = closing_wait;
+ tmp.closing_wait = cwait;
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;
return 0;
}
-static int edge_ioctl(struct tty_struct *tty, struct file *file,
+static int edge_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct async_icount cnow;
- struct async_icount cprev;
-
- dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
switch (cmd) {
case TIOCGSERIAL:
- dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
+ dev_dbg(&port->dev, "%s - TIOCGSERIAL\n", __func__);
return get_serial_info(edge_port,
(struct serial_struct __user *) arg);
- case TIOCMIWAIT:
- dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
- cprev = edge_port->icount;
- while (1) {
- interruptible_sleep_on(&edge_port->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = edge_port->icount;
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
- return 0;
- }
- cprev = cnow;
- }
- /* not reached */
- break;
}
return -ENOIOCTLCMD;
}
@@ -2600,35 +2370,24 @@ static void edge_break(struct tty_struct *tty, int break_state)
int status;
int bv = 0; /* Off */
- dbg("%s - state = %d", __func__, break_state);
-
- /* chase the port close */
- chase_port(edge_port, 0, 0);
-
if (break_state == -1)
bv = 1; /* On */
status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv);
if (status)
- dbg("%s - error %d sending break set/clear command.",
- __func__, status);
+ dev_dbg(&port->dev, "%s - error %d sending break set/clear command.\n",
+ __func__, status);
}
static int edge_startup(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial;
- struct edgeport_port *edge_port;
- struct usb_device *dev;
int status;
- int i;
-
- dev = serial->dev;
/* create our private serial structure */
edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
- if (edge_serial == NULL) {
- dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ if (!edge_serial)
return -ENOMEM;
- }
+
mutex_init(&edge_serial->es_lock);
edge_serial->serial = serial;
usb_set_serial_data(serial, edge_serial);
@@ -2639,74 +2398,82 @@ static int edge_startup(struct usb_serial *serial)
return status;
}
- /* set up our port private structures */
- for (i = 0; i < serial->num_ports; ++i) {
- edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
- if (edge_port == NULL) {
- dev_err(&serial->dev->dev, "%s - Out of memory\n",
- __func__);
- goto cleanup;
- }
- spin_lock_init(&edge_port->ep_lock);
- if (kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE,
- GFP_KERNEL)) {
- dev_err(&serial->dev->dev, "%s - Out of memory\n",
- __func__);
- kfree(edge_port);
- goto cleanup;
- }
- edge_port->port = serial->port[i];
- edge_port->edge_serial = edge_serial;
- usb_set_serial_port_data(serial->port[i], edge_port);
- edge_port->bUartMode = default_uart_mode;
- }
-
return 0;
-
-cleanup:
- for (--i; i >= 0; --i) {
- edge_port = usb_get_serial_port_data(serial->port[i]);
- kfifo_free(&edge_port->write_fifo);
- kfree(edge_port);
- usb_set_serial_port_data(serial->port[i], NULL);
- }
- kfree(edge_serial);
- usb_set_serial_data(serial, NULL);
- return -ENOMEM;
}
static void edge_disconnect(struct usb_serial *serial)
{
- int i;
+}
+
+static void edge_release(struct usb_serial *serial)
+{
+ kfree(usb_get_serial_data(serial));
+}
+
+static int edge_port_probe(struct usb_serial_port *port)
+{
struct edgeport_port *edge_port;
+ int ret;
+
+ edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL);
+ if (!edge_port)
+ return -ENOMEM;
- dbg("%s", __func__);
+ spin_lock_init(&edge_port->ep_lock);
+ edge_port->port = port;
+ edge_port->edge_serial = usb_get_serial_data(port->serial);
+ edge_port->bUartMode = default_uart_mode;
- for (i = 0; i < serial->num_ports; ++i) {
- edge_port = usb_get_serial_port_data(serial->port[i]);
- edge_remove_sysfs_attrs(edge_port->port);
+ switch (port->port_number) {
+ case 0:
+ edge_port->uart_base = UMPMEM_BASE_UART1;
+ edge_port->dma_address = UMPD_OEDB1_ADDRESS;
+ break;
+ case 1:
+ edge_port->uart_base = UMPMEM_BASE_UART2;
+ edge_port->dma_address = UMPD_OEDB2_ADDRESS;
+ break;
+ default:
+ dev_err(&port->dev, "unknown port number\n");
+ ret = -ENODEV;
+ goto err;
}
+
+ dev_dbg(&port->dev,
+ "%s - port_number = %d, uart_base = %04x, dma_address = %04x\n",
+ __func__, port->port_number, edge_port->uart_base,
+ edge_port->dma_address);
+
+ usb_set_serial_port_data(port, edge_port);
+
+ ret = edge_create_sysfs_attrs(port);
+ if (ret)
+ goto err;
+
+ port->port.closing_wait = msecs_to_jiffies(closing_wait * 10);
+ port->port.drain_delay = 1;
+
+ return 0;
+err:
+ kfree(edge_port);
+
+ return ret;
}
-static void edge_release(struct usb_serial *serial)
+static int edge_port_remove(struct usb_serial_port *port)
{
- int i;
struct edgeport_port *edge_port;
- dbg("%s", __func__);
+ edge_port = usb_get_serial_port_data(port);
+ edge_remove_sysfs_attrs(port);
+ kfree(edge_port);
- for (i = 0; i < serial->num_ports; ++i) {
- edge_port = usb_get_serial_port_data(serial->port[i]);
- kfifo_free(&edge_port->write_fifo);
- kfree(edge_port);
- }
- kfree(usb_get_serial_data(serial));
+ return 0;
}
-
/* Sysfs Attributes */
-static ssize_t show_uart_mode(struct device *dev,
+static ssize_t uart_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
@@ -2715,14 +2482,14 @@ static ssize_t show_uart_mode(struct device *dev,
return sprintf(buf, "%d\n", edge_port->bUartMode);
}
-static ssize_t store_uart_mode(struct device *dev,
+static ssize_t uart_mode_store(struct device *dev,
struct device_attribute *attr, const char *valbuf, size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int v = simple_strtoul(valbuf, NULL, 0);
- dbg("%s: setting uart_mode = %d", __func__, v);
+ dev_dbg(dev, "%s: setting uart_mode = %d\n", __func__, v);
if (v < 256)
edge_port->bUartMode = v;
@@ -2731,9 +2498,7 @@ static ssize_t store_uart_mode(struct device *dev,
return count;
}
-
-static DEVICE_ATTR(uart_mode, S_IWUSR | S_IRUGO, show_uart_mode,
- store_uart_mode);
+static DEVICE_ATTR_RW(uart_mode);
static int edge_create_sysfs_attrs(struct usb_serial_port *port)
{
@@ -2753,7 +2518,6 @@ static struct usb_serial_driver edgeport_1port_device = {
.name = "edgeport_ti_1",
},
.description = "Edgeport TI 1 port adapter",
- .usb_driver = &io_driver,
.id_table = edgeport_1port_id_table,
.num_ports = 1,
.open = edge_open,
@@ -2763,15 +2527,18 @@ static struct usb_serial_driver edgeport_1port_device = {
.attach = edge_startup,
.disconnect = edge_disconnect,
.release = edge_release,
- .port_probe = edge_create_sysfs_attrs,
+ .port_probe = edge_port_probe,
+ .port_remove = edge_port_remove,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
- .get_icount = edge_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
+ .tx_empty = edge_tx_empty,
.break_ctl = edge_break,
.read_int_callback = edge_interrupt_callback,
.read_bulk_callback = edge_bulk_in_callback,
@@ -2784,7 +2551,6 @@ static struct usb_serial_driver edgeport_2port_device = {
.name = "edgeport_ti_2",
},
.description = "Edgeport TI 2 port adapter",
- .usb_driver = &io_driver,
.id_table = edgeport_2port_id_table,
.num_ports = 2,
.open = edge_open,
@@ -2794,63 +2560,35 @@ static struct usb_serial_driver edgeport_2port_device = {
.attach = edge_startup,
.disconnect = edge_disconnect,
.release = edge_release,
- .port_probe = edge_create_sysfs_attrs,
+ .port_probe = edge_port_probe,
+ .port_remove = edge_port_remove,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
+ .tx_empty = edge_tx_empty,
.break_ctl = edge_break,
.read_int_callback = edge_interrupt_callback,
.read_bulk_callback = edge_bulk_in_callback,
.write_bulk_callback = edge_bulk_out_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &edgeport_1port_device, &edgeport_2port_device, NULL
+};
-static int __init edgeport_init(void)
-{
- int retval;
- retval = usb_serial_register(&edgeport_1port_device);
- if (retval)
- goto failed_1port_device_register;
- retval = usb_serial_register(&edgeport_2port_device);
- if (retval)
- goto failed_2port_device_register;
- retval = usb_register(&io_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&edgeport_2port_device);
-failed_2port_device_register:
- usb_serial_deregister(&edgeport_1port_device);
-failed_1port_device_register:
- return retval;
-}
-
-static void __exit edgeport_exit(void)
-{
- usb_deregister(&io_driver);
- usb_serial_deregister(&edgeport_1port_device);
- usb_serial_deregister(&edgeport_2port_device);
-}
-
-module_init(edgeport_init);
-module_exit(edgeport_exit);
+module_usb_serial_driver(serial_drivers, id_table_combined);
-/* Module information */
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("edgeport/down3.bin");
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
module_param(closing_wait, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs");
diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h
index 51f83fbb73b..6f6a856bc37 100644
--- a/drivers/usb/serial/io_usbvend.h
+++ b/drivers/usb/serial/io_usbvend.h
@@ -594,7 +594,7 @@ struct edge_boot_descriptor {
struct ti_i2c_desc {
__u8 Type; // Type of descriptor
- __u16 Size; // Size of data only not including header
+ __le16 Size; // Size of data only not including header
__u8 CheckSum; // Checksum (8 bit sum of data only)
__u8 Data[0]; // Data starts here
} __attribute__((packed));
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 4735931b4c7..f51a5d52c0e 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -8,45 +8,10 @@
* 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.
- *
- * (12/12/2002) ganesh
- * Added support for practically all devices supported by ActiveSync
- * on Windows. Thanks to Wes Cilldhaire <billybobjoehenrybob@hotmail.com>.
- *
- * (26/11/2002) ganesh
- * Added insmod options to specify product and vendor id.
- * Use modprobe ipaq vendor=0xfoo product=0xbar
- *
- * (26/7/2002) ganesh
- * Fixed up broken error handling in ipaq_open. Retry the "kickstart"
- * packet much harder - this drastically reduces connection failures.
- *
- * (30/4/2002) ganesh
- * Added support for the Casio EM500. Completely untested. Thanks
- * to info from Nathan <wfilardo@fuse.net>
- *
- * (19/3/2002) ganesh
- * Don't submit urbs while holding spinlocks. Not strictly necessary
- * in 2.5.x.
- *
- * (8/3/2002) ganesh
- * The ipaq sometimes emits a '\0' before the CLIENT string. At this
- * point of time, the ppp ldisc is not yet attached to the tty, so
- * n_tty echoes "^ " to the ipaq, which messes up the chat. In 2.5.6-pre2
- * this causes a panic because echo_char() tries to sleep in interrupt
- * context.
- * The fix is to tell the upper layers that this is a raw device so that
- * echoing is suppressed. Thanks to Lyle Lindholm for a detailed bug
- * report.
- *
- * (25/2/2002) ganesh
- * Added support for the HP Jornada 548 and 568. Completely untested.
- * Thanks to info from Heath Robinson and Arieh Davidoff.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -59,16 +24,9 @@
#define KP_RETRIES 100
-/*
- * Version Information
- */
-
-#define DRIVER_VERSION "v1.0"
#define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>"
#define DRIVER_DESC "USB PocketPC PDA driver"
-static __u16 product, vendor;
-static int debug;
static int connect_retries = KP_RETRIES;
static int initial_wait;
@@ -78,9 +36,7 @@ static int ipaq_open(struct tty_struct *tty,
static int ipaq_calc_num_ports(struct usb_serial *serial);
static int ipaq_startup(struct usb_serial *serial);
-static struct usb_device_id ipaq_id_table [] = {
- /* The first entry is a placeholder for the insmod-specified device */
- { USB_DEVICE(0x049F, 0x0003) },
+static const struct usb_device_id ipaq_id_table[] = {
{ USB_DEVICE(0x0104, 0x00BE) }, /* Socket USB Sync */
{ USB_DEVICE(0x03F0, 0x1016) }, /* HP USB Sync */
{ USB_DEVICE(0x03F0, 0x1116) }, /* HP USB Sync 1611 */
@@ -539,14 +495,6 @@ static struct usb_device_id ipaq_id_table [] = {
MODULE_DEVICE_TABLE(usb, ipaq_id_table);
-static struct usb_driver ipaq_driver = {
- .name = "ipaq",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = ipaq_id_table,
- .no_dynamic_id = 1,
-};
-
/* All of the device info needed for the Compaq iPAQ */
static struct usb_serial_driver ipaq_device = {
@@ -555,7 +503,6 @@ static struct usb_serial_driver ipaq_device = {
.name = "ipaq",
},
.description = "PocketPC PDA",
- .usb_driver = &ipaq_driver,
.id_table = ipaq_id_table,
.bulk_in_size = 256,
.bulk_out_size = 256,
@@ -564,6 +511,10 @@ static struct usb_serial_driver ipaq_device = {
.calc_num_ports = ipaq_calc_num_ports,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ipaq_device, NULL
+};
+
static int ipaq_open(struct tty_struct *tty,
struct usb_serial_port *port)
{
@@ -571,8 +522,6 @@ static int ipaq_open(struct tty_struct *tty,
int result = 0;
int retries = connect_retries;
- dbg("%s - port %d", __func__, port->number);
-
msleep(1000*initial_wait);
/*
@@ -609,7 +558,7 @@ static int ipaq_calc_num_ports(struct usb_serial *serial)
*/
int ipaq_num_ports = 1;
- dbg("%s - numberofendpoints: %d", __FUNCTION__,
+ dev_dbg(&serial->dev->dev, "%s - numberofendpoints: %d\n", __func__,
(int)serial->interface->cur_altsetting->desc.bNumEndpoints);
/*
@@ -628,8 +577,6 @@ static int ipaq_calc_num_ports(struct usb_serial *serial)
static int ipaq_startup(struct usb_serial *serial)
{
- dbg("%s", __func__);
-
/* Some of the devices in ipaq_id_table[] are composite, and we
* shouldn't bind to all the interfaces. This test will rule out
* some obviously invalid possibilities.
@@ -649,58 +596,19 @@ static int ipaq_startup(struct usb_serial *serial)
return -ENODEV;
}
- dbg("%s - iPAQ module configured for %d ports",
- __FUNCTION__, serial->num_ports);
+ dev_dbg(&serial->dev->dev,
+ "%s - iPAQ module configured for %d ports\n", __func__,
+ serial->num_ports);
return usb_reset_configuration(serial->dev);
}
-static int __init ipaq_init(void)
-{
- int retval;
- retval = usb_serial_register(&ipaq_device);
- if (retval)
- goto failed_usb_serial_register;
- if (vendor) {
- ipaq_id_table[0].idVendor = vendor;
- ipaq_id_table[0].idProduct = product;
- }
- retval = usb_register(&ipaq_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&ipaq_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit ipaq_exit(void)
-{
- usb_deregister(&ipaq_driver);
- usb_serial_deregister(&ipaq_device);
-}
-
-
-module_init(ipaq_init);
-module_exit(ipaq_exit);
+module_usb_serial_driver(serial_drivers, ipaq_id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
-module_param(vendor, ushort, 0);
-MODULE_PARM_DESC(vendor, "User specified USB idVendor");
-
-module_param(product, ushort, 0);
-MODULE_PARM_DESC(product, "User specified USB idProduct");
-
module_param(connect_retries, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(connect_retries,
"Maximum number of connect retries (one second each)");
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index ca77e88836b..8b1cf18a668 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -38,7 +38,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
@@ -47,11 +46,8 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include <linux/uaccess.h>
+#include "usb-wwan.h"
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.4"
#define DRIVER_AUTHOR "Roelf Diedericks"
#define DRIVER_DESC "IPWireless tty driver"
@@ -131,32 +127,20 @@ enum {
#define IPW_WANTS_TO_SEND 0x30
-static const struct usb_device_id usb_ipw_ids[] = {
+static const struct usb_device_id id_table[] = {
{ USB_DEVICE(IPW_VID, IPW_PID) },
{ },
};
-
-MODULE_DEVICE_TABLE(usb, usb_ipw_ids);
-
-static struct usb_driver usb_ipw_driver = {
- .name = "ipwtty",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = usb_ipw_ids,
- .no_dynamic_id = 1,
-};
-
-static int debug;
+MODULE_DEVICE_TABLE(usb, id_table);
static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
{
- struct usb_device *dev = port->serial->dev;
+ struct usb_device *udev = port->serial->dev;
+ struct device *dev = &port->dev;
u8 buf_flow_static[16] = IPW_BYTES_FLOWINIT;
u8 *buf_flow_init;
int result;
- dbg("%s", __func__);
-
buf_flow_init = kmemdup(buf_flow_static, 16, GFP_KERNEL);
if (!buf_flow_init)
return -ENOMEM;
@@ -164,8 +148,8 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
/* --1: Tell the modem to initialize (we think) From sniffs this is
* always the first thing that gets sent to the modem during
* opening of the device */
- dbg("%s: Sending SIO_INIT (we guess)", __func__);
- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ dev_dbg(dev, "%s: Sending SIO_INIT (we guess)\n", __func__);
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
IPW_SIO_INIT,
USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
0,
@@ -174,22 +158,19 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
0,
100000);
if (result < 0)
- dev_err(&port->dev,
- "Init of modem failed (error = %d)\n", result);
+ dev_err(dev, "Init of modem failed (error = %d)\n", result);
/* reset the bulk pipes */
- usb_clear_halt(dev,
- usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress));
- usb_clear_halt(dev,
- usb_sndbulkpipe(dev, port->bulk_out_endpointAddress));
+ usb_clear_halt(udev, usb_rcvbulkpipe(udev, port->bulk_in_endpointAddress));
+ usb_clear_halt(udev, usb_sndbulkpipe(udev, port->bulk_out_endpointAddress));
/*--2: Start reading from the device */
- dbg("%s: setting up bulk read callback", __func__);
- usb_serial_generic_open(tty, port);
+ dev_dbg(dev, "%s: setting up bulk read callback\n", __func__);
+ usb_wwan_open(tty, port);
/*--3: Tell the modem to open the floodgates on the rx bulk channel */
- dbg("%s:asking modem for RxRead (RXBULK_ON)", __func__);
- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ dev_dbg(dev, "%s:asking modem for RxRead (RXBULK_ON)\n", __func__);
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
IPW_SIO_RXCTL,
USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
IPW_RXBULK_ON,
@@ -198,12 +179,11 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
0,
100000);
if (result < 0)
- dev_err(&port->dev,
- "Enabling bulk RxRead failed (error = %d)\n", result);
+ dev_err(dev, "Enabling bulk RxRead failed (error = %d)\n", result);
/*--4: setup the initial flowcontrol */
- dbg("%s:setting init flowcontrol (%s)", __func__, buf_flow_init);
- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ dev_dbg(dev, "%s:setting init flowcontrol (%s)\n", __func__, buf_flow_init);
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
IPW_SIO_HANDFLOW,
USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
0,
@@ -212,21 +192,42 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
0x10,
200000);
if (result < 0)
- dev_err(&port->dev,
- "initial flowcontrol failed (error = %d)\n", result);
+ dev_err(dev, "initial flowcontrol failed (error = %d)\n", result);
kfree(buf_flow_init);
return 0;
}
+static int ipw_attach(struct usb_serial *serial)
+{
+ struct usb_wwan_intf_private *data;
+
+ data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ spin_lock_init(&data->susp_lock);
+ usb_set_serial_data(serial, data);
+ return 0;
+}
+
+static void ipw_release(struct usb_serial *serial)
+{
+ struct usb_wwan_intf_private *data = usb_get_serial_data(serial);
+
+ usb_set_serial_data(serial, NULL);
+ kfree(data);
+}
+
static void ipw_dtr_rts(struct usb_serial_port *port, int on)
{
- struct usb_device *dev = port->serial->dev;
+ struct usb_device *udev = port->serial->dev;
+ struct device *dev = &port->dev;
int result;
- dbg("%s: on = %d", __func__, on);
+ dev_dbg(dev, "%s: on = %d\n", __func__, on);
- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
IPW_SIO_SET_PIN,
USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
on ? IPW_PIN_SETDTR : IPW_PIN_CLRDTR,
@@ -235,10 +236,9 @@ static void ipw_dtr_rts(struct usb_serial_port *port, int on)
0,
200000);
if (result < 0)
- dev_err(&port->dev, "setting dtr failed (error = %d)\n",
- result);
+ dev_err(dev, "setting dtr failed (error = %d)\n", result);
- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
IPW_SIO_SET_PIN, USB_TYPE_VENDOR |
USB_RECIP_INTERFACE | USB_DIR_OUT,
on ? IPW_PIN_SETRTS : IPW_PIN_CLRRTS,
@@ -247,18 +247,18 @@ static void ipw_dtr_rts(struct usb_serial_port *port, int on)
0,
200000);
if (result < 0)
- dev_err(&port->dev, "setting rts failed (error = %d)\n",
- result);
+ dev_err(dev, "setting rts failed (error = %d)\n", result);
}
static void ipw_close(struct usb_serial_port *port)
{
- struct usb_device *dev = port->serial->dev;
+ struct usb_device *udev = port->serial->dev;
+ struct device *dev = &port->dev;
int result;
/*--3: purge */
- dbg("%s:sending purge", __func__);
- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ dev_dbg(dev, "%s:sending purge\n", __func__);
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
IPW_SIO_PURGE, USB_TYPE_VENDOR |
USB_RECIP_INTERFACE | USB_DIR_OUT,
0x03,
@@ -267,12 +267,12 @@ static void ipw_close(struct usb_serial_port *port)
0,
200000);
if (result < 0)
- dev_err(&port->dev, "purge failed (error = %d)\n", result);
+ dev_err(dev, "purge failed (error = %d)\n", result);
/* send RXBULK_off (tell modem to stop transmitting bulk data on
rx chan) */
- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
IPW_SIO_RXCTL,
USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
IPW_RXBULK_OFF,
@@ -282,10 +282,9 @@ static void ipw_close(struct usb_serial_port *port)
100000);
if (result < 0)
- dev_err(&port->dev,
- "Disabling bulk RxRead failed (error = %d)\n", result);
+ dev_err(dev, "Disabling bulk RxRead failed (error = %d)\n", result);
- usb_serial_generic_close(port);
+ usb_wwan_close(port);
}
static struct usb_serial_driver ipw_device = {
@@ -294,46 +293,25 @@ static struct usb_serial_driver ipw_device = {
.name = "ipw",
},
.description = "IPWireless converter",
- .usb_driver = &usb_ipw_driver,
- .id_table = usb_ipw_ids,
+ .id_table = id_table,
.num_ports = 1,
.open = ipw_open,
.close = ipw_close,
+ .attach = ipw_attach,
+ .release = ipw_release,
+ .port_probe = usb_wwan_port_probe,
+ .port_remove = usb_wwan_port_remove,
.dtr_rts = ipw_dtr_rts,
+ .write = usb_wwan_write,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ipw_device, NULL
+};
-
-static int __init usb_ipw_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&ipw_device);
- if (retval)
- return retval;
- retval = usb_register(&usb_ipw_driver);
- if (retval) {
- usb_serial_deregister(&ipw_device);
- return retval;
- }
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-}
-
-static void __exit usb_ipw_exit(void)
-{
- usb_deregister(&usb_ipw_driver);
- usb_serial_deregister(&ipw_device);
-}
-
-module_init(usb_ipw_init);
-module_exit(usb_ipw_exit);
+module_usb_serial_driver(serial_drivers, id_table);
/* Module information */
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index ccbce4066d0..73956d48a0c 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -22,38 +22,6 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this
* driver
- *
- * 2008_Jun_02 Felipe Balbi <me@felipebalbi.com>
- * Introduced common header to be used also in USB Gadget Framework.
- * Still needs some other style fixes.
- *
- * 2007_Jun_21 Alan Cox <alan@lxorguk.ukuu.org.uk>
- * Minimal cleanups for some of the driver problens and tty layer abuse.
- * Still needs fixing to allow multiple dongles.
- *
- * 2002_Mar_07 greg kh
- * moved some needed structures and #define values from the
- * net/irda/irda-usb.h file into our file, as we don't want to depend on
- * that codebase compiling correctly :)
- *
- * 2002_Jan_14 gb
- * Added module parameter to force specific number of XBOFs.
- * Added ir_xbof_change().
- * Reorganized read_bulk_callback error handling.
- * Switched from FILL_BULK_URB() to usb_fill_bulk_urb().
- *
- * 2001_Nov_08 greg kh
- * Changed the irda_usb_find_class_desc() function based on comments and
- * code from Martin Diehl.
- *
- * 2001_Nov_01 greg kh
- * Added support for more IrDA USB devices.
- * Added support for zero packet. Added buffer override paramater, so
- * users can transfer larger packets at once if they wish. Both patches
- * came from Dag Brattli <dag@obexcode.com>.
- *
- * 2001_Oct_07 greg kh
- * initial version released.
*/
#include <linux/kernel.h>
@@ -70,15 +38,9 @@
#include <linux/usb/serial.h>
#include <linux/usb/irda.h>
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.5"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Johan Hovold <jhovold@gmail.com>"
#define DRIVER_DESC "USB IR Dongle driver"
-static int debug;
-
/* if overridden by the user, then use their value for the size of the read and
* write urbs */
static int buffer_size;
@@ -109,21 +71,12 @@ static const struct usb_device_id ir_id_table[] = {
MODULE_DEVICE_TABLE(usb, ir_id_table);
-static struct usb_driver ir_driver = {
- .name = "ir-usb",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = ir_id_table,
- .no_dynamic_id = 1,
-};
-
static struct usb_serial_driver ir_device = {
.driver = {
.owner = THIS_MODULE,
.name = "ir-usb",
},
.description = "IR Dongle",
- .usb_driver = &ir_driver,
.id_table = ir_id_table,
.num_ports = 1,
.set_termios = ir_set_termios,
@@ -133,18 +86,25 @@ static struct usb_serial_driver ir_device = {
.process_read_urb = ir_process_read_urb,
};
-static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc)
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ir_device, NULL
+};
+
+static inline void irda_usb_dump_class_desc(struct usb_serial *serial,
+ struct usb_irda_cs_descriptor *desc)
{
- dbg("bLength=%x", desc->bLength);
- dbg("bDescriptorType=%x", desc->bDescriptorType);
- dbg("bcdSpecRevision=%x", __le16_to_cpu(desc->bcdSpecRevision));
- dbg("bmDataSize=%x", desc->bmDataSize);
- dbg("bmWindowSize=%x", desc->bmWindowSize);
- dbg("bmMinTurnaroundTime=%d", desc->bmMinTurnaroundTime);
- dbg("wBaudRate=%x", __le16_to_cpu(desc->wBaudRate));
- dbg("bmAdditionalBOFs=%x", desc->bmAdditionalBOFs);
- dbg("bIrdaRateSniff=%x", desc->bIrdaRateSniff);
- dbg("bMaxUnicastList=%x", desc->bMaxUnicastList);
+ struct device *dev = &serial->dev->dev;
+
+ dev_dbg(dev, "bLength=%x\n", desc->bLength);
+ dev_dbg(dev, "bDescriptorType=%x\n", desc->bDescriptorType);
+ dev_dbg(dev, "bcdSpecRevision=%x\n", __le16_to_cpu(desc->bcdSpecRevision));
+ dev_dbg(dev, "bmDataSize=%x\n", desc->bmDataSize);
+ dev_dbg(dev, "bmWindowSize=%x\n", desc->bmWindowSize);
+ dev_dbg(dev, "bmMinTurnaroundTime=%d\n", desc->bmMinTurnaroundTime);
+ dev_dbg(dev, "wBaudRate=%x\n", __le16_to_cpu(desc->wBaudRate));
+ dev_dbg(dev, "bmAdditionalBOFs=%x\n", desc->bmAdditionalBOFs);
+ dev_dbg(dev, "bIrdaRateSniff=%x\n", desc->bIrdaRateSniff);
+ dev_dbg(dev, "bMaxUnicastList=%x\n", desc->bMaxUnicastList);
}
/*------------------------------------------------------------------*/
@@ -160,8 +120,9 @@ static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc)
* Based on the same function in drivers/net/irda/irda-usb.c
*/
static struct usb_irda_cs_descriptor *
-irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum)
+irda_usb_find_class_desc(struct usb_serial *serial, unsigned int ifnum)
{
+ struct usb_device *dev = serial->dev;
struct usb_irda_cs_descriptor *desc;
int ret;
@@ -174,20 +135,20 @@ irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum)
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, ifnum, desc, sizeof(*desc), 1000);
- dbg("%s - ret=%d", __func__, ret);
+ dev_dbg(&serial->dev->dev, "%s - ret=%d\n", __func__, ret);
if (ret < sizeof(*desc)) {
- dbg("%s - class descriptor read %s (%d)",
- __func__,
- (ret < 0) ? "failed" : "too short",
- ret);
+ dev_dbg(&serial->dev->dev,
+ "%s - class descriptor read %s (%d)\n", __func__,
+ (ret < 0) ? "failed" : "too short", ret);
goto error;
}
if (desc->bDescriptorType != USB_DT_CS_IRDA) {
- dbg("%s - bad class descriptor type", __func__);
+ dev_dbg(&serial->dev->dev, "%s - bad class descriptor type\n",
+ __func__);
goto error;
}
- irda_usb_dump_class_desc(desc);
+ irda_usb_dump_class_desc(serial, desc);
return desc;
error:
@@ -237,14 +198,15 @@ static int ir_startup(struct usb_serial *serial)
{
struct usb_irda_cs_descriptor *irda_desc;
- irda_desc = irda_usb_find_class_desc(serial->dev, 0);
+ irda_desc = irda_usb_find_class_desc(serial, 0);
if (!irda_desc) {
dev_err(&serial->dev->dev,
"IRDA class descriptor not found, device not bound\n");
return -ENODEV;
}
- dbg("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s",
+ dev_dbg(&serial->dev->dev,
+ "%s - Baud rates supported:%s%s%s%s%s%s%s%s%s\n",
__func__,
(irda_desc->wBaudRate & USB_IRDA_BR_2400) ? " 2400" : "",
(irda_desc->wBaudRate & USB_IRDA_BR_9600) ? " 9600" : "",
@@ -294,8 +256,6 @@ static int ir_open(struct tty_struct *tty, struct usb_serial_port *port)
{
int i;
- dbg("%s - port %d", __func__, port->number);
-
for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
port->write_urbs[i]->transfer_flags = URB_ZERO_PACKET;
@@ -327,7 +287,6 @@ static void ir_process_read_urb(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
- struct tty_struct *tty;
if (!urb->actual_length)
return;
@@ -342,25 +301,17 @@ static void ir_process_read_urb(struct urb *urb)
if (urb->actual_length == 1)
return;
- tty = tty_port_tty_get(&port->port);
- if (!tty)
- return;
- tty_insert_flip_string(tty, data + 1, urb->actual_length - 1);
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
+ tty_insert_flip_string(&port->port, data + 1, urb->actual_length - 1);
+ tty_flip_buffer_push(&port->port);
}
static void ir_set_termios_callback(struct urb *urb)
{
- struct usb_serial_port *port = urb->context;
- int status = urb->status;
-
- dbg("%s - port %d", __func__, port->number);
-
kfree(urb->transfer_buffer);
- if (status)
- dbg("%s - non-zero urb status: %d", __func__, status);
+ if (urb->status)
+ dev_dbg(&urb->dev->dev, "%s - non-zero urb status: %d\n",
+ __func__, urb->status);
}
static void ir_set_termios(struct tty_struct *tty,
@@ -372,8 +323,6 @@ static void ir_set_termios(struct tty_struct *tty,
speed_t baud;
int ir_baud;
- dbg("%s - port %d", __func__, port->number);
-
baud = tty_get_baud_rate(tty);
/*
@@ -421,22 +370,19 @@ static void ir_set_termios(struct tty_struct *tty,
ir_xbof = ir_xbof_change(xbof) ;
/* Only speed changes are supported */
- tty_termios_copy_hw(tty->termios, old_termios);
+ tty_termios_copy_hw(&tty->termios, old_termios);
tty_encode_baud_rate(tty, baud, baud);
/*
* send the baud change out on an "empty" data packet
*/
urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb) {
- dev_err(&port->dev, "%s - no more urbs\n", __func__);
+ if (!urb)
return;
- }
+
transfer_buffer = kmalloc(1, GFP_KERNEL);
- if (!transfer_buffer) {
- dev_err(&port->dev, "%s - out of memory\n", __func__);
+ if (!transfer_buffer)
goto err_buf;
- }
*transfer_buffer = ir_xbof | ir_baud;
@@ -470,37 +416,17 @@ err_buf:
static int __init ir_init(void)
{
- int retval;
-
if (buffer_size) {
ir_device.bulk_in_size = buffer_size;
ir_device.bulk_out_size = buffer_size;
}
- retval = usb_serial_register(&ir_device);
- if (retval)
- goto failed_usb_serial_register;
-
- retval = usb_register(&ir_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-
-failed_usb_register:
- usb_serial_deregister(&ir_device);
-
-failed_usb_serial_register:
- return retval;
+ return usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, ir_id_table);
}
static void __exit ir_exit(void)
{
- usb_deregister(&ir_driver);
- usb_serial_deregister(&ir_device);
+ usb_serial_deregister_drivers(serial_drivers);
}
@@ -511,8 +437,6 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
module_param(xbof, int, 0);
MODULE_PARM_DESC(xbof, "Force specific number of XBOFs");
module_param(buffer_size, int, 0);
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index 12ed594f5f8..5ad4a0fb4b2 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -17,7 +17,6 @@
*/
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -32,17 +31,6 @@
#include "iuu_phoenix.h"
#include <linux/random.h>
-
-#ifdef CONFIG_USB_SERIAL_DEBUG
-static int debug = 1;
-#else
-static int debug;
-#endif
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.12"
#define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"
static const struct usb_device_id id_table[] = {
@@ -51,28 +39,21 @@ static const struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver iuu_driver = {
- .name = "iuu_phoenix",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
/* turbo parameter */
static int boost = 100;
static int clockmode = 1;
static int cdmode = 1;
static int iuu_cardin;
static int iuu_cardout;
-static int xmas;
+static bool xmas;
static int vcc_default = 5;
+static int iuu_create_sysfs_attrs(struct usb_serial_port *port);
+static int iuu_remove_sysfs_attrs(struct usb_serial_port *port);
static void read_rxcmd_callback(struct urb *urb);
struct iuu_private {
spinlock_t lock; /* store irq state */
- wait_queue_head_t delta_msr_wait;
u8 line_status;
int tiostatus; /* store IUART SIGNAL for tiocmget call */
u8 reset; /* if 1 reset is needed */
@@ -80,7 +61,6 @@ struct iuu_private {
u8 *writebuf; /* buffer for writing to device */
int writelen; /* num of byte to write to device */
u8 *buf; /* used for initialize speed */
- u8 *dbgbuf; /* debug buffer */
u8 len;
int vcc; /* vcc (either 3 or 5 V) */
u32 baud;
@@ -88,69 +68,57 @@ struct iuu_private {
u32 clk;
};
-
-static void iuu_free_buf(struct iuu_private *priv)
+static int iuu_port_probe(struct usb_serial_port *port)
{
- kfree(priv->buf);
- kfree(priv->dbgbuf);
- kfree(priv->writebuf);
-}
+ struct iuu_private *priv;
+ int ret;
+
+ priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
-static int iuu_alloc_buf(struct iuu_private *priv)
-{
priv->buf = kzalloc(256, GFP_KERNEL);
- priv->dbgbuf = kzalloc(256, GFP_KERNEL);
- priv->writebuf = kzalloc(256, GFP_KERNEL);
- if (!priv->buf || !priv->dbgbuf || !priv->writebuf) {
- iuu_free_buf(priv);
- dbg("%s problem allocation buffer", __func__);
+ if (!priv->buf) {
+ kfree(priv);
return -ENOMEM;
}
- dbg("%s - Privates buffers allocation success", __func__);
- return 0;
-}
-static int iuu_startup(struct usb_serial *serial)
-{
- struct iuu_private *priv;
- priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
- dbg("%s- priv allocation success", __func__);
- if (!priv)
- return -ENOMEM;
- if (iuu_alloc_buf(priv)) {
+ priv->writebuf = kzalloc(256, GFP_KERNEL);
+ if (!priv->writebuf) {
+ kfree(priv->buf);
kfree(priv);
return -ENOMEM;
}
+
priv->vcc = vcc_default;
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
- usb_set_serial_port_data(serial->port[0], priv);
+
+ usb_set_serial_port_data(port, priv);
+
+ ret = iuu_create_sysfs_attrs(port);
+ if (ret) {
+ kfree(priv->writebuf);
+ kfree(priv->buf);
+ kfree(priv);
+ return ret;
+ }
+
return 0;
}
-/* Release function */
-static void iuu_release(struct usb_serial *serial)
+static int iuu_port_remove(struct usb_serial_port *port)
{
- struct usb_serial_port *port = serial->port[0];
struct iuu_private *priv = usb_get_serial_port_data(port);
- if (!port)
- return;
-
- dbg("%s", __func__);
- if (priv) {
- iuu_free_buf(priv);
- dbg("%s - I will free all", __func__);
- usb_set_serial_port_data(port, NULL);
-
- dbg("%s - priv is not anymore in port structure", __func__);
- kfree(priv);
+ iuu_remove_sysfs_attrs(port);
+ kfree(priv->writebuf);
+ kfree(priv->buf);
+ kfree(priv);
- dbg("%s priv is now kfree", __func__);
- }
+ return 0;
}
-static int iuu_tiocmset(struct tty_struct *tty, struct file *file,
+static int iuu_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
@@ -158,13 +126,13 @@ static int iuu_tiocmset(struct tty_struct *tty, struct file *file,
unsigned long flags;
/* FIXME: locking on tiomstatus */
- dbg("%s (%d) msg : SET = 0x%04x, CLEAR = 0x%04x ", __func__,
- port->number, set, clear);
+ dev_dbg(&port->dev, "%s msg : SET = 0x%04x, CLEAR = 0x%04x\n",
+ __func__, set, clear);
spin_lock_irqsave(&priv->lock, flags);
if ((set & TIOCM_RTS) && !(priv->tiostatus == TIOCM_RTS)) {
- dbg("%s TIOCMSET RESET called !!!", __func__);
+ dev_dbg(&port->dev, "%s TIOCMSET RESET called !!!\n", __func__);
priv->reset = 1;
}
if (set & TIOCM_RTS)
@@ -179,7 +147,7 @@ static int iuu_tiocmset(struct tty_struct *tty, struct file *file,
* When no card , the reader respond with TIOCM_CD
* This is known as CD autodetect mechanism
*/
-static int iuu_tiocmget(struct tty_struct *tty, struct file *file)
+static int iuu_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct iuu_private *priv = usb_get_serial_port_data(port);
@@ -199,10 +167,8 @@ static void iuu_rxcmd(struct urb *urb)
int result;
int status = urb->status;
- dbg("%s - enter", __func__);
-
if (status) {
- dbg("%s - status = %d", __func__, status);
+ dev_dbg(&port->dev, "%s - status = %d\n", __func__, status);
/* error stop all */
return;
}
@@ -222,7 +188,6 @@ static int iuu_reset(struct usb_serial_port *port, u8 wt)
struct iuu_private *priv = usb_get_serial_port_data(port);
int result;
char *buf_ptr = port->write_urb->transfer_buffer;
- dbg("%s - enter", __func__);
/* Prepare the reset sequence */
@@ -256,16 +221,14 @@ static void iuu_update_status_callback(struct urb *urb)
u8 *st;
int status = urb->status;
- dbg("%s - enter", __func__);
-
if (status) {
- dbg("%s - status = %d", __func__, status);
+ dev_dbg(&port->dev, "%s - status = %d\n", __func__, status);
/* error stop all */
return;
}
st = urb->transfer_buffer;
- dbg("%s - enter", __func__);
+ dev_dbg(&port->dev, "%s - enter\n", __func__);
if (urb->actual_length == 1) {
switch (st[0]) {
case 0x1:
@@ -287,7 +250,7 @@ static void iuu_status_callback(struct urb *urb)
int result;
int status = urb->status;
- dbg("%s - status = %d", __func__, status);
+ dev_dbg(&port->dev, "%s - status = %d\n", __func__, status);
usb_fill_bulk_urb(port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
@@ -300,8 +263,6 @@ static int iuu_status(struct usb_serial_port *port)
{
int result;
- dbg("%s - enter", __func__);
-
memset(port->write_urb->transfer_buffer, IUU_GET_STATE_REGISTER, 1);
usb_fill_bulk_urb(port->write_urb, port->serial->dev,
usb_sndbulkpipe(port->serial->dev,
@@ -319,20 +280,18 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
struct usb_serial *serial = port->serial;
int actual = 0;
- dbg("%s - enter", __func__);
-
/* send the data out the bulk port */
status =
usb_bulk_msg(serial->dev,
usb_sndbulkpipe(serial->dev,
port->bulk_out_endpointAddress), buf,
- count, &actual, HZ * 1);
+ count, &actual, 1000);
if (status != IUU_OPERATION_OK)
- dbg("%s - error = %2x", __func__, status);
+ dev_dbg(&port->dev, "%s - error = %2x\n", __func__, status);
else
- dbg("%s - write OK !", __func__);
+ dev_dbg(&port->dev, "%s - write OK !\n", __func__);
return status;
}
@@ -342,20 +301,17 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
struct usb_serial *serial = port->serial;
int actual = 0;
- dbg("%s - enter", __func__);
-
/* send the data out the bulk port */
-
status =
usb_bulk_msg(serial->dev,
usb_rcvbulkpipe(serial->dev,
port->bulk_in_endpointAddress), buf,
- count, &actual, HZ * 1);
+ count, &actual, 1000);
if (status != IUU_OPERATION_OK)
- dbg("%s - error = %2x", __func__, status);
+ dev_dbg(&port->dev, "%s - error = %2x\n", __func__, status);
else
- dbg("%s - read OK !", __func__);
+ dev_dbg(&port->dev, "%s - read OK !\n", __func__);
return status;
}
@@ -368,8 +324,6 @@ static int iuu_led(struct usb_serial_port *port, unsigned int R,
if (!buf)
return -ENOMEM;
- dbg("%s - enter", __func__);
-
buf[0] = IUU_SET_LED;
buf[1] = R & 0xFF;
buf[2] = (R >> 8) & 0xFF;
@@ -381,9 +335,9 @@ static int iuu_led(struct usb_serial_port *port, unsigned int R,
status = bulk_immediate(port, buf, 8);
kfree(buf);
if (status != IUU_OPERATION_OK)
- dbg("%s - led error status = %2x", __func__, status);
+ dev_dbg(&port->dev, "%s - led error status = %2x\n", __func__, status);
else
- dbg("%s - led OK !", __func__);
+ dev_dbg(&port->dev, "%s - led OK !\n", __func__);
return IUU_OPERATION_OK;
}
@@ -461,8 +415,6 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq)
unsigned int P2 = 0;
int frq = (int)dwFrq;
- dbg("%s - enter", __func__);
-
if (frq == 0) {
priv->buf[Count++] = IUU_UART_WRITE_I2C;
priv->buf[Count++] = FrqGenAdr << 1;
@@ -471,7 +423,7 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq)
status = bulk_immediate(port, (u8 *) priv->buf, Count);
if (status != 0) {
- dbg("%s - write error ", __func__);
+ dev_dbg(&port->dev, "%s - write error\n", __func__);
return status;
}
} else if (frq == 3579000) {
@@ -580,46 +532,44 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq)
status = bulk_immediate(port, (u8 *) priv->buf, Count);
if (status != IUU_OPERATION_OK)
- dbg("%s - write error ", __func__);
+ dev_dbg(&port->dev, "%s - write error\n", __func__);
return status;
}
static int iuu_uart_flush(struct usb_serial_port *port)
{
+ struct device *dev = &port->dev;
int i;
int status;
u8 rxcmd = IUU_UART_RX;
struct iuu_private *priv = usb_get_serial_port_data(port);
- dbg("%s - enter", __func__);
-
if (iuu_led(port, 0xF000, 0, 0, 0xFF) < 0)
return -EIO;
for (i = 0; i < 2; i++) {
status = bulk_immediate(port, &rxcmd, 1);
if (status != IUU_OPERATION_OK) {
- dbg("%s - uart_flush_write error", __func__);
+ dev_dbg(dev, "%s - uart_flush_write error\n", __func__);
return status;
}
status = read_immediate(port, &priv->len, 1);
if (status != IUU_OPERATION_OK) {
- dbg("%s - uart_flush_read error", __func__);
+ dev_dbg(dev, "%s - uart_flush_read error\n", __func__);
return status;
}
if (priv->len > 0) {
- dbg("%s - uart_flush datalen is : %i ", __func__,
- priv->len);
+ dev_dbg(dev, "%s - uart_flush datalen is : %i\n", __func__, priv->len);
status = read_immediate(port, priv->buf, priv->len);
if (status != IUU_OPERATION_OK) {
- dbg("%s - uart_flush_read error", __func__);
+ dev_dbg(dev, "%s - uart_flush_read error\n", __func__);
return status;
}
}
}
- dbg("%s - uart_flush_read OK!", __func__);
+ dev_dbg(dev, "%s - uart_flush_read OK!\n", __func__);
iuu_led(port, 0, 0xF000, 0, 0xFF);
return status;
}
@@ -628,11 +578,8 @@ static void read_buf_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
- struct tty_struct *tty;
int status = urb->status;
- dbg("%s - status = %d", __func__, status);
-
if (status) {
if (status == -EPROTO) {
/* reschedule needed */
@@ -640,15 +587,13 @@ static void read_buf_callback(struct urb *urb)
return;
}
- dbg("%s - %i chars to write", __func__, urb->actual_length);
- tty = tty_port_tty_get(&port->port);
+ dev_dbg(&port->dev, "%s - %i chars to write\n", __func__, urb->actual_length);
if (data == NULL)
- dbg("%s - data is NULL !!!", __func__);
- if (tty && urb->actual_length && data) {
- tty_insert_flip_string(tty, data, urb->actual_length);
- tty_flip_buffer_push(tty);
+ dev_dbg(&port->dev, "%s - data is NULL !!!\n", __func__);
+ if (urb->actual_length && data) {
+ tty_insert_flip_string(&port->port, data, urb->actual_length);
+ tty_flip_buffer_push(&port->port);
}
- tty_kref_put(tty);
iuu_led_activity_on(urb);
}
@@ -657,10 +602,8 @@ static int iuu_bulk_write(struct usb_serial_port *port)
struct iuu_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int result;
- int i;
int buf_len;
char *buf_ptr = port->write_urb->transfer_buffer;
- dbg("%s - enter", __func__);
spin_lock_irqsave(&priv->lock, flags);
*buf_ptr++ = IUU_UART_ESC;
@@ -671,14 +614,8 @@ static int iuu_bulk_write(struct usb_serial_port *port)
buf_len = priv->writelen;
priv->writelen = 0;
spin_unlock_irqrestore(&priv->lock, flags);
- if (debug == 1) {
- for (i = 0; i < buf_len; i++)
- sprintf(priv->dbgbuf + i*2 ,
- "%02X", priv->writebuf[i]);
- priv->dbgbuf[buf_len+i*2] = 0;
- dbg("%s - writing %i chars : %s", __func__,
- buf_len, priv->dbgbuf);
- }
+ dev_dbg(&port->dev, "%s - writing %i chars : %*ph\n", __func__,
+ buf_len, buf_len, buf_ptr);
usb_fill_bulk_urb(port->write_urb, port->serial->dev,
usb_sndbulkpipe(port->serial->dev,
port->bulk_out_endpointAddress),
@@ -692,7 +629,6 @@ static int iuu_bulk_write(struct usb_serial_port *port)
static int iuu_read_buf(struct usb_serial_port *port, int len)
{
int result;
- dbg("%s - enter", __func__);
usb_fill_bulk_urb(port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
@@ -714,21 +650,19 @@ static void iuu_uart_read_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
priv->poll++;
- dbg("%s - enter", __func__);
-
if (status) {
- dbg("%s - status = %d", __func__, status);
+ dev_dbg(&port->dev, "%s - status = %d\n", __func__, status);
/* error stop all */
return;
}
if (data == NULL)
- dbg("%s - data is NULL !!!", __func__);
+ dev_dbg(&port->dev, "%s - data is NULL !!!\n", __func__);
if (urb->actual_length == 1 && data != NULL)
len = (int) data[0];
if (urb->actual_length > 1) {
- dbg("%s - urb->actual_length = %i", __func__,
+ dev_dbg(&port->dev, "%s - urb->actual_length = %i\n", __func__,
urb->actual_length);
error = 1;
return;
@@ -736,7 +670,7 @@ static void iuu_uart_read_callback(struct urb *urb)
/* if len > 0 call readbuf */
if (len > 0 && error == 0) {
- dbg("%s - call read buf - len to read is %i ",
+ dev_dbg(&port->dev, "%s - call read buf - len to read is %i\n",
__func__, len);
status = iuu_read_buf(port, len);
return;
@@ -763,7 +697,7 @@ static void iuu_uart_read_callback(struct urb *urb)
}
spin_unlock_irqrestore(&priv->lock, flags);
/* if nothing to write call again rxcmd */
- dbg("%s - rxcmd recall", __func__);
+ dev_dbg(&port->dev, "%s - rxcmd recall\n", __func__);
iuu_led_activity_off(urb);
}
@@ -772,7 +706,6 @@ static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port,
{
struct iuu_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- dbg("%s - enter", __func__);
if (count > 256)
return -ENOMEM;
@@ -793,8 +726,6 @@ static void read_rxcmd_callback(struct urb *urb)
int result;
int status = urb->status;
- dbg("%s - status = %d", __func__, status);
-
if (status) {
/* error stop all */
return;
@@ -806,7 +737,7 @@ static void read_rxcmd_callback(struct urb *urb)
port->read_urb->transfer_buffer, 256,
iuu_uart_read_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- dbg("%s - submit result = %d", __func__, result);
+ dev_dbg(&port->dev, "%s - submit result = %d\n", __func__, result);
}
static int iuu_uart_on(struct usb_serial_port *port)
@@ -826,19 +757,19 @@ static int iuu_uart_on(struct usb_serial_port *port)
status = bulk_immediate(port, buf, 4);
if (status != IUU_OPERATION_OK) {
- dbg("%s - uart_on error", __func__);
+ dev_dbg(&port->dev, "%s - uart_on error\n", __func__);
goto uart_enable_failed;
}
/* iuu_reset() the card after iuu_uart_on() */
status = iuu_uart_flush(port);
if (status != IUU_OPERATION_OK)
- dbg("%s - uart_flush error", __func__);
+ dev_dbg(&port->dev, "%s - uart_flush error\n", __func__);
uart_enable_failed:
kfree(buf);
return status;
}
-/* Diables the IUU UART (a.k.a. the Phoenix voiderface) */
+/* Disables the IUU UART (a.k.a. the Phoenix voiderface) */
static int iuu_uart_off(struct usb_serial_port *port)
{
int status;
@@ -850,7 +781,7 @@ static int iuu_uart_off(struct usb_serial_port *port)
status = bulk_immediate(port, buf, 1);
if (status != IUU_OPERATION_OK)
- dbg("%s - uart_off error", __func__);
+ dev_dbg(&port->dev, "%s - uart_off error\n", __func__);
kfree(buf);
return status;
@@ -867,7 +798,7 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud_base,
u8 T1reload = 0;
unsigned int T1FrekvensHZ = 0;
- dbg("%s - enter baud_base=%d", __func__, baud_base);
+ dev_dbg(&port->dev, "%s - enter baud_base=%d\n", __func__, baud_base);
dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL);
if (!dataout)
@@ -948,7 +879,7 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud_base,
status = bulk_immediate(port, dataout, DataCount);
if (status != IUU_OPERATION_OK)
- dbg("%s - uart_off error", __func__);
+ dev_dbg(&port->dev, "%s - uart_off error\n", __func__);
kfree(dataout);
return status;
}
@@ -958,7 +889,7 @@ static void iuu_set_termios(struct tty_struct *tty,
{
const u32 supported_mask = CMSPAR|PARENB|PARODD;
struct iuu_private *priv = usb_get_serial_port_data(port);
- unsigned int cflag = tty->termios->c_cflag;
+ unsigned int cflag = tty->termios.c_cflag;
int status;
u32 actual;
u32 parity;
@@ -967,9 +898,9 @@ static void iuu_set_termios(struct tty_struct *tty,
u32 newval = cflag & supported_mask;
/* Just use the ospeed. ispeed should be the same. */
- baud = tty->termios->c_ospeed;
+ baud = tty->termios.c_ospeed;
- dbg("%s - enter c_ospeed or baud=%d", __func__, baud);
+ dev_dbg(&port->dev, "%s - enter c_ospeed or baud=%d\n", __func__, baud);
/* compute the parity parameter */
parity = 0;
@@ -998,66 +929,55 @@ static void iuu_set_termios(struct tty_struct *tty,
* settings back over and then adjust them
*/
if (old_termios)
- tty_termios_copy_hw(tty->termios, old_termios);
+ tty_termios_copy_hw(&tty->termios, old_termios);
if (status != 0) /* Set failed - return old bits */
return;
/* Re-encode speed, parity and csize */
tty_encode_baud_rate(tty, baud, baud);
- tty->termios->c_cflag &= ~(supported_mask|CSIZE);
- tty->termios->c_cflag |= newval | csize;
+ tty->termios.c_cflag &= ~(supported_mask|CSIZE);
+ tty->termios.c_cflag |= newval | csize;
}
static void iuu_close(struct usb_serial_port *port)
{
/* iuu_led (port,255,0,0,0); */
- struct usb_serial *serial;
- serial = port->serial;
- if (!serial)
- return;
+ iuu_uart_off(port);
- dbg("%s - port %d", __func__, port->number);
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
- iuu_uart_off(port);
- if (serial->dev) {
- /* free writebuf */
- /* shutdown our urbs */
- dbg("%s - shutting down urbs", __func__);
- usb_kill_urb(port->write_urb);
- usb_kill_urb(port->read_urb);
- usb_kill_urb(port->interrupt_in_urb);
- iuu_led(port, 0, 0, 0xF000, 0xFF);
- }
+ iuu_led(port, 0, 0, 0xF000, 0xFF);
}
static void iuu_init_termios(struct tty_struct *tty)
{
- dbg("%s - enter", __func__);
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
+ tty->termios = tty_std_termios;
+ tty->termios.c_cflag = CLOCAL | CREAD | CS8 | B9600
| TIOCM_CTS | CSTOPB | PARENB;
- tty->termios->c_ispeed = 9600;
- tty->termios->c_ospeed = 9600;
- tty->termios->c_lflag = 0;
- tty->termios->c_oflag = 0;
- tty->termios->c_iflag = 0;
+ tty->termios.c_ispeed = 9600;
+ tty->termios.c_ospeed = 9600;
+ tty->termios.c_lflag = 0;
+ tty->termios.c_oflag = 0;
+ tty->termios.c_iflag = 0;
}
static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
+ struct device *dev = &port->dev;
u8 *buf;
int result;
int baud;
u32 actual;
struct iuu_private *priv = usb_get_serial_port_data(port);
- baud = tty->termios->c_ospeed;
- tty->termios->c_ispeed = baud;
+ baud = tty->termios.c_ospeed;
+ tty->termios.c_ispeed = baud;
/* Re-encode speed */
tty_encode_baud_rate(tty, baud, baud);
- dbg("%s - port %d, baud %d", __func__, port->number, baud);
+ dev_dbg(dev, "%s - baud %d\n", __func__, baud);
usb_clear_halt(serial->dev, port->write_urb->pipe);
usb_clear_halt(serial->dev, port->read_urb->pipe);
@@ -1072,14 +992,14 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
result = usb_control_msg(port->serial->dev, \
usb_rcvctrlpipe(port->serial->dev, 0), \
b, a, c, d, buf, 1, 1000); \
- dbg("0x%x:0x%x:0x%x:0x%x %d - %x", a, b, c, d, result, \
+ dev_dbg(dev, "0x%x:0x%x:0x%x:0x%x %d - %x\n", a, b, c, d, result, \
buf[0]); } while (0);
#define SOUP(a, b, c, d) do { \
result = usb_control_msg(port->serial->dev, \
usb_sndctrlpipe(port->serial->dev, 0), \
b, a, c, d, NULL, 0, 1000); \
- dbg("0x%x:0x%x:0x%x:0x%x %d", a, b, c, d, result); } while (0)
+ dev_dbg(dev, "0x%x:0x%x:0x%x:0x%x %d\n", a, b, c, d, result); } while (0)
/* This is not UART related but IUU USB driver related or something */
/* like that. Basically no IUU will accept any commands from the USB */
@@ -1159,7 +1079,7 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
iuu_uart_flush(port);
- dbg("%s - initialization done", __func__);
+ dev_dbg(dev, "%s - initialization done\n", __func__);
memset(port->write_urb->transfer_buffer, IUU_UART_RX, 1);
usb_fill_bulk_urb(port->write_urb, port->serial->dev,
@@ -1168,15 +1088,13 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
port->write_urb->transfer_buffer, 1,
read_rxcmd_callback, port);
result = usb_submit_urb(port->write_urb, GFP_KERNEL);
-
if (result) {
- dev_err(&port->dev, "%s - failed submitting read urb,"
- " error %d\n", __func__, result);
+ dev_err(dev, "%s - failed submitting read urb, error %d\n", __func__, result);
iuu_close(port);
- return -EPROTO;
} else {
- dbg("%s - rxcmd OK", __func__);
+ dev_dbg(dev, "%s - rxcmd OK\n", __func__);
}
+
return result;
}
@@ -1190,8 +1108,6 @@ static int iuu_vcc_set(struct usb_serial_port *port, unsigned int vcc)
if (!buf)
return -ENOMEM;
- dbg("%s - enter", __func__);
-
buf[0] = IUU_SET_VCC;
buf[1] = vcc & 0xFF;
buf[2] = (vcc >> 8) & 0xFF;
@@ -1202,9 +1118,9 @@ static int iuu_vcc_set(struct usb_serial_port *port, unsigned int vcc)
kfree(buf);
if (status != IUU_OPERATION_OK)
- dbg("%s - vcc error status = %2x", __func__, status);
+ dev_dbg(&port->dev, "%s - vcc error status = %2x\n", __func__, status);
else
- dbg("%s - vcc OK !", __func__);
+ dev_dbg(&port->dev, "%s - vcc OK !\n", __func__);
return status;
}
@@ -1213,7 +1129,7 @@ static int iuu_vcc_set(struct usb_serial_port *port, unsigned int vcc)
* Sysfs Attributes
*/
-static ssize_t show_vcc_mode(struct device *dev,
+static ssize_t vcc_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
@@ -1222,20 +1138,20 @@ static ssize_t show_vcc_mode(struct device *dev,
return sprintf(buf, "%d\n", priv->vcc);
}
-static ssize_t store_vcc_mode(struct device *dev,
+static ssize_t vcc_mode_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct iuu_private *priv = usb_get_serial_port_data(port);
unsigned long v;
- if (strict_strtoul(buf, 10, &v)) {
+ if (kstrtoul(buf, 10, &v)) {
dev_err(dev, "%s - vcc_mode: %s is not a unsigned long\n",
__func__, buf);
goto fail_store_vcc_mode;
}
- dbg("%s: setting vcc_mode = %ld", __func__, v);
+ dev_dbg(dev, "%s: setting vcc_mode = %ld\n", __func__, v);
if ((v != 3) && (v != 5)) {
dev_err(dev, "%s - vcc_mode %ld is invalid\n", __func__, v);
@@ -1246,21 +1162,15 @@ static ssize_t store_vcc_mode(struct device *dev,
fail_store_vcc_mode:
return count;
}
-
-static DEVICE_ATTR(vcc_mode, S_IRUSR | S_IWUSR, show_vcc_mode,
- store_vcc_mode);
+static DEVICE_ATTR_RW(vcc_mode);
static int iuu_create_sysfs_attrs(struct usb_serial_port *port)
{
- dbg("%s", __func__);
-
return device_create_file(&port->dev, &dev_attr_vcc_mode);
}
static int iuu_remove_sysfs_attrs(struct usb_serial_port *port)
{
- dbg("%s", __func__);
-
device_remove_file(&port->dev, &dev_attr_vcc_mode);
return 0;
}
@@ -1278,8 +1188,6 @@ static struct usb_serial_driver iuu_device = {
.num_ports = 1,
.bulk_in_size = 512,
.bulk_out_size = 512,
- .port_probe = iuu_create_sysfs_attrs,
- .port_remove = iuu_remove_sysfs_attrs,
.open = iuu_open,
.close = iuu_close,
.write = iuu_uart_write,
@@ -1288,46 +1196,21 @@ static struct usb_serial_driver iuu_device = {
.tiocmset = iuu_tiocmset,
.set_termios = iuu_set_termios,
.init_termios = iuu_init_termios,
- .attach = iuu_startup,
- .release = iuu_release,
+ .port_probe = iuu_port_probe,
+ .port_remove = iuu_port_remove,
};
-static int __init iuu_init(void)
-{
- int retval;
- retval = usb_serial_register(&iuu_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&iuu_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&iuu_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit iuu_exit(void)
-{
- usb_deregister(&iuu_driver);
- usb_serial_deregister(&iuu_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &iuu_device, NULL
+};
-module_init(iuu_init);
-module_exit(iuu_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR("Alain Degreffe eczema@ecze.com");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-MODULE_VERSION(DRIVER_VERSION);
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
module_param(xmas, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(xmas, "Xmas colors enabled or not");
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 0791778a66f..93cb7cebda6 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -25,122 +25,51 @@
Tip 'o the hat to IBM (and previously Linuxcare :) for supporting
staff in their work on open source projects.
-
- Change History
-
- 2003sep04 LPM (Keyspan) add support for new single port product USA19HS.
- Improve setup message handling for all devices.
-
- Wed Feb 19 22:00:00 PST 2003 (Jeffrey S. Laing <keyspan@jsl.com>)
- Merged the current (1/31/03) Keyspan code with the current (2.4.21-pre4)
- Linux source tree. The Linux tree lacked support for the 49WLC and
- others. The Keyspan patches didn't work with the current kernel.
-
- 2003jan30 LPM add support for the 49WLC and MPR
-
- Wed Apr 25 12:00:00 PST 2002 (Keyspan)
- Started with Hugh Blemings' code dated Jan 17, 2002. All adapters
- now supported (including QI and QW). Modified port open, port
- close, and send setup() logic to fix various data and endpoint
- synchronization bugs and device LED status bugs. Changed keyspan_
- write_room() to accurately return transmit buffer availability.
- Changed forwardingLength from 1 to 16 for all adapters.
-
- Fri Oct 12 16:45:00 EST 2001
- Preliminary USA-19QI and USA-28 support (both test OK for me, YMMV)
-
- Wed Apr 25 12:00:00 PST 2002 (Keyspan)
- Started with Hugh Blemings' code dated Jan 17, 2002. All adapters
- now supported (including QI and QW). Modified port open, port
- close, and send setup() logic to fix various data and endpoint
- synchronization bugs and device LED status bugs. Changed keyspan_
- write_room() to accurately return transmit buffer availability.
- Changed forwardingLength from 1 to 16 for all adapters.
-
- Fri Oct 12 16:45:00 EST 2001
- Preliminary USA-19QI and USA-28 support (both test OK for me, YMMV)
-
- Mon Oct 8 14:29:00 EST 2001 hugh
- Fixed bug that prevented mulitport devices operating correctly
- if they weren't the first unit attached.
-
- Sat Oct 6 12:31:21 EST 2001 hugh
- Added support for USA-28XA and -28XB, misc cleanups, break support
- for usa26 based models thanks to David Gibson.
-
- Thu May 31 11:56:42 PDT 2001 gkh
- switched from using spinlock to a semaphore
-
- (04/08/2001) gb
- Identify version on module load.
-
- (11/01/2000) Adam J. Richter
- usb_device_id table support.
-
- Tue Oct 10 23:15:33 EST 2000 Hugh
- Merged Paul's changes with my USA-49W mods. Work in progress
- still...
-
- Wed Jul 19 14:00:42 EST 2000 gkh
- Added module_init and module_exit functions to handle the fact that
- this driver is a loadable module now.
-
- Tue Jul 18 16:14:52 EST 2000 Hugh
- Basic character input/output for USA-19 now mostly works,
- fixed at 9600 baud for the moment.
-
- Sat Jul 8 11:11:48 EST 2000 Hugh
- First public release - nothing works except the firmware upload.
- Tested on PPC and x86 architectures, seems to behave...
*/
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.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/firmware.h>
-#include <linux/ihex.h>
#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
+#include <linux/usb/ezusb.h>
#include "keyspan.h"
-static int debug;
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.1.5"
#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
#define INSTAT_BUFLEN 32
#define GLOCONT_BUFLEN 64
#define INDAT49W_BUFLEN 512
+#define IN_BUFLEN 64
+#define OUT_BUFLEN 64
+#define INACK_BUFLEN 1
+#define OUTCONT_BUFLEN 64
/* Per device and per port private data */
struct keyspan_serial_private {
const struct keyspan_device_details *device_details;
struct urb *instat_urb;
- char instat_buf[INSTAT_BUFLEN];
+ char *instat_buf;
/* added to support 49wg, where data from all 4 ports comes in
on 1 EP and high-speed supported */
struct urb *indat_urb;
- char indat_buf[INDAT49W_BUFLEN];
+ char *indat_buf;
/* XXX this one probably will need a lock */
struct urb *glocont_urb;
- char glocont_buf[GLOCONT_BUFLEN];
- char ctrl_buf[8]; /* for EP0 control message */
+ char *glocont_buf;
+ char *ctrl_buf; /* for EP0 control message */
};
struct keyspan_port_private {
@@ -155,18 +84,18 @@ struct keyspan_port_private {
/* Input endpoints and buffer for this port */
struct urb *in_urbs[2];
- char in_buffer[2][64];
+ char *in_buffer[2];
/* Output endpoints and buffer for this port */
struct urb *out_urbs[2];
- char out_buffer[2][64];
+ char *out_buffer[2];
/* Input ack endpoint */
struct urb *inack_urb;
- char inack_buffer[1];
+ char *inack_buffer;
/* Output control endpoint */
struct urb *outcont_urb;
- char outcont_buffer[64];
+ char *outcont_buffer;
/* Settings for the port */
int baud;
@@ -197,61 +126,13 @@ struct keyspan_port_private {
#include "keyspan_usa67msg.h"
-/* Functions used by new usb-serial code. */
-static int __init keyspan_init(void)
-{
- int retval;
- retval = usb_serial_register(&keyspan_pre_device);
- if (retval)
- goto failed_pre_device_register;
- retval = usb_serial_register(&keyspan_1port_device);
- if (retval)
- goto failed_1port_device_register;
- retval = usb_serial_register(&keyspan_2port_device);
- if (retval)
- goto failed_2port_device_register;
- retval = usb_serial_register(&keyspan_4port_device);
- if (retval)
- goto failed_4port_device_register;
- retval = usb_register(&keyspan_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-failed_usb_register:
- usb_serial_deregister(&keyspan_4port_device);
-failed_4port_device_register:
- usb_serial_deregister(&keyspan_2port_device);
-failed_2port_device_register:
- usb_serial_deregister(&keyspan_1port_device);
-failed_1port_device_register:
- usb_serial_deregister(&keyspan_pre_device);
-failed_pre_device_register:
- return retval;
-}
-
-static void __exit keyspan_exit(void)
-{
- usb_deregister(&keyspan_driver);
- usb_serial_deregister(&keyspan_pre_device);
- usb_serial_deregister(&keyspan_1port_device);
- usb_serial_deregister(&keyspan_2port_device);
- usb_serial_deregister(&keyspan_4port_device);
-}
-
-module_init(keyspan_init);
-module_exit(keyspan_exit);
+module_usb_serial_driver(serial_drivers, keyspan_ids_combined);
static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct keyspan_port_private *p_priv;
- dbg("%s", __func__);
-
p_priv = usb_get_serial_port_data(port);
if (break_state == -1)
@@ -271,21 +152,19 @@ static void keyspan_set_termios(struct tty_struct *tty,
const struct keyspan_device_details *d_details;
unsigned int cflag;
- dbg("%s", __func__);
-
p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
- cflag = tty->termios->c_cflag;
- device_port = port->number - port->serial->minor;
+ cflag = tty->termios.c_cflag;
+ device_port = port->port_number;
/* Baud rate calculation takes baud rate as an integer
so other rates can be generated if desired. */
baud_rate = tty_get_baud_rate(tty);
/* If no match or invalid, don't change */
- if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
+ if (d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
/* FIXME - more to do here to ensure rate changes cleanly */
- /* FIXME - calcuate exact rate from divisor ? */
+ /* FIXME - calculate exact rate from divisor ? */
p_priv->baud = baud_rate;
} else
baud_rate = tty_termios_baud_rate(old_termios);
@@ -293,15 +172,15 @@ static void keyspan_set_termios(struct tty_struct *tty,
tty_encode_baud_rate(tty, baud_rate, baud_rate);
/* set CTS/RTS handshake etc. */
p_priv->cflag = cflag;
- p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
+ p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
/* Mark/Space not supported */
- tty->termios->c_cflag &= ~CMSPAR;
+ tty->termios.c_cflag &= ~CMSPAR;
keyspan_send_setup(port, 0);
}
-static int keyspan_tiocmget(struct tty_struct *tty, struct file *file)
+static int keyspan_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
@@ -317,7 +196,7 @@ static int keyspan_tiocmget(struct tty_struct *tty, struct file *file)
return value;
}
-static int keyspan_tiocmset(struct tty_struct *tty, struct file *file,
+static int keyspan_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
@@ -358,8 +237,8 @@ static int keyspan_write(struct tty_struct *tty,
dataOffset = 1;
}
- dbg("%s - for port %d (%d chars), flip=%d",
- __func__, port->number, count, p_priv->out_flip);
+ dev_dbg(&port->dev, "%s - %d chars, flip=%d\n", __func__, count,
+ p_priv->out_flip);
for (left = count; left > 0; left -= todo) {
todo = left;
@@ -372,11 +251,11 @@ static int keyspan_write(struct tty_struct *tty,
this_urb = p_priv->out_urbs[flip];
if (this_urb == NULL) {
/* no bulk out, so return 0 bytes written */
- dbg("%s - no output urb :(", __func__);
+ dev_dbg(&port->dev, "%s - no output urb :(\n", __func__);
return count;
}
- dbg("%s - endpoint %d flip %d",
+ dev_dbg(&port->dev, "%s - endpoint %d flip %d\n",
__func__, usb_pipeendpoint(this_urb->pipe), flip);
if (this_urb->status == -EINPROGRESS) {
@@ -397,10 +276,9 @@ static int keyspan_write(struct tty_struct *tty,
/* send the data out the bulk port */
this_urb->transfer_buffer_length = todo + dataOffset;
- this_urb->dev = port->serial->dev;
err = usb_submit_urb(this_urb, GFP_ATOMIC);
if (err != 0)
- dbg("usb_submit_urb(write bulk) failed (%d)", err);
+ dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed (%d)\n", err);
p_priv->tx_start_time[flip] = jiffies;
/* Flip for next time if usa26 or usa28 interface
@@ -416,23 +294,19 @@ static void usa26_indat_callback(struct urb *urb)
int i, err;
int endpoint;
struct usb_serial_port *port;
- struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg("%s", __func__);
-
endpoint = usb_pipeendpoint(urb->pipe);
if (status) {
- dbg("%s - nonzero status: %x on endpoint %d.",
- __func__, status, endpoint);
+ dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
+ __func__, status, endpoint);
return;
}
port = urb->context;
- tty = tty_port_tty_get(&port->port);
- if (tty && urb->actual_length) {
+ if (urb->actual_length) {
/* 0x80 bit is error flag */
if ((data[0] & 0x80) == 0) {
/* no errors on individual bytes, only
@@ -442,10 +316,10 @@ static void usa26_indat_callback(struct urb *urb)
else
err = 0;
for (i = 1; i < urb->actual_length ; ++i)
- tty_insert_flip_char(tty, data[i], err);
+ tty_insert_flip_char(&port->port, data[i], err);
} else {
/* some bytes had errors, every byte has status */
- dbg("%s - RX error!!!!", __func__);
+ dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
for (i = 0; i + 1 < urb->actual_length; i += 2) {
int stat = data[i], flag = 0;
if (stat & RXERROR_OVERRUN)
@@ -455,18 +329,17 @@ static void usa26_indat_callback(struct urb *urb)
if (stat & RXERROR_PARITY)
flag |= TTY_PARITY;
/* XXX should handle break (0x10) */
- tty_insert_flip_char(tty, data[i+1], flag);
+ tty_insert_flip_char(&port->port, data[i+1],
+ flag);
}
}
- tty_flip_buffer_push(tty);
+ tty_flip_buffer_push(&port->port);
}
- tty_kref_put(tty);
/* Resubmit urb so we continue receiving */
- urb->dev = port->serial->dev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
}
/* Outdat handling is common for all devices */
@@ -477,15 +350,13 @@ static void usa2x_outdat_callback(struct urb *urb)
port = urb->context;
p_priv = usb_get_serial_port_data(port);
- dbg("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
+ dev_dbg(&port->dev, "%s - urb %d\n", __func__, urb == p_priv->out_urbs[1]);
usb_serial_port_softint(port);
}
static void usa26_inack_callback(struct urb *urb)
{
- dbg("%s", __func__);
-
}
static void usa26_outcont_callback(struct urb *urb)
@@ -497,7 +368,7 @@ static void usa26_outcont_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg("%s - sending setup", __func__);
+ dev_dbg(&port->dev, "%s - sending setup\n", __func__);
keyspan_usa26_send_setup(port->serial, port,
p_priv->resend_cont - 1);
}
@@ -510,35 +381,25 @@ static void usa26_instat_callback(struct urb *urb)
struct usb_serial *serial;
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
- struct tty_struct *tty;
int old_dcd_state, err;
int status = urb->status;
serial = urb->context;
if (status) {
- dbg("%s - nonzero status: %x", __func__, status);
+ dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
return;
}
if (urb->actual_length != 9) {
- dbg("%s - %d byte report??", __func__, urb->actual_length);
+ dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
goto exit;
}
msg = (struct keyspan_usa26_portStatusMessage *)data;
-#if 0
- dbg("%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d",
- __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff,
- msg->_txXoff, msg->rxEnabled, msg->controlResponse);
-#endif
-
- /* Now do something useful with the data */
-
-
/* Check port number from message and retrieve private data */
if (msg->port >= serial->num_ports) {
- dbg("%s - Unexpected port number %d", __func__, msg->port);
+ dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
goto exit;
}
port = serial->port[msg->port];
@@ -551,24 +412,18 @@ static void usa26_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (old_dcd_state != p_priv->dcd_state) {
- tty = tty_port_tty_get(&port->port);
- if (tty && !C_CLOCAL(tty))
- tty_hangup(tty);
- tty_kref_put(tty);
- }
+ if (old_dcd_state != p_priv->dcd_state)
+ tty_port_tty_hangup(&port->port, true);
/* Resubmit urb so we continue receiving */
- urb->dev = serial->dev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
exit: ;
}
static void usa26_glocont_callback(struct urb *urb)
{
- dbg("%s", __func__);
}
@@ -576,13 +431,10 @@ static void usa28_indat_callback(struct urb *urb)
{
int err;
struct usb_serial_port *port;
- struct tty_struct *tty;
unsigned char *data;
struct keyspan_port_private *p_priv;
int status = urb->status;
- dbg("%s", __func__);
-
port = urb->context;
p_priv = usb_get_serial_port_data(port);
data = urb->transfer_buffer;
@@ -592,8 +444,8 @@ static void usa28_indat_callback(struct urb *urb)
do {
if (status) {
- dbg("%s - nonzero status: %x on endpoint %d.",
- __func__, status, usb_pipeendpoint(urb->pipe));
+ dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
+ __func__, status, usb_pipeendpoint(urb->pipe));
return;
}
@@ -601,18 +453,16 @@ static void usa28_indat_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
data = urb->transfer_buffer;
- tty =tty_port_tty_get(&port->port);
- if (tty && urb->actual_length) {
- tty_insert_flip_string(tty, data, urb->actual_length);
- tty_flip_buffer_push(tty);
+ if (urb->actual_length) {
+ tty_insert_flip_string(&port->port, data,
+ urb->actual_length);
+ tty_flip_buffer_push(&port->port);
}
- tty_kref_put(tty);
/* Resubmit urb so we continue receiving */
- urb->dev = port->serial->dev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - resubmit read urb failed. (%d)",
+ dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n",
__func__, err);
p_priv->in_flip ^= 1;
@@ -622,7 +472,6 @@ static void usa28_indat_callback(struct urb *urb)
static void usa28_inack_callback(struct urb *urb)
{
- dbg("%s", __func__);
}
static void usa28_outcont_callback(struct urb *urb)
@@ -634,7 +483,7 @@ static void usa28_outcont_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg("%s - sending setup", __func__);
+ dev_dbg(&port->dev, "%s - sending setup\n", __func__);
keyspan_usa28_send_setup(port->serial, port,
p_priv->resend_cont - 1);
}
@@ -648,32 +497,26 @@ static void usa28_instat_callback(struct urb *urb)
struct usb_serial *serial;
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
- struct tty_struct *tty;
int old_dcd_state;
int status = urb->status;
serial = urb->context;
if (status) {
- dbg("%s - nonzero status: %x", __func__, status);
+ dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
return;
}
if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
- dbg("%s - bad length %d", __func__, urb->actual_length);
+ dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
goto exit;
}
- /*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__
- data[0], data[1], data[2], data[3], data[4], data[5],
- data[6], data[7], data[8], data[9], data[10], data[11]);*/
-
- /* Now do something useful with the data */
msg = (struct keyspan_usa28_portStatusMessage *)data;
/* Check port number from message and retrieve private data */
if (msg->port >= serial->num_ports) {
- dbg("%s - Unexpected port number %d", __func__, msg->port);
+ dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
goto exit;
}
port = serial->port[msg->port];
@@ -686,24 +529,18 @@ static void usa28_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if( old_dcd_state != p_priv->dcd_state && old_dcd_state) {
- tty = tty_port_tty_get(&port->port);
- if (tty && !C_CLOCAL(tty))
- tty_hangup(tty);
- tty_kref_put(tty);
- }
+ if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+ tty_port_tty_hangup(&port->port, true);
/* Resubmit urb so we continue receiving */
- urb->dev = serial->dev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
exit: ;
}
static void usa28_glocont_callback(struct urb *urb)
{
- dbg("%s", __func__);
}
@@ -714,15 +551,13 @@ static void usa49_glocont_callback(struct urb *urb)
struct keyspan_port_private *p_priv;
int i;
- dbg("%s", __func__);
-
serial = urb->context;
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg("%s - sending setup", __func__);
+ dev_dbg(&port->dev, "%s - sending setup\n", __func__);
keyspan_usa49_send_setup(serial, port,
p_priv->resend_cont - 1);
break;
@@ -743,32 +578,25 @@ static void usa49_instat_callback(struct urb *urb)
int old_dcd_state;
int status = urb->status;
- dbg("%s", __func__);
-
serial = urb->context;
if (status) {
- dbg("%s - nonzero status: %x", __func__, status);
+ dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
return;
}
if (urb->actual_length !=
sizeof(struct keyspan_usa49_portStatusMessage)) {
- dbg("%s - bad length %d", __func__, urb->actual_length);
+ dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
goto exit;
}
- /*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__,
- data[0], data[1], data[2], data[3], data[4], data[5],
- data[6], data[7], data[8], data[9], data[10]);*/
-
- /* Now do something useful with the data */
msg = (struct keyspan_usa49_portStatusMessage *)data;
/* Check port number from message and retrieve private data */
if (msg->portNumber >= serial->num_ports) {
- dbg("%s - Unexpected port number %d",
- __func__, msg->portNumber);
+ dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
+ __func__, msg->portNumber);
goto exit;
}
port = serial->port[msg->portNumber];
@@ -781,25 +609,18 @@ static void usa49_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- if (tty && !C_CLOCAL(tty))
- tty_hangup(tty);
- tty_kref_put(tty);
- }
+ if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+ tty_port_tty_hangup(&port->port, true);
/* Resubmit urb so we continue receiving */
- urb->dev = serial->dev;
-
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
exit: ;
}
static void usa49_inack_callback(struct urb *urb)
{
- dbg("%s", __func__);
}
static void usa49_indat_callback(struct urb *urb)
@@ -807,27 +628,23 @@ static void usa49_indat_callback(struct urb *urb)
int i, err;
int endpoint;
struct usb_serial_port *port;
- struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg("%s", __func__);
-
endpoint = usb_pipeendpoint(urb->pipe);
if (status) {
- dbg("%s - nonzero status: %x on endpoint %d.", __func__,
- status, endpoint);
+ dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
+ __func__, status, endpoint);
return;
}
port = urb->context;
- tty = tty_port_tty_get(&port->port);
- if (tty && urb->actual_length) {
+ if (urb->actual_length) {
/* 0x80 bit is error flag */
if ((data[0] & 0x80) == 0) {
/* no error on any byte */
- tty_insert_flip_string(tty, data + 1,
+ tty_insert_flip_string(&port->port, data + 1,
urb->actual_length - 1);
} else {
/* some bytes had errors, every byte has status */
@@ -840,18 +657,17 @@ static void usa49_indat_callback(struct urb *urb)
if (stat & RXERROR_PARITY)
flag |= TTY_PARITY;
/* XXX should handle break (0x10) */
- tty_insert_flip_char(tty, data[i+1], flag);
+ tty_insert_flip_char(&port->port, data[i+1],
+ flag);
}
}
- tty_flip_buffer_push(tty);
+ tty_flip_buffer_push(&port->port);
}
- tty_kref_put(tty);
/* Resubmit urb so we continue receiving */
- urb->dev = port->serial->dev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
}
static void usa49wg_indat_callback(struct urb *urb)
@@ -859,16 +675,13 @@ static void usa49wg_indat_callback(struct urb *urb)
int i, len, x, err;
struct usb_serial *serial;
struct usb_serial_port *port;
- struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg("%s", __func__);
-
serial = urb->context;
if (status) {
- dbg("%s - nonzero status: %x", __func__, status);
+ dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
return;
}
@@ -876,60 +689,56 @@ static void usa49wg_indat_callback(struct urb *urb)
i = 0;
len = 0;
- if (urb->actual_length) {
- while (i < urb->actual_length) {
+ while (i < urb->actual_length) {
- /* Check port number from message*/
- if (data[i] >= serial->num_ports) {
- dbg("%s - Unexpected port number %d",
- __func__, data[i]);
- return;
- }
- port = serial->port[data[i++]];
- tty = tty_port_tty_get(&port->port);
- len = data[i++];
+ /* Check port number from message */
+ if (data[i] >= serial->num_ports) {
+ dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
+ __func__, data[i]);
+ return;
+ }
+ port = serial->port[data[i++]];
+ len = data[i++];
- /* 0x80 bit is error flag */
- if ((data[i] & 0x80) == 0) {
- /* no error on any byte */
- i++;
- for (x = 1; x < len ; ++x)
- tty_insert_flip_char(tty, data[i++], 0);
- } else {
- /*
- * some bytes had errors, every byte has status
- */
- for (x = 0; x + 1 < len; x += 2) {
- int stat = data[i], flag = 0;
- if (stat & RXERROR_OVERRUN)
- flag |= TTY_OVERRUN;
- if (stat & RXERROR_FRAMING)
- flag |= TTY_FRAME;
- if (stat & RXERROR_PARITY)
- flag |= TTY_PARITY;
- /* XXX should handle break (0x10) */
- tty_insert_flip_char(tty,
- data[i+1], flag);
- i += 2;
- }
+ /* 0x80 bit is error flag */
+ if ((data[i] & 0x80) == 0) {
+ /* no error on any byte */
+ i++;
+ for (x = 1; x < len && i < urb->actual_length; ++x)
+ tty_insert_flip_char(&port->port,
+ data[i++], 0);
+ } else {
+ /*
+ * some bytes had errors, every byte has status
+ */
+ for (x = 0; x + 1 < len &&
+ i + 1 < urb->actual_length; x += 2) {
+ int stat = data[i], flag = 0;
+
+ if (stat & RXERROR_OVERRUN)
+ flag |= TTY_OVERRUN;
+ if (stat & RXERROR_FRAMING)
+ flag |= TTY_FRAME;
+ if (stat & RXERROR_PARITY)
+ flag |= TTY_PARITY;
+ /* XXX should handle break (0x10) */
+ tty_insert_flip_char(&port->port, data[i+1],
+ flag);
+ i += 2;
}
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
}
+ tty_flip_buffer_push(&port->port);
}
/* Resubmit urb so we continue receiving */
- urb->dev = serial->dev;
-
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
}
/* not used, usa-49 doesn't have per-port control endpoints */
static void usa49_outcont_callback(struct urb *urb)
{
- dbg("%s", __func__);
}
static void usa90_indat_callback(struct urb *urb)
@@ -938,16 +747,13 @@ static void usa90_indat_callback(struct urb *urb)
int endpoint;
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
- struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg("%s", __func__);
-
endpoint = usb_pipeendpoint(urb->pipe);
if (status) {
- dbg("%s - nonzero status: %x on endpoint %d.",
+ dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
__func__, status, endpoint);
return;
}
@@ -956,12 +762,12 @@ static void usa90_indat_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
if (urb->actual_length) {
- tty = tty_port_tty_get(&port->port);
/* if current mode is DMA, looks like usa28 format
otherwise looks like usa26 data format */
if (p_priv->baud > 57600)
- tty_insert_flip_string(tty, data, urb->actual_length);
+ tty_insert_flip_string(&port->port, data,
+ urb->actual_length);
else {
/* 0x80 bit is error flag */
if ((data[0] & 0x80) == 0) {
@@ -972,11 +778,11 @@ static void usa90_indat_callback(struct urb *urb)
else
err = 0;
for (i = 1; i < urb->actual_length ; ++i)
- tty_insert_flip_char(tty, data[i],
- err);
+ tty_insert_flip_char(&port->port,
+ data[i], err);
} else {
/* some bytes had errors, every byte has status */
- dbg("%s - RX error!!!!", __func__);
+ dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
for (i = 0; i + 1 < urb->actual_length; i += 2) {
int stat = data[i], flag = 0;
if (stat & RXERROR_OVERRUN)
@@ -986,20 +792,18 @@ static void usa90_indat_callback(struct urb *urb)
if (stat & RXERROR_PARITY)
flag |= TTY_PARITY;
/* XXX should handle break (0x10) */
- tty_insert_flip_char(tty, data[i+1],
- flag);
+ tty_insert_flip_char(&port->port,
+ data[i+1], flag);
}
}
}
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
+ tty_flip_buffer_push(&port->port);
}
/* Resubmit urb so we continue receiving */
- urb->dev = port->serial->dev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
}
@@ -1010,18 +814,17 @@ static void usa90_instat_callback(struct urb *urb)
struct usb_serial *serial;
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
- struct tty_struct *tty;
int old_dcd_state, err;
int status = urb->status;
serial = urb->context;
if (status) {
- dbg("%s - nonzero status: %x", __func__, status);
+ dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
return;
}
if (urb->actual_length < 14) {
- dbg("%s - %d byte report??", __func__, urb->actual_length);
+ dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
goto exit;
}
@@ -1039,18 +842,13 @@ static void usa90_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
- tty = tty_port_tty_get(&port->port);
- if (tty && !C_CLOCAL(tty))
- tty_hangup(tty);
- tty_kref_put(tty);
- }
+ if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+ tty_port_tty_hangup(&port->port, true);
/* Resubmit urb so we continue receiving */
- urb->dev = serial->dev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
exit:
;
}
@@ -1064,7 +862,7 @@ static void usa90_outcont_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg("%s - sending setup", __func__);
+ dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__);
keyspan_usa90_send_setup(port->serial, port,
p_priv->resend_cont - 1);
}
@@ -1082,18 +880,16 @@ static void usa67_instat_callback(struct urb *urb)
int old_dcd_state;
int status = urb->status;
- dbg("%s", __func__);
-
serial = urb->context;
if (status) {
- dbg("%s - nonzero status: %x", __func__, status);
+ dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
return;
}
if (urb->actual_length !=
sizeof(struct keyspan_usa67_portStatusMessage)) {
- dbg("%s - bad length %d", __func__, urb->actual_length);
+ dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
return;
}
@@ -1103,7 +899,7 @@ static void usa67_instat_callback(struct urb *urb)
/* Check port number from message and retrieve private data */
if (msg->port >= serial->num_ports) {
- dbg("%s - Unexpected port number %d", __func__, msg->port);
+ dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
return;
}
@@ -1115,18 +911,13 @@ static void usa67_instat_callback(struct urb *urb)
p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
- if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- if (tty && !C_CLOCAL(tty))
- tty_hangup(tty);
- tty_kref_put(tty);
- }
+ if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+ tty_port_tty_hangup(&port->port, true);
/* Resubmit urb so we continue receiving */
- urb->dev = serial->dev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
}
static void usa67_glocont_callback(struct urb *urb)
@@ -1136,15 +927,13 @@ static void usa67_glocont_callback(struct urb *urb)
struct keyspan_port_private *p_priv;
int i;
- dbg("%s", __func__);
-
serial = urb->context;
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg("%s - sending setup", __func__);
+ dev_dbg(&port->dev, "%s - sending setup\n", __func__);
keyspan_usa67_send_setup(serial, port,
p_priv->resend_cont - 1);
break;
@@ -1161,7 +950,6 @@ static int keyspan_write_room(struct tty_struct *tty)
int data_len;
struct urb *this_urb;
- dbg("%s", __func__);
p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
@@ -1192,20 +980,15 @@ static int keyspan_write_room(struct tty_struct *tty)
static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct keyspan_port_private *p_priv;
- struct keyspan_serial_private *s_priv;
- struct usb_serial *serial = port->serial;
const struct keyspan_device_details *d_details;
int i, err;
int baud_rate, device_port;
struct urb *urb;
unsigned int cflag = 0;
- s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
- dbg("%s - port%d.", __func__, port->number);
-
/* Set some sane defaults */
p_priv->rts_state = 1;
p_priv->dtr_state = 1;
@@ -1223,15 +1006,13 @@ static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
urb = p_priv->in_urbs[i];
if (urb == NULL)
continue;
- urb->dev = serial->dev;
/* make sure endpoint data toggle is synchronized
with the device */
usb_clear_halt(urb->dev, urb->pipe);
err = usb_submit_urb(urb, GFP_KERNEL);
if (err != 0)
- dbg("%s - submit urb %d failed (%d)",
- __func__, i, err);
+ dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err);
}
/* Reset low level data toggle on out endpoints */
@@ -1239,7 +1020,6 @@ static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
urb = p_priv->out_urbs[i];
if (urb == NULL)
continue;
- urb->dev = serial->dev;
/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
usb_pipeout(urb->pipe), 0); */
}
@@ -1247,22 +1027,22 @@ static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
/* get the terminal config for the setup message now so we don't
* need to send 2 of them */
- device_port = port->number - port->serial->minor;
+ device_port = port->port_number;
if (tty) {
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
/* Baud rate calculation takes baud rate as an integer
so other rates can be generated if desired. */
baud_rate = tty_get_baud_rate(tty);
/* If no match or invalid, leave as default */
if (baud_rate >= 0
- && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
+ && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
p_priv->baud = baud_rate;
}
}
/* set CTS/RTS handshake etc. */
p_priv->cflag = cflag;
- p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
+ p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
keyspan_send_setup(port, 1);
/* mdelay(100); */
@@ -1289,57 +1069,39 @@ static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
static void keyspan_close(struct usb_serial_port *port)
{
int i;
- struct usb_serial *serial = port->serial;
- struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
- dbg("%s", __func__);
- s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
p_priv->rts_state = 0;
p_priv->dtr_state = 0;
- if (serial->dev) {
- keyspan_send_setup(port, 2);
- /* pilot-xfer seems to work best with this delay */
- mdelay(100);
- /* keyspan_set_termios(port, NULL); */
- }
-
- /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
- dbg("%s - urb in progress", __func__);
- }*/
+ keyspan_send_setup(port, 2);
+ /* pilot-xfer seems to work best with this delay */
+ mdelay(100);
p_priv->out_flip = 0;
p_priv->in_flip = 0;
- if (serial->dev) {
- /* Stop reading/writing urbs */
- stop_urb(p_priv->inack_urb);
- /* stop_urb(p_priv->outcont_urb); */
- for (i = 0; i < 2; i++) {
- stop_urb(p_priv->in_urbs[i]);
- stop_urb(p_priv->out_urbs[i]);
- }
+ stop_urb(p_priv->inack_urb);
+ for (i = 0; i < 2; i++) {
+ stop_urb(p_priv->in_urbs[i]);
+ stop_urb(p_priv->out_urbs[i]);
}
}
/* download the firmware to a pre-renumeration device */
static int keyspan_fake_startup(struct usb_serial *serial)
{
- int response;
- const struct ihex_binrec *record;
- char *fw_name;
- const struct firmware *fw;
+ char *fw_name;
- dbg("Keyspan startup version %04x product %04x",
- le16_to_cpu(serial->dev->descriptor.bcdDevice),
- le16_to_cpu(serial->dev->descriptor.idProduct));
+ dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n",
+ le16_to_cpu(serial->dev->descriptor.bcdDevice),
+ le16_to_cpu(serial->dev->descriptor.idProduct));
if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
!= 0x8000) {
- dbg("Firmware already loaded. Quitting.");
+ dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n");
return 1;
}
@@ -1399,34 +1161,16 @@ static int keyspan_fake_startup(struct usb_serial *serial)
return 1;
}
- if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) {
- dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name);
- return(1);
- }
-
- dbg("Uploading Keyspan %s firmware.", fw_name);
-
- /* download the firmware image */
- response = ezusb_set_reset(serial, 1);
-
- record = (const struct ihex_binrec *)fw->data;
+ dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name);
- while (record) {
- response = ezusb_writememory(serial, be32_to_cpu(record->addr),
- (unsigned char *)record->data,
- be16_to_cpu(record->len), 0xa0);
- if (response < 0) {
- dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan firmware (%d %04X %p %d)\n",
- response, be32_to_cpu(record->addr),
- record->data, be16_to_cpu(record->len));
- break;
- }
- record = ihex_next_binrec(record);
+ if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
+ dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
+ fw_name);
+ return -ENOENT;
}
- release_firmware(fw);
- /* bring device out of reset. Renumeration will occur in a
- moment and the new device will bind to the real driver */
- response = ezusb_set_reset(serial, 0);
+
+ /* after downloading firmware Renumeration will occur in a
+ moment and the new device will bind to the real driver */
/* we don't want this device to have a driver assigned to it. */
return 1;
@@ -1462,12 +1206,10 @@ static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
if (endpoint == -1)
return NULL; /* endpoint not needed */
- dbg("%s - alloc for endpoint %d.", __func__, endpoint);
+ dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d.\n", __func__, endpoint);
urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
- if (urb == NULL) {
- dbg("%s - alloc for endpoint %d failed.", __func__, endpoint);
+ if (!urb)
return NULL;
- }
if (endpoint == 0) {
/* control EP filled in when used */
@@ -1498,7 +1240,7 @@ static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
return NULL;
}
- dbg("%s - using urb %p for %s endpoint %x",
+ dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n",
__func__, urb, ep_type_name, endpoint);
return urb;
}
@@ -1558,15 +1300,9 @@ static struct callbacks {
data in device_details */
static void keyspan_setup_urbs(struct usb_serial *serial)
{
- int i, j;
struct keyspan_serial_private *s_priv;
const struct keyspan_device_details *d_details;
- struct usb_serial_port *port;
- struct keyspan_port_private *p_priv;
struct callbacks *cback;
- int endp;
-
- dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
d_details = s_priv->device_details;
@@ -1590,56 +1326,18 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
(serial, d_details->glocont_endpoint, USB_DIR_OUT,
serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
cback->glocont_callback);
-
- /* Setup endpoints for each port specific thing */
- for (i = 0; i < d_details->num_ports; i++) {
- port = serial->port[i];
- p_priv = usb_get_serial_port_data(port);
-
- /* Do indat endpoints first, once for each flip */
- endp = d_details->indat_endpoints[i];
- for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
- p_priv->in_urbs[j] = keyspan_setup_urb
- (serial, endp, USB_DIR_IN, port,
- p_priv->in_buffer[j], 64,
- cback->indat_callback);
- }
- for (; j < 2; ++j)
- p_priv->in_urbs[j] = NULL;
-
- /* outdat endpoints also have flip */
- endp = d_details->outdat_endpoints[i];
- for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
- p_priv->out_urbs[j] = keyspan_setup_urb
- (serial, endp, USB_DIR_OUT, port,
- p_priv->out_buffer[j], 64,
- cback->outdat_callback);
- }
- for (; j < 2; ++j)
- p_priv->out_urbs[j] = NULL;
-
- /* inack endpoint */
- p_priv->inack_urb = keyspan_setup_urb
- (serial, d_details->inack_endpoints[i], USB_DIR_IN,
- port, p_priv->inack_buffer, 1, cback->inack_callback);
-
- /* outcont endpoint */
- p_priv->outcont_urb = keyspan_setup_urb
- (serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
- port, p_priv->outcont_buffer, 64,
- cback->outcont_callback);
- }
}
/* usa19 function doesn't require prescaler */
-static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
+ u32 baud_rate, u32 baudclk, u8 *rate_hi,
u8 *rate_low, u8 *prescaler, int portnum)
{
u32 b16, /* baud rate times 16 (actual rate used internally) */
div, /* divisor */
cnt; /* inverse of divisor (programmed into 8051) */
- dbg("%s - %d.", __func__, baud_rate);
+ dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
/* prevent divide by zero... */
b16 = baud_rate * 16L;
@@ -1666,19 +1364,20 @@ static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
if (rate_hi)
*rate_hi = (u8) ((cnt >> 8) & 0xff);
if (rate_low && rate_hi)
- dbg("%s - %d %02x %02x.",
+ dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
__func__, baud_rate, *rate_hi, *rate_low);
return KEYSPAN_BAUD_RATE_OK;
}
/* usa19hs function doesn't require prescaler */
-static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
- u8 *rate_low, u8 *prescaler, int portnum)
+static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
+ u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ u8 *rate_low, u8 *prescaler, int portnum)
{
u32 b16, /* baud rate times 16 (actual rate used internally) */
div; /* divisor */
- dbg("%s - %d.", __func__, baud_rate);
+ dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
/* prevent divide by zero... */
b16 = baud_rate * 16L;
@@ -1701,13 +1400,14 @@ static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
*rate_hi = (u8) ((div >> 8) & 0xff);
if (rate_low && rate_hi)
- dbg("%s - %d %02x %02x.",
+ dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
__func__, baud_rate, *rate_hi, *rate_low);
return KEYSPAN_BAUD_RATE_OK;
}
-static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
+ u32 baud_rate, u32 baudclk, u8 *rate_hi,
u8 *rate_low, u8 *prescaler, int portnum)
{
u32 b16, /* baud rate times 16 (actual rate used internally) */
@@ -1719,7 +1419,7 @@ static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
u8 best_prescaler;
int i;
- dbg("%s - %d.", __func__, baud_rate);
+ dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
/* prevent divide by zero */
b16 = baud_rate * 16L;
@@ -1764,20 +1464,21 @@ static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
*rate_hi = (u8) ((div >> 8) & 0xff);
if (prescaler) {
*prescaler = best_prescaler;
- /* dbg("%s - %d %d", __func__, *prescaler, div); */
+ /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */
}
return KEYSPAN_BAUD_RATE_OK;
}
/* USA-28 supports different maximum baud rates on each port */
-static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
- u8 *rate_low, u8 *prescaler, int portnum)
+static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
+ u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ u8 *rate_low, u8 *prescaler, int portnum)
{
u32 b16, /* baud rate times 16 (actual rate used internally) */
div, /* divisor */
cnt; /* inverse of divisor (programmed into 8051) */
- dbg("%s - %d.", __func__, baud_rate);
+ dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
/* prevent divide by zero */
b16 = baud_rate * 16L;
@@ -1810,7 +1511,7 @@ static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
*rate_low = (u8) (cnt & 0xff);
if (rate_hi)
*rate_hi = (u8) ((cnt >> 8) & 0xff);
- dbg("%s - %d OK.", __func__, baud_rate);
+ dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate);
return KEYSPAN_BAUD_RATE_OK;
}
@@ -1822,34 +1523,32 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
- int outcont_urb;
struct urb *this_urb;
int device_port, err;
- dbg("%s reset=%d", __func__, reset_port);
+ dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port);
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
- device_port = port->number - port->serial->minor;
+ device_port = port->port_number;
- outcont_urb = d_details->outcont_endpoints[port->number];
this_urb = p_priv->outcont_urb;
- dbg("%s - endpoint %d", __func__, usb_pipeendpoint(this_urb->pipe));
-
/* Make sure we have an urb then send the message */
if (this_urb == NULL) {
- dbg("%s - oops no urb.", __func__);
+ dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
return -1;
}
+ dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe));
+
/* Save reset port val for resend.
Don't overwrite resend for open/close condition. */
if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- /* dbg("%s - already writing", __func__); */
+ /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
mdelay(5);
return -1;
}
@@ -1860,11 +1559,11 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
if (p_priv->old_baud != p_priv->baud) {
p_priv->old_baud = p_priv->baud;
msg.setClocking = 0xff;
- if (d_details->calculate_baud_rate
- (p_priv->baud, d_details->baudclk, &msg.baudHi,
- &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
- dbg("%s - Invalid baud rate %d requested, using 9600.",
- __func__, p_priv->baud);
+ if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
+ &msg.baudHi, &msg.baudLo, &msg.prescaler,
+ device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+ dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
+ __func__, p_priv->baud);
msg.baudLo = 0;
msg.baudHi = 125; /* Values for 9600 baud */
msg.prescaler = 10;
@@ -1872,7 +1571,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
msg.setPrescaler = 0xff;
}
- msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
+ msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
switch (p_priv->cflag & CSIZE) {
case CS5:
msg.lcr |= USA_DATABITS_5;
@@ -1889,7 +1588,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
}
if (p_priv->cflag & PARENB) {
/* note USA_PARITY_NONE == 0 */
- msg.lcr |= (p_priv->cflag & PARODD)?
+ msg.lcr |= (p_priv->cflag & PARODD) ?
USA_PARITY_ODD : USA_PARITY_EVEN;
}
msg.setLcr = 0xff;
@@ -1956,18 +1655,9 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
/* send the data out the device on control endpoint */
this_urb->transfer_buffer_length = sizeof(msg);
- this_urb->dev = serial->dev;
err = usb_submit_urb(this_urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
-#if 0
- else {
- dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__
- outcont_urb, this_urb->transfer_buffer_length,
- usb_pipeendpoint(this_urb->pipe));
- }
-#endif
-
+ dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
return 0;
}
@@ -1982,17 +1672,15 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
struct urb *this_urb;
int device_port, err;
- dbg("%s", __func__);
-
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
- device_port = port->number - port->serial->minor;
+ device_port = port->port_number;
/* only do something if we have a bulk out endpoint */
this_urb = p_priv->outcont_urb;
if (this_urb == NULL) {
- dbg("%s - oops no urb.", __func__);
+ dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
return -1;
}
@@ -2001,7 +1689,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- dbg("%s already writing", __func__);
+ dev_dbg(&port->dev, "%s already writing\n", __func__);
mdelay(5);
return -1;
}
@@ -2009,9 +1697,10 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
msg.setBaudRate = 1;
- if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
- &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
- dbg("%s - Invalid baud rate requested %d.",
+ if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
+ &msg.baudHi, &msg.baudLo, NULL,
+ device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+ dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n",
__func__, p_priv->baud);
msg.baudLo = 0xff;
msg.baudHi = 0xb2; /* Values for 9600 baud */
@@ -2084,16 +1773,9 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
/* send the data out the device on control endpoint */
this_urb->transfer_buffer_length = sizeof(msg);
- this_urb->dev = serial->dev;
err = usb_submit_urb(this_urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - usb_submit_urb(setup) failed", __func__);
-#if 0
- else {
- dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__,
- this_urb->transfer_buffer_length);
- }
-#endif
+ dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__);
return 0;
}
@@ -2110,8 +1792,6 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
struct urb *this_urb;
int err, device_port;
- dbg("%s", __func__);
-
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
@@ -2119,43 +1799,41 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
this_urb = s_priv->glocont_urb;
/* Work out which port within the device is being setup */
- device_port = port->number - port->serial->minor;
-
- dbg("%s - endpoint %d port %d (%d)",
- __func__, usb_pipeendpoint(this_urb->pipe),
- port->number, device_port);
+ device_port = port->port_number;
- /* Make sure we have an urb then send the message */
+ /* Make sure we have an urb then send the message */
if (this_urb == NULL) {
- dbg("%s - oops no urb for port %d.", __func__, port->number);
+ dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
return -1;
}
+ dev_dbg(&port->dev, "%s - endpoint %d (%d)\n",
+ __func__, usb_pipeendpoint(this_urb->pipe), device_port);
+
/* Save reset port val for resend.
Don't overwrite resend for open/close condition. */
if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- /* dbg("%s - already writing", __func__); */
+ /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
mdelay(5);
return -1;
}
memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
- /*msg.portNumber = port->number;*/
msg.portNumber = device_port;
/* Only set baud rate if it's changed */
if (p_priv->old_baud != p_priv->baud) {
p_priv->old_baud = p_priv->baud;
msg.setClocking = 0xff;
- if (d_details->calculate_baud_rate
- (p_priv->baud, d_details->baudclk, &msg.baudHi,
- &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
- dbg("%s - Invalid baud rate %d requested, using 9600.",
- __func__, p_priv->baud);
+ if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
+ &msg.baudHi, &msg.baudLo, &msg.prescaler,
+ device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+ dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
+ __func__, p_priv->baud);
msg.baudLo = 0;
msg.baudHi = 125; /* Values for 9600 baud */
msg.prescaler = 10;
@@ -2163,7 +1841,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
/* msg.setPrescaler = 0xff; */
}
- msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
+ msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
switch (p_priv->cflag & CSIZE) {
case CS5:
msg.lcr |= USA_DATABITS_5;
@@ -2180,7 +1858,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
}
if (p_priv->cflag & PARENB) {
/* note USA_PARITY_NONE == 0 */
- msg.lcr |= (p_priv->cflag & PARODD)?
+ msg.lcr |= (p_priv->cflag & PARODD) ?
USA_PARITY_ODD : USA_PARITY_EVEN;
}
msg.setLcr = 0xff;
@@ -2271,19 +1949,10 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
/* send the data out the device on control endpoint */
this_urb->transfer_buffer_length = sizeof(msg);
-
- this_urb->dev = serial->dev;
}
err = usb_submit_urb(this_urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
-#if 0
- else {
- dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__,
- outcont_urb, this_urb->transfer_buffer_length,
- usb_pipeendpoint(this_urb->pipe));
- }
-#endif
+ dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
return 0;
}
@@ -2300,8 +1969,6 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
int err;
u8 prescaler;
- dbg("%s", __func__);
-
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
@@ -2309,7 +1976,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
/* only do something if we have a bulk out endpoint */
this_urb = p_priv->outcont_urb;
if (this_urb == NULL) {
- dbg("%s - oops no urb.", __func__);
+ dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
return -1;
}
@@ -2318,7 +1985,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- dbg("%s already writing", __func__);
+ dev_dbg(&port->dev, "%s already writing\n", __func__);
mdelay(5);
return -1;
}
@@ -2329,13 +1996,12 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
if (p_priv->old_baud != p_priv->baud) {
p_priv->old_baud = p_priv->baud;
msg.setClocking = 0x01;
- if (d_details->calculate_baud_rate
- (p_priv->baud, d_details->baudclk, &msg.baudHi,
- &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
- dbg("%s - Invalid baud rate %d requested, using 9600.",
- __func__, p_priv->baud);
+ if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
+ &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
+ dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
+ __func__, p_priv->baud);
p_priv->baud = 9600;
- d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
+ d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
&msg.baudHi, &msg.baudLo, &prescaler, 0);
}
msg.setRxMode = 1;
@@ -2351,7 +2017,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
msg.txMode = TXMODE_BYHAND;
}
- msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
+ msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
switch (p_priv->cflag & CSIZE) {
case CS5:
msg.lcr |= USA_DATABITS_5;
@@ -2368,7 +2034,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
}
if (p_priv->cflag & PARENB) {
/* note USA_PARITY_NONE == 0 */
- msg.lcr |= (p_priv->cflag & PARODD)?
+ msg.lcr |= (p_priv->cflag & PARODD) ?
USA_PARITY_ODD : USA_PARITY_EVEN;
}
if (p_priv->old_cflag != p_priv->cflag) {
@@ -2415,10 +2081,9 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
/* send the data out the device on control endpoint */
this_urb->transfer_buffer_length = sizeof(msg);
- this_urb->dev = serial->dev;
err = usb_submit_urb(this_urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
+ dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
return 0;
}
@@ -2433,8 +2098,6 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
struct urb *this_urb;
int err, device_port;
- dbg("%s", __func__);
-
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
@@ -2442,12 +2105,11 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
this_urb = s_priv->glocont_urb;
/* Work out which port within the device is being setup */
- device_port = port->number - port->serial->minor;
+ device_port = port->port_number;
/* Make sure we have an urb then send the message */
if (this_urb == NULL) {
- dbg("%s - oops no urb for port %d.", __func__,
- port->number);
+ dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
return -1;
}
@@ -2456,7 +2118,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- /* dbg("%s - already writing", __func__); */
+ /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
mdelay(5);
return -1;
}
@@ -2469,11 +2131,11 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
if (p_priv->old_baud != p_priv->baud) {
p_priv->old_baud = p_priv->baud;
msg.setClocking = 0xff;
- if (d_details->calculate_baud_rate
- (p_priv->baud, d_details->baudclk, &msg.baudHi,
- &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
- dbg("%s - Invalid baud rate %d requested, using 9600.",
- __func__, p_priv->baud);
+ if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
+ &msg.baudHi, &msg.baudLo, &msg.prescaler,
+ device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+ dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
+ __func__, p_priv->baud);
msg.baudLo = 0;
msg.baudHi = 125; /* Values for 9600 baud */
msg.prescaler = 10;
@@ -2498,7 +2160,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
}
if (p_priv->cflag & PARENB) {
/* note USA_PARITY_NONE == 0 */
- msg.lcr |= (p_priv->cflag & PARODD)?
+ msg.lcr |= (p_priv->cflag & PARODD) ?
USA_PARITY_ODD : USA_PARITY_EVEN;
}
msg.setLcr = 0xff;
@@ -2561,12 +2223,10 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
/* send the data out the device on control endpoint */
this_urb->transfer_buffer_length = sizeof(msg);
- this_urb->dev = serial->dev;
err = usb_submit_urb(this_urb, GFP_ATOMIC);
if (err != 0)
- dbg("%s - usb_submit_urb(setup) failed (%d)", __func__,
- err);
+ dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
return 0;
}
@@ -2576,8 +2236,6 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
struct keyspan_serial_private *s_priv;
const struct keyspan_device_details *d_details;
- dbg("%s", __func__);
-
s_priv = usb_get_serial_data(serial);
d_details = s_priv->device_details;
@@ -2606,13 +2264,9 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
static int keyspan_startup(struct usb_serial *serial)
{
int i, err;
- struct usb_serial_port *port;
struct keyspan_serial_private *s_priv;
- struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
- dbg("%s", __func__);
-
for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
if (d_details->product_id ==
le16_to_cpu(serial->dev->descriptor.idProduct))
@@ -2620,114 +2274,216 @@ static int keyspan_startup(struct usb_serial *serial)
if (d_details == NULL) {
dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
__func__, le16_to_cpu(serial->dev->descriptor.idProduct));
- return 1;
+ return -ENODEV;
}
/* Setup private data for serial driver */
s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
- if (!s_priv) {
- dbg("%s - kmalloc for keyspan_serial_private failed.",
- __func__);
+ if (!s_priv)
return -ENOMEM;
- }
+
+ s_priv->instat_buf = kzalloc(INSTAT_BUFLEN, GFP_KERNEL);
+ if (!s_priv->instat_buf)
+ goto err_instat_buf;
+
+ s_priv->indat_buf = kzalloc(INDAT49W_BUFLEN, GFP_KERNEL);
+ if (!s_priv->indat_buf)
+ goto err_indat_buf;
+
+ s_priv->glocont_buf = kzalloc(GLOCONT_BUFLEN, GFP_KERNEL);
+ if (!s_priv->glocont_buf)
+ goto err_glocont_buf;
+
+ s_priv->ctrl_buf = kzalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
+ if (!s_priv->ctrl_buf)
+ goto err_ctrl_buf;
s_priv->device_details = d_details;
usb_set_serial_data(serial, s_priv);
- /* Now setup per port private data */
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- p_priv = kzalloc(sizeof(struct keyspan_port_private),
- GFP_KERNEL);
- if (!p_priv) {
- dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i);
- return 1;
- }
- p_priv->device_details = d_details;
- usb_set_serial_port_data(port, p_priv);
- }
-
keyspan_setup_urbs(serial);
if (s_priv->instat_urb != NULL) {
- s_priv->instat_urb->dev = serial->dev;
err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
if (err != 0)
- dbg("%s - submit instat urb failed %d", __func__,
- err);
+ dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err);
}
if (s_priv->indat_urb != NULL) {
- s_priv->indat_urb->dev = serial->dev;
err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
if (err != 0)
- dbg("%s - submit indat urb failed %d", __func__,
- err);
+ dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err);
}
return 0;
+
+err_ctrl_buf:
+ kfree(s_priv->glocont_buf);
+err_glocont_buf:
+ kfree(s_priv->indat_buf);
+err_indat_buf:
+ kfree(s_priv->instat_buf);
+err_instat_buf:
+ kfree(s_priv);
+
+ return -ENOMEM;
}
static void keyspan_disconnect(struct usb_serial *serial)
{
- int i, j;
- struct usb_serial_port *port;
- struct keyspan_serial_private *s_priv;
- struct keyspan_port_private *p_priv;
-
- dbg("%s", __func__);
+ struct keyspan_serial_private *s_priv;
s_priv = usb_get_serial_data(serial);
- /* Stop reading/writing urbs */
stop_urb(s_priv->instat_urb);
stop_urb(s_priv->glocont_urb);
stop_urb(s_priv->indat_urb);
- for (i = 0; i < serial->num_ports; ++i) {
- port = serial->port[i];
- p_priv = usb_get_serial_port_data(port);
- stop_urb(p_priv->inack_urb);
- stop_urb(p_priv->outcont_urb);
- for (j = 0; j < 2; j++) {
- stop_urb(p_priv->in_urbs[j]);
- stop_urb(p_priv->out_urbs[j]);
- }
- }
+}
+
+static void keyspan_release(struct usb_serial *serial)
+{
+ struct keyspan_serial_private *s_priv;
+
+ s_priv = usb_get_serial_data(serial);
- /* Now free them */
usb_free_urb(s_priv->instat_urb);
usb_free_urb(s_priv->indat_urb);
usb_free_urb(s_priv->glocont_urb);
- for (i = 0; i < serial->num_ports; ++i) {
- port = serial->port[i];
- p_priv = usb_get_serial_port_data(port);
- usb_free_urb(p_priv->inack_urb);
- usb_free_urb(p_priv->outcont_urb);
- for (j = 0; j < 2; j++) {
- usb_free_urb(p_priv->in_urbs[j]);
- usb_free_urb(p_priv->out_urbs[j]);
- }
- }
+
+ kfree(s_priv->ctrl_buf);
+ kfree(s_priv->glocont_buf);
+ kfree(s_priv->indat_buf);
+ kfree(s_priv->instat_buf);
+
+ kfree(s_priv);
}
-static void keyspan_release(struct usb_serial *serial)
+static int keyspan_port_probe(struct usb_serial_port *port)
{
- int i;
- struct usb_serial_port *port;
- struct keyspan_serial_private *s_priv;
-
- dbg("%s", __func__);
+ struct usb_serial *serial = port->serial;
+ struct keyspan_serial_private *s_priv;
+ struct keyspan_port_private *p_priv;
+ const struct keyspan_device_details *d_details;
+ struct callbacks *cback;
+ int endp;
+ int port_num;
+ int i;
s_priv = usb_get_serial_data(serial);
+ d_details = s_priv->device_details;
- /* dbg("Freeing serial->private."); */
- kfree(s_priv);
+ p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
+ if (!p_priv)
+ return -ENOMEM;
- /* dbg("Freeing port->private."); */
- /* Now free per port private data */
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- kfree(usb_get_serial_port_data(port));
+ for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) {
+ p_priv->in_buffer[i] = kzalloc(IN_BUFLEN, GFP_KERNEL);
+ if (!p_priv->in_buffer[i])
+ goto err_in_buffer;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i) {
+ p_priv->out_buffer[i] = kzalloc(OUT_BUFLEN, GFP_KERNEL);
+ if (!p_priv->out_buffer[i])
+ goto err_out_buffer;
+ }
+
+ p_priv->inack_buffer = kzalloc(INACK_BUFLEN, GFP_KERNEL);
+ if (!p_priv->inack_buffer)
+ goto err_inack_buffer;
+
+ p_priv->outcont_buffer = kzalloc(OUTCONT_BUFLEN, GFP_KERNEL);
+ if (!p_priv->outcont_buffer)
+ goto err_outcont_buffer;
+
+ p_priv->device_details = d_details;
+
+ /* Setup values for the various callback routines */
+ cback = &keyspan_callbacks[d_details->msg_format];
+
+ port_num = port->port_number;
+
+ /* Do indat endpoints first, once for each flip */
+ endp = d_details->indat_endpoints[port_num];
+ for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
+ p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
+ USB_DIR_IN, port,
+ p_priv->in_buffer[i],
+ IN_BUFLEN,
+ cback->indat_callback);
+ }
+ /* outdat endpoints also have flip */
+ endp = d_details->outdat_endpoints[port_num];
+ for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
+ p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
+ USB_DIR_OUT, port,
+ p_priv->out_buffer[i],
+ OUT_BUFLEN,
+ cback->outdat_callback);
+ }
+ /* inack endpoint */
+ p_priv->inack_urb = keyspan_setup_urb(serial,
+ d_details->inack_endpoints[port_num],
+ USB_DIR_IN, port,
+ p_priv->inack_buffer,
+ INACK_BUFLEN,
+ cback->inack_callback);
+ /* outcont endpoint */
+ p_priv->outcont_urb = keyspan_setup_urb(serial,
+ d_details->outcont_endpoints[port_num],
+ USB_DIR_OUT, port,
+ p_priv->outcont_buffer,
+ OUTCONT_BUFLEN,
+ cback->outcont_callback);
+
+ usb_set_serial_port_data(port, p_priv);
+
+ return 0;
+
+err_outcont_buffer:
+ kfree(p_priv->inack_buffer);
+err_inack_buffer:
+ for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
+ kfree(p_priv->out_buffer[i]);
+err_out_buffer:
+ for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
+ kfree(p_priv->in_buffer[i]);
+err_in_buffer:
+ kfree(p_priv);
+
+ return -ENOMEM;
+}
+
+static int keyspan_port_remove(struct usb_serial_port *port)
+{
+ struct keyspan_port_private *p_priv;
+ int i;
+
+ p_priv = usb_get_serial_port_data(port);
+
+ stop_urb(p_priv->inack_urb);
+ stop_urb(p_priv->outcont_urb);
+ for (i = 0; i < 2; i++) {
+ stop_urb(p_priv->in_urbs[i]);
+ stop_urb(p_priv->out_urbs[i]);
+ }
+
+ usb_free_urb(p_priv->inack_urb);
+ usb_free_urb(p_priv->outcont_urb);
+ for (i = 0; i < 2; i++) {
+ usb_free_urb(p_priv->in_urbs[i]);
+ usb_free_urb(p_priv->out_urbs[i]);
}
+
+ kfree(p_priv->outcont_buffer);
+ kfree(p_priv->inack_buffer);
+ for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
+ kfree(p_priv->out_buffer[i]);
+ for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
+ kfree(p_priv->in_buffer[i]);
+
+ kfree(p_priv);
+
+ return 0;
}
MODULE_AUTHOR(DRIVER_AUTHOR);
@@ -2746,7 +2502,3 @@ MODULE_FIRMWARE("keyspan/usa18x.fw");
MODULE_FIRMWARE("keyspan/usa19w.fw");
MODULE_FIRMWARE("keyspan/usa49w.fw");
MODULE_FIRMWARE("keyspan/usa49wlc.fw");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 2d8baf6ac47..0273dda303a 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -42,6 +42,8 @@ static void keyspan_dtr_rts (struct usb_serial_port *port, int on);
static int keyspan_startup (struct usb_serial *serial);
static void keyspan_disconnect (struct usb_serial *serial);
static void keyspan_release (struct usb_serial *serial);
+static int keyspan_port_probe(struct usb_serial_port *port);
+static int keyspan_port_remove(struct usb_serial_port *port);
static int keyspan_write_room (struct tty_struct *tty);
static int keyspan_write (struct tty_struct *tty,
@@ -58,26 +60,29 @@ static void keyspan_set_termios (struct tty_struct *tty,
struct ktermios *old);
static void keyspan_break_ctl (struct tty_struct *tty,
int break_state);
-static int keyspan_tiocmget (struct tty_struct *tty,
- struct file *file);
+static int keyspan_tiocmget (struct tty_struct *tty);
static int keyspan_tiocmset (struct tty_struct *tty,
- struct file *file, unsigned int set,
+ unsigned int set,
unsigned int clear);
static int keyspan_fake_startup (struct usb_serial *serial);
-static int keyspan_usa19_calc_baud (u32 baud_rate, u32 baudclk,
+static int keyspan_usa19_calc_baud (struct usb_serial_port *port,
+ u32 baud_rate, u32 baudclk,
u8 *rate_hi, u8 *rate_low,
u8 *prescaler, int portnum);
-static int keyspan_usa19w_calc_baud (u32 baud_rate, u32 baudclk,
+static int keyspan_usa19w_calc_baud (struct usb_serial_port *port,
+ u32 baud_rate, u32 baudclk,
u8 *rate_hi, u8 *rate_low,
u8 *prescaler, int portnum);
-static int keyspan_usa28_calc_baud (u32 baud_rate, u32 baudclk,
+static int keyspan_usa28_calc_baud (struct usb_serial_port *port,
+ u32 baud_rate, u32 baudclk,
u8 *rate_hi, u8 *rate_low,
u8 *prescaler, int portnum);
-static int keyspan_usa19hs_calc_baud (u32 baud_rate, u32 baudclk,
+static int keyspan_usa19hs_calc_baud (struct usb_serial_port *port,
+ u32 baud_rate, u32 baudclk,
u8 *rate_hi, u8 *rate_low,
u8 *prescaler, int portnum);
@@ -189,8 +194,9 @@ struct keyspan_device_details {
/* Endpoint used for global control functions */
int glocont_endpoint;
- int (*calculate_baud_rate) (u32 baud_rate, u32 baudclk,
- u8 *rate_hi, u8 *rate_low, u8 *prescaler, int portnum);
+ int (*calculate_baud_rate) (struct usb_serial_port *port,
+ u32 baud_rate, u32 baudclk,
+ u8 *rate_hi, u8 *rate_low, u8 *prescaler, int portnum);
u32 baudclk;
};
@@ -488,14 +494,6 @@ static const struct usb_device_id keyspan_ids_combined[] = {
MODULE_DEVICE_TABLE(usb, keyspan_ids_combined);
-static struct usb_driver keyspan_driver = {
- .name = "keyspan",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = keyspan_ids_combined,
- .no_dynamic_id = 1,
-};
-
/* usb_device_id table for the pre-firmware download keyspan devices */
static const struct usb_device_id keyspan_pre_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_pre_product_id) },
@@ -571,6 +569,8 @@ static struct usb_serial_driver keyspan_1port_device = {
.attach = keyspan_startup,
.disconnect = keyspan_disconnect,
.release = keyspan_release,
+ .port_probe = keyspan_port_probe,
+ .port_remove = keyspan_port_remove,
};
static struct usb_serial_driver keyspan_2port_device = {
@@ -593,6 +593,8 @@ static struct usb_serial_driver keyspan_2port_device = {
.attach = keyspan_startup,
.disconnect = keyspan_disconnect,
.release = keyspan_release,
+ .port_probe = keyspan_port_probe,
+ .port_remove = keyspan_port_remove,
};
static struct usb_serial_driver keyspan_4port_device = {
@@ -615,6 +617,13 @@ static struct usb_serial_driver keyspan_4port_device = {
.attach = keyspan_startup,
.disconnect = keyspan_disconnect,
.release = keyspan_release,
+ .port_probe = keyspan_port_probe,
+ .port_remove = keyspan_port_remove,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+ &keyspan_pre_device, &keyspan_1port_device,
+ &keyspan_2port_device, &keyspan_4port_device, NULL
};
#endif
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index a10dd5676cc..742d827f876 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -12,65 +12,11 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this
* driver
- *
- * (09/07/2001) gkh
- * cleaned up the Xircom support. Added ids for Entregra device which is
- * the same as the Xircom device. Enabled the code to be compiled for
- * either Xircom or Keyspan devices.
- *
- * (08/11/2001) Cristian M. Craciunescu
- * support for Xircom PGSDB9
- *
- * (05/31/2001) gkh
- * switched from using spinlock to a semaphore, which fixes lots of
- * problems.
- *
- * (04/08/2001) gb
- * Identify version on module load.
- *
- * (11/01/2000) Adam J. Richter
- * usb_device_id table support
- *
- * (10/05/2000) gkh
- * Fixed bug with urb->dev not being set properly, now that the usb
- * core needs it.
- *
- * (08/28/2000) gkh
- * Added locks for SMP safeness.
- * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
- * than once.
- *
- * (07/20/2000) borchers
- * - keyspan_pda_write no longer sleeps if it is called on interrupt time;
- * PPP and the line discipline with stty echo on can call write on
- * interrupt time and this would cause an oops if write slept
- * - if keyspan_pda_write is in an interrupt, it will not call
- * usb_control_msg (which sleeps) to query the room in the device
- * buffer, it simply uses the current room value it has
- * - if the urb is busy or if it is throttled keyspan_pda_write just
- * returns 0, rather than sleeping to wait for this to change; the
- * write_chan code in n_tty.c will sleep if needed before calling
- * keyspan_pda_write again
- * - if the device needs to be unthrottled, write now queues up the
- * call to usb_control_msg (which sleeps) to unthrottle the device
- * - the wakeups from keyspan_pda_write_bulk_callback are queued rather
- * than done directly from the callback to avoid the race in write_chan
- * - keyspan_pda_chars_in_buffer also indicates its buffer is full if the
- * urb status is -EINPROGRESS, meaning it cannot write at the moment
- *
- * (07/19/2000) gkh
- * Added module_init and module_exit functions to handle the fact that this
- * driver is a loadable module now.
- *
- * (03/26/2000) gkh
- * Split driver up into device specific pieces.
- *
*/
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -78,13 +24,10 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
-#include <linux/firmware.h>
-#include <linux/ihex.h>
#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-
-static int debug;
+#include <linux/usb/ezusb.h>
/* make a simple define to handle if we are compiling keyspan_pda or xircom support */
#if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_KEYSPAN_PDA_MODULE)
@@ -98,10 +41,6 @@ static int debug;
#undef XIRCOM
#endif
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.1"
#define DRIVER_AUTHOR "Brian Warner <warner@lothar.com>"
#define DRIVER_DESC "USB Keyspan PDA Converter driver"
@@ -139,14 +78,6 @@ static const struct usb_device_id id_table_combined[] = {
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver keyspan_pda_driver = {
- .name = "keyspan_pda",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
- .no_dynamic_id = 1,
-};
-
static const struct usb_device_id id_table_std[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_ID) },
{ } /* Terminating entry */
@@ -172,9 +103,8 @@ static void keyspan_pda_wakeup_write(struct work_struct *work)
struct keyspan_pda_private *priv =
container_of(work, struct keyspan_pda_private, wakeup_work);
struct usb_serial_port *port = priv->port;
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- tty_wakeup(tty);
- tty_kref_put(tty);
+
+ tty_port_tty_wakeup(&port->port);
}
static void keyspan_pda_request_unthrottle(struct work_struct *work)
@@ -184,7 +114,6 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work)
struct usb_serial *serial = priv->serial;
int result;
- dbg(" request_unthrottle");
/* ask the device to tell us when the tx buffer becomes
sufficiently empty */
result = usb_control_msg(serial->dev,
@@ -198,15 +127,14 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work)
0,
2000);
if (result < 0)
- dbg("%s - error %d from usb_control_msg",
- __func__, result);
+ dev_dbg(&serial->dev->dev, "%s - error %d from usb_control_msg\n",
+ __func__, result);
}
static void keyspan_pda_rx_interrupt(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
- struct tty_struct *tty = tty_port_tty_get(&port->port);
unsigned char *data = urb->transfer_buffer;
int retval;
int status = urb->status;
@@ -221,28 +149,26 @@ static void keyspan_pda_rx_interrupt(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
- goto out;
+ dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n", __func__, status);
+ return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
+ dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __func__, status);
goto exit;
}
/* see if the message is data or a status interrupt */
switch (data[0]) {
case 0:
- /* rest of message is rx data */
+ /* rest of message is rx data */
if (urb->actual_length) {
- tty_insert_flip_string(tty, data + 1,
+ tty_insert_flip_string(&port->port, data + 1,
urb->actual_length - 1);
- tty_flip_buffer_push(tty);
+ tty_flip_buffer_push(&port->port);
}
break;
case 1:
/* status interrupt */
- dbg(" rx int, d1=%d, d2=%d", data[1], data[2]);
+ dev_dbg(&port->dev, "rx int, d1=%d, d2=%d\n", data[1], data[2]);
switch (data[1]) {
case 1: /* modemline change */
break;
@@ -263,10 +189,8 @@ exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
dev_err(&port->dev,
- "%s - usb_submit_urb failed with result %d",
+ "%s - usb_submit_urb failed with result %d\n",
__func__, retval);
-out:
- tty_kref_put(tty);
}
@@ -279,7 +203,7 @@ static void keyspan_pda_rx_throttle(struct tty_struct *tty)
send an XOFF, although it might make sense to foist that off
upon the device too. */
struct usb_serial_port *port = tty->driver_data;
- dbg("keyspan_pda_rx_throttle port %d", port->number);
+
usb_kill_urb(port->interrupt_in_urb);
}
@@ -288,10 +212,9 @@ static void keyspan_pda_rx_unthrottle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
/* just restart the receive interrupt URB */
- dbg("keyspan_pda_rx_unthrottle port %d", port->number);
- port->interrupt_in_urb->dev = port->serial->dev;
+
if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL))
- dbg(" usb_submit_urb(read urb) failed");
+ dev_dbg(&port->dev, "usb_submit_urb(read urb) failed\n");
}
@@ -370,8 +293,8 @@ static void keyspan_pda_break_ctl(struct tty_struct *tty, int break_state)
USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
value, 0, NULL, 0, 2000);
if (result < 0)
- dbg("%s - error %d from usb_control_msg",
- __func__, result);
+ dev_dbg(&port->dev, "%s - error %d from usb_control_msg\n",
+ __func__, result);
/* there is something funky about this.. the TCSBRK that 'cu' performs
ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4
seconds apart, but it feels like the break sent isn't as long as it
@@ -400,7 +323,7 @@ static void keyspan_pda_set_termios(struct tty_struct *tty,
7[EOMS]1: 10 bit, b0/b7 is parity
7[EOMS]2: 11 bit, b0/b7 is parity, extra bit always (mark?)
- HW flow control is dictated by the tty->termios->c_cflags & CRTSCTS
+ HW flow control is dictated by the tty->termios.c_cflags & CRTSCTS
bit.
For now, just do baud. */
@@ -409,13 +332,13 @@ static void keyspan_pda_set_termios(struct tty_struct *tty,
speed = keyspan_pda_setbaud(serial, speed);
if (speed == 0) {
- dbg("can't handle requested baud rate");
+ dev_dbg(&port->dev, "can't handle requested baud rate\n");
/* It hasn't changed so.. */
speed = tty_termios_baud_rate(old_termios);
}
/* Only speed can change so copy the old h/w parameters
then encode the new speed */
- tty_termios_copy_hw(tty->termios, old_termios);
+ tty_termios_copy_hw(&tty->termios, old_termios);
tty_encode_baud_rate(tty, speed, speed);
}
@@ -457,7 +380,7 @@ static int keyspan_pda_set_modem_info(struct usb_serial *serial,
return rc;
}
-static int keyspan_pda_tiocmget(struct tty_struct *tty, struct file *file)
+static int keyspan_pda_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
@@ -478,7 +401,7 @@ static int keyspan_pda_tiocmget(struct tty_struct *tty, struct file *file)
return value;
}
-static int keyspan_pda_tiocmset(struct tty_struct *tty, struct file *file,
+static int keyspan_pda_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
@@ -520,9 +443,8 @@ static int keyspan_pda_write(struct tty_struct *tty,
select() or poll() too) until we receive that unthrottle interrupt.
Block if we can't write anything at all, otherwise write as much as
we can. */
- dbg("keyspan_pda_write(%d)", count);
if (count == 0) {
- dbg(" write request of 0 bytes");
+ dev_dbg(&port->dev, "write request of 0 bytes\n");
return 0;
}
@@ -531,11 +453,11 @@ static int keyspan_pda_write(struct tty_struct *tty,
the device is full (wait until it says there is room)
*/
spin_lock_bh(&port->lock);
- if (port->write_urb_busy || priv->tx_throttled) {
+ if (!test_bit(0, &port->write_urbs_free) || priv->tx_throttled) {
spin_unlock_bh(&port->lock);
return 0;
}
- port->write_urb_busy = 1;
+ clear_bit(0, &port->write_urbs_free);
spin_unlock_bh(&port->lock);
/* At this point the URB is in our control, nobody else can submit it
@@ -568,16 +490,16 @@ static int keyspan_pda_write(struct tty_struct *tty,
1,
2000);
if (rc > 0) {
- dbg(" roomquery says %d", *room);
+ dev_dbg(&port->dev, "roomquery says %d\n", *room);
priv->tx_room = *room;
}
kfree(room);
if (rc < 0) {
- dbg(" roomquery failed");
+ dev_dbg(&port->dev, "roomquery failed\n");
goto exit;
}
if (rc == 0) {
- dbg(" roomquery returned 0 bytes");
+ dev_dbg(&port->dev, "roomquery returned 0 bytes\n");
rc = -EIO; /* device didn't return any data */
goto exit;
}
@@ -597,10 +519,9 @@ static int keyspan_pda_write(struct tty_struct *tty,
priv->tx_room -= count;
- port->write_urb->dev = port->serial->dev;
rc = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (rc) {
- dbg(" usb_submit_urb(write bulk) failed");
+ dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed\n");
goto exit;
}
} else {
@@ -617,7 +538,7 @@ static int keyspan_pda_write(struct tty_struct *tty,
rc = count;
exit:
if (rc < 0)
- port->write_urb_busy = 0;
+ set_bit(0, &port->write_urbs_free);
return rc;
}
@@ -627,7 +548,7 @@ static void keyspan_pda_write_bulk_callback(struct urb *urb)
struct usb_serial_port *port = urb->context;
struct keyspan_pda_private *priv;
- port->write_urb_busy = 0;
+ set_bit(0, &port->write_urbs_free);
priv = usb_get_serial_port_data(port);
/* queue up a wakeup at scheduler time */
@@ -660,7 +581,7 @@ static int keyspan_pda_chars_in_buffer(struct tty_struct *tty)
n_tty.c:normal_poll() ) that we're not writeable. */
spin_lock_irqsave(&port->lock, flags);
- if (port->write_urb_busy || priv->tx_throttled)
+ if (!test_bit(0, &port->write_urbs_free) || priv->tx_throttled)
ret = 256;
spin_unlock_irqrestore(&port->lock, flags);
return ret;
@@ -671,28 +592,10 @@ static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on)
{
struct usb_serial *serial = port->serial;
- if (serial->dev) {
- if (on)
- keyspan_pda_set_modem_info(serial, (1<<7) | (1<< 2));
- else
- keyspan_pda_set_modem_info(serial, 0);
- }
-}
-
-static int keyspan_pda_carrier_raised(struct usb_serial_port *port)
-{
- struct usb_serial *serial = port->serial;
- unsigned char modembits;
-
- /* If we can read the modem status and the DCD is low then
- carrier is not raised yet */
- if (keyspan_pda_get_modem_info(serial, &modembits) >= 0) {
- if (!(modembits & (1>>6)))
- return 0;
- }
- /* Carrier raised, or we failed (eg disconnected) so
- progress accordingly */
- return 1;
+ if (on)
+ keyspan_pda_set_modem_info(serial, (1 << 7) | (1 << 2));
+ else
+ keyspan_pda_set_modem_info(serial, 0);
}
@@ -719,11 +622,11 @@ static int keyspan_pda_open(struct tty_struct *tty,
1,
2000);
if (rc < 0) {
- dbg("%s - roomquery failed", __func__);
+ dev_dbg(&port->dev, "%s - roomquery failed\n", __func__);
goto error;
}
if (rc == 0) {
- dbg("%s - roomquery returned 0 bytes", __func__);
+ dev_dbg(&port->dev, "%s - roomquery returned 0 bytes\n", __func__);
rc = -EIO;
goto error;
}
@@ -732,10 +635,9 @@ static int keyspan_pda_open(struct tty_struct *tty,
priv->tx_throttled = *room ? 0 : 1;
/*Start reading from the device*/
- port->interrupt_in_urb->dev = serial->dev;
rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (rc) {
- dbg("%s - usb_submit_urb(read int) failed", __func__);
+ dev_dbg(&port->dev, "%s - usb_submit_urb(read int) failed\n", __func__);
goto error;
}
error:
@@ -744,13 +646,8 @@ error:
}
static void keyspan_pda_close(struct usb_serial_port *port)
{
- struct usb_serial *serial = port->serial;
-
- if (serial->dev) {
- /* shutdown our bulk reads and writes */
- usb_kill_urb(port->write_urb);
- usb_kill_urb(port->interrupt_in_urb);
- }
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->interrupt_in_urb);
}
@@ -759,11 +656,9 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial)
{
int response;
const char *fw_name;
- const struct ihex_binrec *record;
- const struct firmware *fw;
/* download the firmware here ... */
- response = ezusb_set_reset(serial, 1);
+ response = ezusb_fx1_set_reset(serial->dev, 1);
if (0) { ; }
#ifdef KEYSPAN
@@ -780,30 +675,15 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial)
__func__);
return -ENODEV;
}
- if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) {
+
+ if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
fw_name);
return -ENOENT;
}
- record = (const struct ihex_binrec *)fw->data;
-
- while (record) {
- response = ezusb_writememory(serial, be32_to_cpu(record->addr),
- (unsigned char *)record->data,
- be16_to_cpu(record->len), 0xa0);
- if (response < 0) {
- dev_err(&serial->dev->dev, "ezusb_writememory failed "
- "for Keyspan PDA firmware (%d %04X %p %d)\n",
- response, be32_to_cpu(record->addr),
- record->data, be16_to_cpu(record->len));
- break;
- }
- record = ihex_next_binrec(record);
- }
- release_firmware(fw);
- /* bring device out of reset. Renumeration will occur in a moment
- and the new device will bind to the real driver */
- response = ezusb_set_reset(serial, 0);
+
+ /* after downloading firmware Renumeration will occur in a
+ moment and the new device will bind to the real driver */
/* we want this device to fail to have a driver assigned to it. */
return 1;
@@ -816,31 +696,33 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw");
MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw");
#endif
-static int keyspan_pda_startup(struct usb_serial *serial)
+static int keyspan_pda_port_probe(struct usb_serial_port *port)
{
struct keyspan_pda_private *priv;
- /* allocate the private data structures for all ports. Well, for all
- one ports. */
-
priv = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL);
if (!priv)
- return 1; /* error */
- usb_set_serial_port_data(serial->port[0], priv);
- init_waitqueue_head(&serial->port[0]->write_wait);
+ return -ENOMEM;
+
INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write);
INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle);
- priv->serial = serial;
- priv->port = serial->port[0];
+ priv->serial = port->serial;
+ priv->port = port;
+
+ usb_set_serial_port_data(port, priv);
+
return 0;
}
-static void keyspan_pda_release(struct usb_serial *serial)
+static int keyspan_pda_port_remove(struct usb_serial_port *port)
{
- dbg("%s", __func__);
+ struct keyspan_pda_private *priv;
+
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
- kfree(usb_get_serial_port_data(serial->port[0]));
+ return 0;
}
#ifdef KEYSPAN
@@ -850,7 +732,6 @@ static struct usb_serial_driver keyspan_pda_fake_device = {
.name = "keyspan_pda_pre",
},
.description = "Keyspan PDA - (prerenumeration)",
- .usb_driver = &keyspan_pda_driver,
.id_table = id_table_fake,
.num_ports = 1,
.attach = keyspan_pda_fake_startup,
@@ -864,7 +745,6 @@ static struct usb_serial_driver xircom_pgs_fake_device = {
.name = "xircom_no_firm",
},
.description = "Xircom / Entregra PGS - (prerenumeration)",
- .usb_driver = &keyspan_pda_driver,
.id_table = id_table_fake_xircom,
.num_ports = 1,
.attach = keyspan_pda_fake_startup,
@@ -877,11 +757,9 @@ static struct usb_serial_driver keyspan_pda_device = {
.name = "keyspan_pda",
},
.description = "Keyspan PDA",
- .usb_driver = &keyspan_pda_driver,
.id_table = id_table_std,
.num_ports = 1,
.dtr_rts = keyspan_pda_dtr_rts,
- .carrier_raised = keyspan_pda_carrier_raised,
.open = keyspan_pda_open,
.close = keyspan_pda_close,
.write = keyspan_pda_write,
@@ -895,70 +773,23 @@ static struct usb_serial_driver keyspan_pda_device = {
.break_ctl = keyspan_pda_break_ctl,
.tiocmget = keyspan_pda_tiocmget,
.tiocmset = keyspan_pda_tiocmset,
- .attach = keyspan_pda_startup,
- .release = keyspan_pda_release,
+ .port_probe = keyspan_pda_port_probe,
+ .port_remove = keyspan_pda_port_remove,
};
-
-static int __init keyspan_pda_init(void)
-{
- int retval;
- retval = usb_serial_register(&keyspan_pda_device);
- if (retval)
- goto failed_pda_register;
-#ifdef KEYSPAN
- retval = usb_serial_register(&keyspan_pda_fake_device);
- if (retval)
- goto failed_pda_fake_register;
-#endif
-#ifdef XIRCOM
- retval = usb_serial_register(&xircom_pgs_fake_device);
- if (retval)
- goto failed_xircom_register;
-#endif
- retval = usb_register(&keyspan_pda_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
-#ifdef XIRCOM
- usb_serial_deregister(&xircom_pgs_fake_device);
-failed_xircom_register:
-#endif /* XIRCOM */
-#ifdef KEYSPAN
- usb_serial_deregister(&keyspan_pda_fake_device);
-#endif
-#ifdef KEYSPAN
-failed_pda_fake_register:
-#endif
- usb_serial_deregister(&keyspan_pda_device);
-failed_pda_register:
- return retval;
-}
-
-
-static void __exit keyspan_pda_exit(void)
-{
- usb_deregister(&keyspan_pda_driver);
- usb_serial_deregister(&keyspan_pda_device);
+static struct usb_serial_driver * const serial_drivers[] = {
+ &keyspan_pda_device,
#ifdef KEYSPAN
- usb_serial_deregister(&keyspan_pda_fake_device);
+ &keyspan_pda_fake_device,
#endif
#ifdef XIRCOM
- usb_serial_deregister(&xircom_pgs_fake_device);
+ &xircom_pgs_fake_device,
#endif
-}
-
+ NULL
+};
-module_init(keyspan_pda_init);
-module_exit(keyspan_pda_exit);
+module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
diff --git a/drivers/usb/serial/keyspan_usa26msg.h b/drivers/usb/serial/keyspan_usa26msg.h
index 3808727db65..09e21e84fc4 100644
--- a/drivers/usb/serial/keyspan_usa26msg.h
+++ b/drivers/usb/serial/keyspan_usa26msg.h
@@ -62,7 +62,7 @@
or:
(b) 0x80 bit set
- indiates that the bytes following alternate data and
+ indicates that the bytes following alternate data and
status bytes:
STAT DATA STAT DATA STAT DATA STAT DATA ...
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index e8a65ce45a2..d7440b7557a 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -37,7 +37,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -49,12 +48,6 @@
#include <linux/usb/serial.h>
#include "kl5kusb105.h"
-static int debug;
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.4"
#define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>, Johan Hovold <jhovold@gmail.com>"
#define DRIVER_DESC "KLSI KL5KUSB105 chipset USB->Serial Converter driver"
@@ -62,14 +55,14 @@ static int debug;
/*
* Function prototypes
*/
-static int klsi_105_startup(struct usb_serial *serial);
-static void klsi_105_release(struct usb_serial *serial);
+static int klsi_105_port_probe(struct usb_serial_port *port);
+static int klsi_105_port_remove(struct usb_serial_port *port);
static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port);
static void klsi_105_close(struct usb_serial_port *port);
static void klsi_105_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
-static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file);
-static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file,
+static int klsi_105_tiocmget(struct tty_struct *tty);
+static int klsi_105_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
static void klsi_105_process_read_urb(struct urb *urb);
static int klsi_105_prepare_write_buffer(struct usb_serial_port *port,
@@ -86,21 +79,12 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver kl5kusb105d_driver = {
- .name = "kl5kusb105d",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
static struct usb_serial_driver kl5kusb105d_device = {
.driver = {
.owner = THIS_MODULE,
.name = "kl5kusb105d",
},
.description = "KL5KUSB105D / PalmConnect",
- .usb_driver = &kl5kusb105d_driver,
.id_table = id_table,
.num_ports = 1,
.bulk_out_size = 64,
@@ -110,14 +94,18 @@ static struct usb_serial_driver kl5kusb105d_device = {
/*.break_ctl = klsi_105_break_ctl,*/
.tiocmget = klsi_105_tiocmget,
.tiocmset = klsi_105_tiocmset,
- .attach = klsi_105_startup,
- .release = klsi_105_release,
+ .port_probe = klsi_105_port_probe,
+ .port_remove = klsi_105_port_remove,
.throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle,
.process_read_urb = klsi_105_process_read_urb,
.prepare_write_buffer = klsi_105_prepare_write_buffer,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &kl5kusb105d_device, NULL
+};
+
struct klsi_105_port_settings {
__u8 pktlen; /* always 5, it seems */
__u8 baudrate;
@@ -193,11 +181,9 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
dev_info(&port->serial->dev->dev, "sending SIO Poll request\n");
status_buf = kmalloc(KLSI_STATUSBUF_LEN, GFP_KERNEL);
- if (!status_buf) {
- dev_err(&port->dev, "%s - out of memory for status buffer.\n",
- __func__);
+ if (!status_buf)
return -ENOMEM;
- }
+
status_buf[0] = 0xff;
status_buf[1] = 0xff;
rc = usb_control_msg(port->serial->dev,
@@ -215,7 +201,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
else {
status = get_unaligned_le16(status_buf);
- dev_info(&port->serial->dev->dev, "read status %x %x",
+ dev_info(&port->serial->dev->dev, "read status %x %x\n",
status_buf[0], status_buf[1]);
*line_state_p = klsi_105_status2linestate(status);
@@ -230,60 +216,40 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
* Driver's tty interface functions
*/
-static int klsi_105_startup(struct usb_serial *serial)
+static int klsi_105_port_probe(struct usb_serial_port *port)
{
struct klsi_105_private *priv;
- int i;
- /* check if we support the product id (see keyspan.c)
- * FIXME
- */
+ priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
- /* allocate the private data structure */
- for (i = 0; i < serial->num_ports; i++) {
- priv = kmalloc(sizeof(struct klsi_105_private),
- GFP_KERNEL);
- if (!priv) {
- dbg("%skmalloc for klsi_105_private failed.", __func__);
- i--;
- goto err_cleanup;
- }
- /* set initial values for control structures */
- priv->cfg.pktlen = 5;
- priv->cfg.baudrate = kl5kusb105a_sio_b9600;
- priv->cfg.databits = kl5kusb105a_dtb_8;
- priv->cfg.unknown1 = 0;
- priv->cfg.unknown2 = 1;
+ /* set initial values for control structures */
+ priv->cfg.pktlen = 5;
+ priv->cfg.baudrate = kl5kusb105a_sio_b9600;
+ priv->cfg.databits = kl5kusb105a_dtb_8;
+ priv->cfg.unknown1 = 0;
+ priv->cfg.unknown2 = 1;
- priv->line_state = 0;
+ priv->line_state = 0;
- usb_set_serial_port_data(serial->port[i], priv);
+ spin_lock_init(&priv->lock);
- spin_lock_init(&priv->lock);
+ /* priv->termios is left uninitialized until port opening */
- /* priv->termios is left uninitialized until port opening */
- init_waitqueue_head(&serial->port[i]->write_wait);
- }
+ usb_set_serial_port_data(port, priv);
return 0;
-
-err_cleanup:
- for (; i >= 0; i--) {
- priv = usb_get_serial_port_data(serial->port[i]);
- kfree(priv);
- usb_set_serial_port_data(serial->port[i], NULL);
- }
- return -ENOMEM;
}
-static void klsi_105_release(struct usb_serial *serial)
+static int klsi_105_port_remove(struct usb_serial_port *port)
{
- int i;
+ struct klsi_105_private *priv;
- dbg("%s", __func__);
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
- for (i = 0; i < serial->num_ports; ++i)
- kfree(usb_get_serial_port_data(serial->port[i]));
+ return 0;
}
static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -296,8 +262,6 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
struct klsi_105_port_settings *cfg;
unsigned long flags;
- dbg("%s port %d", __func__, port->number);
-
/* Do a defined restart:
* Set up sane default baud rate and send the 'READ_ON'
* vendor command.
@@ -306,11 +270,9 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
* priv->line_state.
*/
cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
- if (!cfg) {
- dev_err(&port->dev, "%s - out of memory for config buffer.\n",
- __func__);
+ if (!cfg)
return -ENOMEM;
- }
+
cfg->pktlen = 5;
cfg->baudrate = kl5kusb105a_sio_b9600;
cfg->databits = kl5kusb105a_dtb_8;
@@ -320,12 +282,12 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
/* set up termios structure */
spin_lock_irqsave(&priv->lock, flags);
- priv->termios.c_iflag = tty->termios->c_iflag;
- priv->termios.c_oflag = tty->termios->c_oflag;
- priv->termios.c_cflag = tty->termios->c_cflag;
- priv->termios.c_lflag = tty->termios->c_lflag;
+ priv->termios.c_iflag = tty->termios.c_iflag;
+ priv->termios.c_oflag = tty->termios.c_oflag;
+ priv->termios.c_cflag = tty->termios.c_cflag;
+ priv->termios.c_lflag = tty->termios.c_lflag;
for (i = 0; i < NCCS; i++)
- priv->termios.c_cc[i] = tty->termios->c_cc[i];
+ priv->termios.c_cc[i] = tty->termios.c_cc[i];
priv->cfg.pktlen = cfg->pktlen;
priv->cfg.baudrate = cfg->baudrate;
priv->cfg.databits = cfg->databits;
@@ -353,14 +315,14 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
dev_err(&port->dev, "Enabling read failed (error = %d)\n", rc);
retval = rc;
} else
- dbg("%s - enabled reading", __func__);
+ dev_dbg(&port->dev, "%s - enabled reading\n", __func__);
rc = klsi_105_get_line_state(port, &line_state);
if (rc >= 0) {
spin_lock_irqsave(&priv->lock, flags);
priv->line_state = line_state;
spin_unlock_irqrestore(&priv->lock, flags);
- dbg("%s - read line state 0x%lx", __func__, line_state);
+ dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__, line_state);
retval = 0;
} else
retval = rc;
@@ -374,30 +336,20 @@ static void klsi_105_close(struct usb_serial_port *port)
{
int rc;
- dbg("%s port %d", __func__, port->number);
-
- mutex_lock(&port->serial->disc_mutex);
- if (!port->serial->disconnected) {
- /* send READ_OFF */
- rc = usb_control_msg(port->serial->dev,
- usb_sndctrlpipe(port->serial->dev, 0),
- KL5KUSB105A_SIO_CONFIGURE,
- USB_TYPE_VENDOR | USB_DIR_OUT,
- KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
- 0, /* index */
- NULL, 0,
- KLSI_TIMEOUT);
- if (rc < 0)
- dev_err(&port->dev,
- "Disabling read failed (error = %d)\n", rc);
- }
- mutex_unlock(&port->serial->disc_mutex);
+ /* send READ_OFF */
+ rc = usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ KL5KUSB105A_SIO_CONFIGURE,
+ USB_TYPE_VENDOR | USB_DIR_OUT,
+ KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
+ 0, /* index */
+ NULL, 0,
+ KLSI_TIMEOUT);
+ if (rc < 0)
+ dev_err(&port->dev, "failed to disable read: %d\n", rc);
/* shutdown our bulk reads and writes */
usb_serial_generic_close(port);
-
- /* wgg - do I need this? I think so. */
- usb_kill_urb(port->interrupt_in_urb);
}
/* We need to write a complete 64-byte data block and encode the
@@ -424,7 +376,6 @@ static void klsi_105_process_read_urb(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
- struct tty_struct *tty;
unsigned len;
/* empty urbs seem to happen, we ignore them */
@@ -432,23 +383,18 @@ static void klsi_105_process_read_urb(struct urb *urb)
return;
if (urb->actual_length <= KLSI_HDR_LEN) {
- dbg("%s - malformed packet", __func__);
+ dev_dbg(&port->dev, "%s - malformed packet\n", __func__);
return;
}
- tty = tty_port_tty_get(&port->port);
- if (!tty)
- return;
-
len = get_unaligned_le16(data);
if (len > urb->actual_length - KLSI_HDR_LEN) {
- dbg("%s - packet length mismatch", __func__);
+ dev_dbg(&port->dev, "%s - packet length mismatch\n", __func__);
len = urb->actual_length - KLSI_HDR_LEN;
}
- tty_insert_flip_string(tty, data + KLSI_HDR_LEN, len);
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
+ tty_insert_flip_string(&port->port, data + KLSI_HDR_LEN, len);
+ tty_flip_buffer_push(&port->port);
}
static void klsi_105_set_termios(struct tty_struct *tty,
@@ -456,20 +402,18 @@ static void klsi_105_set_termios(struct tty_struct *tty,
struct ktermios *old_termios)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
- unsigned int iflag = tty->termios->c_iflag;
+ struct device *dev = &port->dev;
+ unsigned int iflag = tty->termios.c_iflag;
unsigned int old_iflag = old_termios->c_iflag;
- unsigned int cflag = tty->termios->c_cflag;
+ unsigned int cflag = tty->termios.c_cflag;
unsigned int old_cflag = old_termios->c_cflag;
struct klsi_105_port_settings *cfg;
unsigned long flags;
speed_t baud;
cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
- if (!cfg) {
- dev_err(&port->dev, "%s - out of memory for config buffer.\n",
- __func__);
+ if (!cfg)
return;
- }
/* lock while we are modifying the settings */
spin_lock_irqsave(&priv->lock, flags);
@@ -482,7 +426,7 @@ static void klsi_105_set_termios(struct tty_struct *tty,
if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
/* reassert DTR and (maybe) RTS on transition from B0 */
if ((old_cflag & CBAUD) == B0) {
- dbg("%s: baud was B0", __func__);
+ dev_dbg(dev, "%s: baud was B0\n", __func__);
#if 0
priv->control_state |= TIOCM_DTR;
/* don't set RTS if using hardware flow control */
@@ -520,14 +464,13 @@ static void klsi_105_set_termios(struct tty_struct *tty,
priv->cfg.baudrate = kl5kusb105a_sio_b115200;
break;
default:
- dbg("KLSI USB->Serial converter:"
- " unsupported baudrate request, using default of 9600");
- priv->cfg.baudrate = kl5kusb105a_sio_b9600;
+ dev_dbg(dev, "unsupported baudrate, using 9600\n");
+ priv->cfg.baudrate = kl5kusb105a_sio_b9600;
baud = 9600;
break;
}
if ((cflag & CBAUD) == B0) {
- dbg("%s: baud is B0", __func__);
+ dev_dbg(dev, "%s: baud is B0\n", __func__);
/* Drop RTS and DTR */
/* maybe this should be simulated by sending read
* disable and read enable messages?
@@ -544,11 +487,11 @@ static void klsi_105_set_termios(struct tty_struct *tty,
/* set the number of data bits */
switch (cflag & CSIZE) {
case CS5:
- dbg("%s - 5 bits/byte not supported", __func__);
+ dev_dbg(dev, "%s - 5 bits/byte not supported\n", __func__);
spin_unlock_irqrestore(&priv->lock, flags);
goto err;
case CS6:
- dbg("%s - 6 bits/byte not supported", __func__);
+ dev_dbg(dev, "%s - 6 bits/byte not supported\n", __func__);
spin_unlock_irqrestore(&priv->lock, flags);
goto err;
case CS7:
@@ -558,8 +501,7 @@ static void klsi_105_set_termios(struct tty_struct *tty,
priv->cfg.databits = kl5kusb105a_dtb_8;
break;
default:
- dev_err(&port->dev,
- "CSIZE was not CS5-CS8, using default of 8\n");
+ dev_err(dev, "CSIZE was not CS5-CS8, using default of 8\n");
priv->cfg.databits = kl5kusb105a_dtb_8;
break;
}
@@ -571,7 +513,7 @@ static void klsi_105_set_termios(struct tty_struct *tty,
if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
|| (cflag & CSTOPB) != (old_cflag & CSTOPB)) {
/* Not currently supported */
- tty->termios->c_cflag &= ~(PARENB|PARODD|CSTOPB);
+ tty->termios.c_cflag &= ~(PARENB|PARODD|CSTOPB);
#if 0
priv->last_lcr = 0;
@@ -598,7 +540,7 @@ static void klsi_105_set_termios(struct tty_struct *tty,
|| (iflag & IXON) != (old_iflag & IXON)
|| (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
/* Not currently supported */
- tty->termios->c_cflag &= ~CRTSCTS;
+ tty->termios.c_cflag &= ~CRTSCTS;
/* Drop DTR/RTS if no flow control otherwise assert */
#if 0
if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
@@ -627,7 +569,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
(struct mct_u232_private *)port->private;
unsigned char lcr = priv->last_lcr;
- dbg("%sstate=%d", __func__, break_state);
+ dev_dbg(&port->dev, "%s - state=%d\n", __func__, break_state);
/* LOCKING */
if (break_state)
@@ -637,14 +579,13 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
}
#endif
-static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file)
+static int klsi_105_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int rc;
unsigned long line_state;
- dbg("%s - request, just guessing", __func__);
rc = klsi_105_get_line_state(port, &line_state);
if (rc < 0) {
@@ -657,17 +598,15 @@ static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file)
spin_lock_irqsave(&priv->lock, flags);
priv->line_state = line_state;
spin_unlock_irqrestore(&priv->lock, flags);
- dbg("%s - read line state 0x%lx", __func__, line_state);
+ dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__, line_state);
return (int)line_state;
}
-static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file,
+static int klsi_105_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
int retval = -EINVAL;
- dbg("%s", __func__);
-
/* if this ever gets implemented, it should be done something like this:
struct usb_serial *serial = port->serial;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
@@ -690,40 +629,8 @@ static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file,
return retval;
}
-
-static int __init klsi_105_init(void)
-{
- int retval;
- retval = usb_serial_register(&kl5kusb105d_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&kl5kusb105d_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&kl5kusb105d_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit klsi_105_exit(void)
-{
- usb_deregister(&kl5kusb105d_driver);
- usb_serial_deregister(&kl5kusb105d_device);
-}
-
-
-module_init(klsi_105_init);
-module_exit(klsi_105_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "enable extensive debugging messages");
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index bd5bd8589e0..078f9ed419c 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -20,24 +20,11 @@
*
* Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus
* (Adapter K), B1 Professional and KAAN Professional (Adapter B)
- *
- * (21/05/2004) tw
- * Fix bug with P'n'P readers
- *
- * (28/05/2003) tw
- * Add support for KAAN SIM
- *
- * (12/09/2002) tw
- * Adapted to 2.5.
- *
- * (11/08/2002) tw
- * Initial version.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -50,10 +37,6 @@
#include <linux/ioctl.h>
#include "kobil_sct.h"
-static int debug;
-
-/* Version Information */
-#define DRIVER_VERSION "21/05/2004"
#define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com"
#define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)"
@@ -68,20 +51,20 @@ static int debug;
/* Function prototypes */
-static int kobil_startup(struct usb_serial *serial);
-static void kobil_release(struct usb_serial *serial);
+static int kobil_port_probe(struct usb_serial_port *probe);
+static int kobil_port_remove(struct usb_serial_port *probe);
static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port);
static void kobil_close(struct usb_serial_port *port);
static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static int kobil_write_room(struct tty_struct *tty);
-static int kobil_ioctl(struct tty_struct *tty, struct file *file,
+static int kobil_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
-static int kobil_tiocmget(struct tty_struct *tty, struct file *file);
-static int kobil_tiocmset(struct tty_struct *tty, struct file *file,
+static int kobil_tiocmget(struct tty_struct *tty);
+static int kobil_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
static void kobil_read_int_callback(struct urb *urb);
-static void kobil_write_callback(struct urb *purb);
+static void kobil_write_int_callback(struct urb *urb);
static void kobil_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
static void kobil_init_termios(struct tty_struct *tty);
@@ -93,30 +76,18 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_KAAN_SIM_PRODUCT_ID) },
{ } /* Terminating entry */
};
-
-
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver kobil_driver = {
- .name = "kobil",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
-
static struct usb_serial_driver kobil_device = {
.driver = {
.owner = THIS_MODULE,
.name = "kobil",
},
.description = "KOBIL USB smart card terminal",
- .usb_driver = &kobil_driver,
.id_table = id_table,
.num_ports = 1,
- .attach = kobil_startup,
- .release = kobil_release,
+ .port_probe = kobil_port_probe,
+ .port_remove = kobil_port_remove,
.ioctl = kobil_ioctl,
.set_termios = kobil_set_termios,
.init_termios = kobil_init_termios,
@@ -127,12 +98,14 @@ static struct usb_serial_driver kobil_device = {
.write = kobil_write,
.write_room = kobil_write_room,
.read_int_callback = kobil_read_int_callback,
+ .write_int_callback = kobil_write_int_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &kobil_device, NULL
+};
struct kobil_private {
- int write_int_endpoint_address;
- int read_int_endpoint_address;
unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */
int filled; /* index of the last char in buf */
int cur_pos; /* index of the next char to send in buf */
@@ -140,15 +113,10 @@ struct kobil_private {
};
-static int kobil_startup(struct usb_serial *serial)
+static int kobil_port_probe(struct usb_serial_port *port)
{
- int i;
+ struct usb_serial *serial = port->serial;
struct kobil_private *priv;
- struct usb_device *pdev;
- struct usb_host_config *actconfig;
- struct usb_interface *interface;
- struct usb_host_interface *altsetting;
- struct usb_host_endpoint *endpoint;
priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL);
if (!priv)
@@ -160,108 +128,59 @@ static int kobil_startup(struct usb_serial *serial)
switch (priv->device_type) {
case KOBIL_ADAPTER_B_PRODUCT_ID:
- printk(KERN_DEBUG "KOBIL B1 PRO / KAAN PRO detected\n");
+ dev_dbg(&serial->dev->dev, "KOBIL B1 PRO / KAAN PRO detected\n");
break;
case KOBIL_ADAPTER_K_PRODUCT_ID:
- printk(KERN_DEBUG
- "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n");
+ dev_dbg(&serial->dev->dev, "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n");
break;
case KOBIL_USBTWIN_PRODUCT_ID:
- printk(KERN_DEBUG "KOBIL USBTWIN detected\n");
+ dev_dbg(&serial->dev->dev, "KOBIL USBTWIN detected\n");
break;
case KOBIL_KAAN_SIM_PRODUCT_ID:
- printk(KERN_DEBUG "KOBIL KAAN SIM detected\n");
+ dev_dbg(&serial->dev->dev, "KOBIL KAAN SIM detected\n");
break;
}
- usb_set_serial_port_data(serial->port[0], priv);
-
- /* search for the necessary endpoints */
- pdev = serial->dev;
- actconfig = pdev->actconfig;
- interface = actconfig->interface[0];
- altsetting = interface->cur_altsetting;
- endpoint = altsetting->endpoint;
-
- for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
- endpoint = &altsetting->endpoint[i];
- if (usb_endpoint_is_int_out(&endpoint->desc)) {
- dbg("%s Found interrupt out endpoint. Address: %d",
- __func__, endpoint->desc.bEndpointAddress);
- priv->write_int_endpoint_address =
- endpoint->desc.bEndpointAddress;
- }
- if (usb_endpoint_is_int_in(&endpoint->desc)) {
- dbg("%s Found interrupt in endpoint. Address: %d",
- __func__, endpoint->desc.bEndpointAddress);
- priv->read_int_endpoint_address =
- endpoint->desc.bEndpointAddress;
- }
- }
+ usb_set_serial_port_data(port, priv);
+
return 0;
}
-static void kobil_release(struct usb_serial *serial)
+static int kobil_port_remove(struct usb_serial_port *port)
{
- int i;
- dbg("%s - port %d", __func__, serial->port[0]->number);
+ struct kobil_private *priv;
- for (i = 0; i < serial->num_ports; ++i)
- kfree(usb_get_serial_port_data(serial->port[i]));
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
}
static void kobil_init_termios(struct tty_struct *tty)
{
/* Default to echo off and other sane device settings */
- tty->termios->c_lflag = 0;
- tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);
- tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
+ tty->termios.c_lflag = 0;
+ tty->termios.c_iflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);
+ tty->termios.c_iflag |= IGNBRK | IGNPAR | IXOFF;
/* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */
- tty->termios->c_oflag &= ~ONLCR;
+ tty->termios.c_oflag &= ~ONLCR;
}
static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
{
+ struct device *dev = &port->dev;
int result = 0;
struct kobil_private *priv;
unsigned char *transfer_buffer;
int transfer_buffer_length = 8;
- int write_urb_transfer_buffer_length = 8;
- dbg("%s - port %d", __func__, port->number);
priv = usb_get_serial_port_data(port);
- /* someone sets the dev to 0 if the close method has been called */
- port->interrupt_in_urb->dev = port->serial->dev;
-
/* allocate memory for transfer buffer */
transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
if (!transfer_buffer)
return -ENOMEM;
- /* allocate write_urb */
- if (!port->write_urb) {
- dbg("%s - port %d Allocating port->write_urb",
- __func__, port->number);
- port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->write_urb) {
- dbg("%s - port %d usb_alloc_urb failed",
- __func__, port->number);
- kfree(transfer_buffer);
- return -ENOMEM;
- }
- }
-
- /* allocate memory for write_urb transfer buffer */
- port->write_urb->transfer_buffer =
- kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
- if (!port->write_urb->transfer_buffer) {
- kfree(transfer_buffer);
- usb_free_urb(port->write_urb);
- port->write_urb = NULL;
- return -ENOMEM;
- }
-
/* get hardware version */
result = usb_control_msg(port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0),
@@ -273,10 +192,9 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
transfer_buffer_length,
KOBIL_TIMEOUT
);
- dbg("%s - port %d Send get_HW_version URB returns: %i",
- __func__, port->number, result);
- dbg("Harware version: %i.%i.%i",
- transfer_buffer[0], transfer_buffer[1], transfer_buffer[2]);
+ dev_dbg(dev, "%s - Send get_HW_version URB returns: %i\n", __func__, result);
+ dev_dbg(dev, "Hardware version: %i.%i.%i\n", transfer_buffer[0],
+ transfer_buffer[1], transfer_buffer[2]);
/* get firmware version */
result = usb_control_msg(port->serial->dev,
@@ -289,49 +207,45 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
transfer_buffer_length,
KOBIL_TIMEOUT
);
- dbg("%s - port %d Send get_FW_version URB returns: %i",
- __func__, port->number, result);
- dbg("Firmware version: %i.%i.%i",
- transfer_buffer[0], transfer_buffer[1], transfer_buffer[2]);
+ dev_dbg(dev, "%s - Send get_FW_version URB returns: %i\n", __func__, result);
+ dev_dbg(dev, "Firmware version: %i.%i.%i\n", transfer_buffer[0],
+ transfer_buffer[1], transfer_buffer[2]);
if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
/* Setting Baudrate, Parity and Stopbits */
result = usb_control_msg(port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0),
+ usb_sndctrlpipe(port->serial->dev, 0),
SUSBCRequest_SetBaudRateParityAndStopBits,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity |
SUSBCR_SPASB_1StopBit,
0,
- transfer_buffer,
+ NULL,
0,
KOBIL_TIMEOUT
);
- dbg("%s - port %d Send set_baudrate URB returns: %i",
- __func__, port->number, result);
+ dev_dbg(dev, "%s - Send set_baudrate URB returns: %i\n", __func__, result);
/* reset all queues */
result = usb_control_msg(port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0),
+ usb_sndctrlpipe(port->serial->dev, 0),
SUSBCRequest_Misc,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
SUSBCR_MSC_ResetAllQueues,
0,
- transfer_buffer,
+ NULL,
0,
KOBIL_TIMEOUT
);
- dbg("%s - port %d Send reset_all_queues URB returns: %i",
- __func__, port->number, result);
+ dev_dbg(dev, "%s - Send reset_all_queues URB returns: %i\n", __func__, result);
}
if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
/* start reading (Adapter B 'cause PNP string) */
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
- dbg("%s - port %d Send read URB returns: %i",
- __func__, port->number, result);
+ dev_dbg(dev, "%s - Send read URB returns: %i\n", __func__, result);
}
kfree(transfer_buffer);
@@ -341,15 +255,8 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
static void kobil_close(struct usb_serial_port *port)
{
- dbg("%s - port %d", __func__, port->number);
-
/* FIXME: Add rts/dtr methods */
- if (port->write_urb) {
- usb_poison_urb(port->write_urb);
- kfree(port->write_urb->transfer_buffer);
- usb_free_urb(port->write_urb);
- port->write_urb = NULL;
- }
+ usb_kill_urb(port->interrupt_out_urb);
usb_kill_urb(port->interrupt_in_urb);
}
@@ -358,51 +265,27 @@ static void kobil_read_int_callback(struct urb *urb)
{
int result;
struct usb_serial_port *port = urb->context;
- struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
-/* char *dbg_data; */
-
- dbg("%s - port %d", __func__, port->number);
if (status) {
- dbg("%s - port %d Read int status not zero: %d",
- __func__, port->number, status);
+ dev_dbg(&port->dev, "%s - Read int status not zero: %d\n", __func__, status);
return;
}
- tty = tty_port_tty_get(&port->port);
if (urb->actual_length) {
-
- /* BEGIN DEBUG */
- /*
- dbg_data = kzalloc((3 * purb->actual_length + 10)
- * sizeof(char), GFP_KERNEL);
- if (! dbg_data) {
- return;
- }
- for (i = 0; i < purb->actual_length; i++) {
- sprintf(dbg_data +3*i, "%02X ", data[i]);
- }
- dbg(" <-- %s", dbg_data);
- kfree(dbg_data);
- */
- /* END DEBUG */
-
- tty_insert_flip_string(tty, data, urb->actual_length);
- tty_flip_buffer_push(tty);
+ usb_serial_debug_data(&port->dev, __func__, urb->actual_length,
+ data);
+ tty_insert_flip_string(&port->port, data, urb->actual_length);
+ tty_flip_buffer_push(&port->port);
}
- tty_kref_put(tty);
- /* someone sets the dev to 0 if the close method has been called */
- port->interrupt_in_urb->dev = port->serial->dev;
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
- dbg("%s - port %d Send read URB returns: %i",
- __func__, port->number, result);
+ dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result);
}
-static void kobil_write_callback(struct urb *purb)
+static void kobil_write_int_callback(struct urb *urb)
{
}
@@ -416,22 +299,20 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
struct kobil_private *priv;
if (count == 0) {
- dbg("%s - port %d write request of 0 bytes",
- __func__, port->number);
+ dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__);
return 0;
}
priv = usb_get_serial_port_data(port);
if (count > (KOBIL_BUF_LENGTH - priv->filled)) {
- dbg("%s - port %d Error: write request bigger than buffer size", __func__, port->number);
+ dev_dbg(&port->dev, "%s - Error: write request bigger than buffer size\n", __func__);
return -ENOMEM;
}
/* Copy data to buffer */
memcpy(priv->buf + priv->filled, buf, count);
- usb_serial_debug_data(debug, &port->dev, __func__, count,
- priv->buf + priv->filled);
+ usb_serial_debug_data(&port->dev, __func__, count, priv->buf + priv->filled);
priv->filled = priv->filled + count;
/* only send complete block. TWIN, KAAN SIM and adapter K
@@ -447,25 +328,15 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
while (todo > 0) {
/* max 8 byte in one urb (endpoint size) */
- length = (todo < 8) ? todo : 8;
+ length = min(todo, port->interrupt_out_size);
/* copy data to transfer buffer */
- memcpy(port->write_urb->transfer_buffer,
+ memcpy(port->interrupt_out_buffer,
priv->buf + priv->cur_pos, length);
- usb_fill_int_urb(port->write_urb,
- port->serial->dev,
- usb_sndintpipe(port->serial->dev,
- priv->write_int_endpoint_address),
- port->write_urb->transfer_buffer,
- length,
- kobil_write_callback,
- port,
- 8
- );
+ port->interrupt_out_urb->transfer_buffer_length = length;
priv->cur_pos = priv->cur_pos + length;
- result = usb_submit_urb(port->write_urb, GFP_NOIO);
- dbg("%s - port %d Send write URB returns: %i",
- __func__, port->number, result);
+ result = usb_submit_urb(port->interrupt_out_urb, GFP_NOIO);
+ dev_dbg(&port->dev, "%s - Send write URB returns: %i\n", __func__, result);
todo = priv->filled - priv->cur_pos;
if (todo > 0)
@@ -475,21 +346,12 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
priv->filled = 0;
priv->cur_pos = 0;
- /* someone sets the dev to 0 if the close method
- has been called */
- port->interrupt_in_urb->dev = port->serial->dev;
-
/* start reading (except TWIN and KAAN SIM) */
if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
- /* someone sets the dev to 0 if the close method has
- been called */
- port->interrupt_in_urb->dev = port->serial->dev;
-
result = usb_submit_urb(port->interrupt_in_urb,
GFP_NOIO);
- dbg("%s - port %d Send read URB returns: %i",
- __func__, port->number, result);
+ dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result);
}
}
return count;
@@ -498,13 +360,12 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
static int kobil_write_room(struct tty_struct *tty)
{
- /* dbg("%s - port %d", __func__, port->number); */
/* FIXME */
return 8;
}
-static int kobil_tiocmget(struct tty_struct *tty, struct file *file)
+static int kobil_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct kobil_private *priv;
@@ -534,8 +395,8 @@ static int kobil_tiocmget(struct tty_struct *tty, struct file *file)
transfer_buffer_length,
KOBIL_TIMEOUT);
- dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x",
- __func__, port->number, result, transfer_buffer[0]);
+ dev_dbg(&port->dev, "%s - Send get_status_line_state URB returns: %i. Statusline: %02x\n",
+ __func__, result, transfer_buffer[0]);
result = 0;
if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0)
@@ -544,10 +405,11 @@ static int kobil_tiocmget(struct tty_struct *tty, struct file *file)
return result;
}
-static int kobil_tiocmset(struct tty_struct *tty, struct file *file,
+static int kobil_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
+ struct device *dev = &port->dev;
struct kobil_private *priv;
int result;
int dtr = 0;
@@ -579,39 +441,34 @@ static int kobil_tiocmset(struct tty_struct *tty, struct file *file,
if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
if (dtr != 0)
- dbg("%s - port %d Setting DTR",
- __func__, port->number);
+ dev_dbg(dev, "%s - Setting DTR\n", __func__);
else
- dbg("%s - port %d Clearing DTR",
- __func__, port->number);
+ dev_dbg(dev, "%s - Clearing DTR\n", __func__);
result = usb_control_msg(port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0),
+ usb_sndctrlpipe(port->serial->dev, 0),
SUSBCRequest_SetStatusLinesOrQueues,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
0,
- transfer_buffer,
+ NULL,
0,
KOBIL_TIMEOUT);
} else {
if (rts != 0)
- dbg("%s - port %d Setting RTS",
- __func__, port->number);
+ dev_dbg(dev, "%s - Setting RTS\n", __func__);
else
- dbg("%s - port %d Clearing RTS",
- __func__, port->number);
+ dev_dbg(dev, "%s - Clearing RTS\n", __func__);
result = usb_control_msg(port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0),
+ usb_sndctrlpipe(port->serial->dev, 0),
SUSBCRequest_SetStatusLinesOrQueues,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
0,
- transfer_buffer,
+ NULL,
0,
KOBIL_TIMEOUT);
}
- dbg("%s - port %d Send set_status_line URB returns: %i",
- __func__, port->number, result);
+ dev_dbg(dev, "%s - Send set_status_line URB returns: %i\n", __func__, result);
kfree(transfer_buffer);
return (result < 0) ? result : 0;
}
@@ -622,14 +479,14 @@ static void kobil_set_termios(struct tty_struct *tty,
struct kobil_private *priv;
int result;
unsigned short urb_val = 0;
- int c_cflag = tty->termios->c_cflag;
+ int c_cflag = tty->termios.c_cflag;
speed_t speed;
priv = usb_get_serial_port_data(port);
if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
/* This device doesn't support ioctl calls */
- *tty->termios = *old;
+ tty_termios_copy_hw(&tty->termios, old);
return;
}
@@ -653,11 +510,11 @@ static void kobil_set_termios(struct tty_struct *tty,
urb_val |= SUSBCR_SPASB_EvenParity;
} else
urb_val |= SUSBCR_SPASB_NoParity;
- tty->termios->c_cflag &= ~CMSPAR;
+ tty->termios.c_cflag &= ~CMSPAR;
tty_encode_baud_rate(tty, speed, speed);
result = usb_control_msg(port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0),
+ usb_sndctrlpipe(port->serial->dev, 0),
SUSBCRequest_SetBaudRateParityAndStopBits,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
urb_val,
@@ -668,7 +525,7 @@ static void kobil_set_termios(struct tty_struct *tty,
);
}
-static int kobil_ioctl(struct tty_struct *tty, struct file *file,
+static int kobil_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
@@ -689,17 +546,19 @@ static int kobil_ioctl(struct tty_struct *tty, struct file *file,
return -ENOBUFS;
result = usb_control_msg(port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0),
+ usb_sndctrlpipe(port->serial->dev, 0),
SUSBCRequest_Misc,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
SUSBCR_MSC_ResetAllQueues,
0,
- NULL, /* transfer_buffer, */
+ NULL,
0,
KOBIL_TIMEOUT
);
- dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __func__, port->number, result);
+ dev_dbg(&port->dev,
+ "%s - Send reset_all_queues (FLUSH) URB returns: %i\n",
+ __func__, result);
kfree(transfer_buffer);
return (result < 0) ? -EIO: 0;
default:
@@ -707,39 +566,8 @@ static int kobil_ioctl(struct tty_struct *tty, struct file *file,
}
}
-static int __init kobil_init(void)
-{
- int retval;
- retval = usb_serial_register(&kobil_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&kobil_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-failed_usb_register:
- usb_serial_deregister(&kobil_device);
-failed_usb_serial_register:
- return retval;
-}
-
-
-static void __exit kobil_exit(void)
-{
- usb_deregister(&kobil_driver);
- usb_serial_deregister(&kobil_device);
-}
-
-module_init(kobil_init);
-module_exit(kobil_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 2849f8c3201..fd707d6a10e 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -19,55 +19,10 @@
* DTR/RTS signal handling may be incomplete or incorrect. I have mainly
* implemented what I have seen with SniffUSB or found in belkin_sa.c.
* For further TODOs check also belkin_sa.c.
- *
- * TEST STATUS:
- * Basic tests have been performed with minicom/zmodem transfers and
- * modem dialing under Linux 2.4.0-test10 (for me it works fine).
- *
- * 04-Nov-2003 Bill Marr <marr at flex dot com>
- * - Mimic Windows driver by sending 2 USB 'device request' messages
- * following normal 'baud rate change' message. This allows data to be
- * transmitted to RS-232 devices which don't assert the 'CTS' signal.
- *
- * 10-Nov-2001 Wolfgang Grandegger
- * - Fixed an endianess problem with the baudrate selection for PowerPC.
- *
- * 06-Dec-2001 Martin Hamilton <martinh@gnu.org>
- * - Added support for the Belkin F5U109 DB9 adaptor
- *
- * 30-May-2001 Greg Kroah-Hartman
- * - switched from using spinlock to a semaphore, which fixes lots of
- * problems.
- *
- * 04-May-2001 Stelian Pop
- * - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes
- * instead of the device reported 32 (using 32 bytes causes many data
- * loss, Windows driver uses 16 too).
- *
- * 02-May-2001 Stelian Pop
- * - Fixed the baud calculation for Sitecom U232-P25 model
- *
- * 08-Apr-2001 gb
- * - Identify version on module load.
- *
- * 06-Jan-2001 Cornel Ciocirlan
- * - Added support for Sitecom U232-P25 model (Product Id 0x0230)
- * - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200)
- *
- * 29-Nov-2000 Greg Kroah-Hartman
- * - Added device id table to fit with 2.4.0-test11 structure.
- * - took out DEAL_WITH_TWO_INT_IN_ENDPOINTS #define as it's not needed
- * (lots of things will change if/when the usb-serial core changes to
- * handle these issues.
- *
- * 27-Nov-2000 Wolfgang Grandegge
- * A version for kernel 2.4.0-test10 released to the Linux community
- * (via linux-usb-devel).
*/
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -78,22 +33,17 @@
#include <asm/unaligned.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
+#include <linux/serial.h>
#include "mct_u232.h"
-/*
- * Version Information
- */
-#define DRIVER_VERSION "z2.1" /* Linux in-kernel version */
#define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
#define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
-static int debug;
-
/*
* Function prototypes
*/
-static int mct_u232_startup(struct usb_serial *serial);
-static void mct_u232_release(struct usb_serial *serial);
+static int mct_u232_port_probe(struct usb_serial_port *port);
+static int mct_u232_port_remove(struct usb_serial_port *remove);
static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);
static void mct_u232_close(struct usb_serial_port *port);
static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
@@ -101,8 +51,8 @@ static void mct_u232_read_int_callback(struct urb *urb);
static void mct_u232_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);
-static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file);
-static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file,
+static int mct_u232_tiocmget(struct tty_struct *tty);
+static int mct_u232_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
static void mct_u232_throttle(struct tty_struct *tty);
static void mct_u232_unthrottle(struct tty_struct *tty);
@@ -111,23 +61,14 @@ static void mct_u232_unthrottle(struct tty_struct *tty);
/*
* All of the device info needed for the MCT USB-RS232 converter.
*/
-static const struct usb_device_id id_table_combined[] = {
+static const struct usb_device_id id_table[] = {
{ USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
{ USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
{ USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
{ USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
{ } /* Terminating entry */
};
-
-MODULE_DEVICE_TABLE(usb, id_table_combined);
-
-static struct usb_driver mct_u232_driver = {
- .name = "mct_u232",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
- .no_dynamic_id = 1,
-};
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_serial_driver mct_u232_device = {
.driver = {
@@ -135,8 +76,7 @@ static struct usb_serial_driver mct_u232_device = {
.name = "mct_u232",
},
.description = "MCT U232",
- .usb_driver = &mct_u232_driver,
- .id_table = id_table_combined,
+ .id_table = id_table,
.num_ports = 1,
.open = mct_u232_open,
.close = mct_u232_close,
@@ -148,12 +88,18 @@ static struct usb_serial_driver mct_u232_device = {
.break_ctl = mct_u232_break_ctl,
.tiocmget = mct_u232_tiocmget,
.tiocmset = mct_u232_tiocmset,
- .attach = mct_u232_startup,
- .release = mct_u232_release,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .port_probe = mct_u232_port_probe,
+ .port_remove = mct_u232_port_remove,
+ .get_icount = usb_serial_generic_get_icount,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &mct_u232_device, NULL
+};
struct mct_u232_private {
+ struct urb *read_urb;
spinlock_t lock;
unsigned int control_state; /* Modem Line Setting (TIOCM) */
unsigned char last_lcr; /* Line Control Register */
@@ -254,7 +200,7 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty,
value, rc);
else
tty_encode_baud_rate(tty, speed, speed);
- dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);
+ dev_dbg(&port->dev, "set_baud_rate: value: 0x%x, divisor: 0x%x\n", value, divisor);
/* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
always sends two extra USB 'device request' messages after the
@@ -287,8 +233,8 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty,
if (port && C_CRTSCTS(tty))
cts_enable_byte = 1;
- dbg("set_baud_rate: send second control message, data = %02X",
- cts_enable_byte);
+ dev_dbg(&port->dev, "set_baud_rate: send second control message, data = %02X\n",
+ cts_enable_byte);
buf[0] = cts_enable_byte;
rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
MCT_U232_SET_CTS_REQUEST,
@@ -303,7 +249,8 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty,
return rc;
} /* mct_u232_set_baud_rate */
-static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
+static int mct_u232_set_line_ctrl(struct usb_serial_port *port,
+ unsigned char lcr)
{
int rc;
unsigned char *buf;
@@ -313,20 +260,19 @@ static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
return -ENOMEM;
buf[0] = lcr;
- rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ rc = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
MCT_U232_SET_LINE_CTRL_REQUEST,
MCT_U232_SET_REQUEST_TYPE,
0, 0, buf, MCT_U232_SET_LINE_CTRL_SIZE,
WDR_TIMEOUT);
if (rc < 0)
- dev_err(&serial->dev->dev,
- "Set LINE CTRL 0x%x failed (error = %d)\n", lcr, rc);
- dbg("set_line_ctrl: 0x%x", lcr);
+ dev_err(&port->dev, "Set LINE CTRL 0x%x failed (error = %d)\n", lcr, rc);
+ dev_dbg(&port->dev, "set_line_ctrl: 0x%x\n", lcr);
kfree(buf);
return rc;
} /* mct_u232_set_line_ctrl */
-static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
+static int mct_u232_set_modem_ctrl(struct usb_serial_port *port,
unsigned int control_state)
{
int rc;
@@ -344,22 +290,24 @@ static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
mcr |= MCT_U232_MCR_RTS;
buf[0] = mcr;
- rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ rc = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
MCT_U232_SET_MODEM_CTRL_REQUEST,
MCT_U232_SET_REQUEST_TYPE,
0, 0, buf, MCT_U232_SET_MODEM_CTRL_SIZE,
WDR_TIMEOUT);
- if (rc < 0)
- dev_err(&serial->dev->dev,
- "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc);
- dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
-
kfree(buf);
- return rc;
+
+ dev_dbg(&port->dev, "set_modem_ctrl: state=0x%x ==> mcr=0x%x\n", control_state, mcr);
+
+ if (rc < 0) {
+ dev_err(&port->dev, "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc);
+ return rc;
+ }
+ return 0;
} /* mct_u232_set_modem_ctrl */
-static int mct_u232_get_modem_stat(struct usb_serial *serial,
- unsigned char *msr)
+static int mct_u232_get_modem_stat(struct usb_serial_port *port,
+ unsigned char *msr)
{
int rc;
unsigned char *buf;
@@ -369,27 +317,40 @@ static int mct_u232_get_modem_stat(struct usb_serial *serial,
*msr = 0;
return -ENOMEM;
}
- rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ rc = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0),
MCT_U232_GET_MODEM_STAT_REQUEST,
MCT_U232_GET_REQUEST_TYPE,
0, 0, buf, MCT_U232_GET_MODEM_STAT_SIZE,
WDR_TIMEOUT);
if (rc < 0) {
- dev_err(&serial->dev->dev,
- "Get MODEM STATus failed (error = %d)\n", rc);
+ dev_err(&port->dev, "Get MODEM STATus failed (error = %d)\n", rc);
*msr = 0;
} else {
*msr = buf[0];
}
- dbg("get_modem_stat: 0x%x", *msr);
+ dev_dbg(&port->dev, "get_modem_stat: 0x%x\n", *msr);
kfree(buf);
return rc;
} /* mct_u232_get_modem_stat */
-static void mct_u232_msr_to_state(unsigned int *control_state,
+static void mct_u232_msr_to_icount(struct async_icount *icount,
unsigned char msr)
{
/* Translate Control Line states */
+ if (msr & MCT_U232_MSR_DDSR)
+ icount->dsr++;
+ if (msr & MCT_U232_MSR_DCTS)
+ icount->cts++;
+ if (msr & MCT_U232_MSR_DRI)
+ icount->rng++;
+ if (msr & MCT_U232_MSR_DCD)
+ icount->dcd++;
+} /* mct_u232_msr_to_icount */
+
+static void mct_u232_msr_to_state(struct usb_serial_port *port,
+ unsigned int *control_state, unsigned char msr)
+{
+ /* Translate Control Line states */
if (msr & MCT_U232_MSR_DSR)
*control_state |= TIOCM_DSR;
else
@@ -406,52 +367,41 @@ static void mct_u232_msr_to_state(unsigned int *control_state,
*control_state |= TIOCM_CD;
else
*control_state &= ~TIOCM_CD;
- dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state);
+ dev_dbg(&port->dev, "msr_to_state: msr=0x%x ==> state=0x%x\n", msr, *control_state);
} /* mct_u232_msr_to_state */
/*
* Driver's tty interface functions
*/
-static int mct_u232_startup(struct usb_serial *serial)
+static int mct_u232_port_probe(struct usb_serial_port *port)
{
struct mct_u232_private *priv;
- struct usb_serial_port *port, *rport;
- priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
- spin_lock_init(&priv->lock);
- usb_set_serial_port_data(serial->port[0], priv);
- init_waitqueue_head(&serial->port[0]->write_wait);
+ /* Use second interrupt-in endpoint for reading. */
+ priv->read_urb = port->serial->port[1]->interrupt_in_urb;
+ priv->read_urb->context = port;
- /* Puh, that's dirty */
- port = serial->port[0];
- rport = serial->port[1];
- /* No unlinking, it wasn't submitted yet. */
- usb_free_urb(port->read_urb);
- port->read_urb = rport->interrupt_in_urb;
- rport->interrupt_in_urb = NULL;
- port->read_urb->context = port;
+ spin_lock_init(&priv->lock);
- return 0;
-} /* mct_u232_startup */
+ usb_set_serial_port_data(port, priv);
+ return 0;
+}
-static void mct_u232_release(struct usb_serial *serial)
+static int mct_u232_port_remove(struct usb_serial_port *port)
{
struct mct_u232_private *priv;
- int i;
- dbg("%s", __func__);
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
- for (i = 0; i < serial->num_ports; ++i) {
- /* My special items, the standard routines free my urbs */
- priv = usb_get_serial_port_data(serial->port[i]);
- kfree(priv);
- }
-} /* mct_u232_release */
+ return 0;
+}
static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
{
@@ -463,8 +413,6 @@ static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
unsigned char last_lcr;
unsigned char last_msr;
- dbg("%s port %d", __func__, port->number);
-
/* Compensate for a hardware bug: although the Sitecom U232-P25
* device reports a maximum output packet size of 32 bytes,
* it seems to be able to accept only 16 bytes (and that's what
@@ -480,7 +428,7 @@ static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
* either.
*/
spin_lock_irqsave(&priv->lock, flags);
- if (tty && (tty->termios->c_cflag & CBAUD))
+ if (tty && (tty->termios.c_cflag & CBAUD))
priv->control_state = TIOCM_DTR | TIOCM_RTS;
else
priv->control_state = 0;
@@ -491,29 +439,27 @@ static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
control_state = priv->control_state;
last_lcr = priv->last_lcr;
spin_unlock_irqrestore(&priv->lock, flags);
- mct_u232_set_modem_ctrl(serial, control_state);
- mct_u232_set_line_ctrl(serial, last_lcr);
+ mct_u232_set_modem_ctrl(port, control_state);
+ mct_u232_set_line_ctrl(port, last_lcr);
/* Read modem status and update control state */
- mct_u232_get_modem_stat(serial, &last_msr);
+ mct_u232_get_modem_stat(port, &last_msr);
spin_lock_irqsave(&priv->lock, flags);
priv->last_msr = last_msr;
- mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
+ mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
spin_unlock_irqrestore(&priv->lock, flags);
- port->read_urb->dev = port->serial->dev;
- retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ retval = usb_submit_urb(priv->read_urb, GFP_KERNEL);
if (retval) {
dev_err(&port->dev,
- "usb_submit_urb(read bulk) failed pipe 0x%x err %d\n",
+ "usb_submit_urb(read) failed pipe 0x%x err %d\n",
port->read_urb->pipe, retval);
goto error;
}
- port->interrupt_in_urb->dev = port->serial->dev;
retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (retval) {
- usb_kill_urb(port->read_urb);
+ usb_kill_urb(priv->read_urb);
dev_err(&port->dev,
"usb_submit_urb(read int) failed pipe 0x%x err %d",
port->interrupt_in_urb->pipe, retval);
@@ -530,31 +476,25 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
unsigned int control_state;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
- mutex_lock(&port->serial->disc_mutex);
- if (!port->serial->disconnected) {
- /* drop DTR and RTS */
- spin_lock_irq(&priv->lock);
- if (on)
- priv->control_state |= TIOCM_DTR | TIOCM_RTS;
- else
- priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
- control_state = priv->control_state;
- spin_unlock_irq(&priv->lock);
- mct_u232_set_modem_ctrl(port->serial, control_state);
- }
- mutex_unlock(&port->serial->disc_mutex);
+ spin_lock_irq(&priv->lock);
+ if (on)
+ priv->control_state |= TIOCM_DTR | TIOCM_RTS;
+ else
+ priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+ control_state = priv->control_state;
+ spin_unlock_irq(&priv->lock);
+
+ mct_u232_set_modem_ctrl(port, control_state);
}
static void mct_u232_close(struct usb_serial_port *port)
{
- dbg("%s port %d", __func__, port->number);
+ struct mct_u232_private *priv = usb_get_serial_port_data(port);
- if (port->serial->dev) {
- /* shutdown our urbs */
- usb_kill_urb(port->write_urb);
- usb_kill_urb(port->read_urb);
- usb_kill_urb(port->interrupt_in_urb);
- }
+ usb_kill_urb(priv->read_urb);
+ usb_kill_urb(port->interrupt_in_urb);
+
+ usb_serial_generic_close(port);
} /* mct_u232_close */
@@ -562,8 +502,6 @@ static void mct_u232_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
- struct usb_serial *serial = port->serial;
- struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int retval;
int status = urb->status;
@@ -577,36 +515,25 @@ static void mct_u232_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
goto exit;
}
- if (!serial) {
- dbg("%s - bad serial pointer, exiting", __func__);
- return;
- }
-
- dbg("%s - port %d", __func__, port->number);
- usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, data);
+ usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
/*
* Work-a-round: handle the 'usual' bulk-in pipe here
*/
if (urb->transfer_buffer_length > 2) {
if (urb->actual_length) {
- tty = tty_port_tty_get(&port->port);
- if (tty) {
- tty_insert_flip_string(tty, data,
- urb->actual_length);
- tty_flip_buffer_push(tty);
- }
- tty_kref_put(tty);
+ tty_insert_flip_string(&port->port, data,
+ urb->actual_length);
+ tty_flip_buffer_push(&port->port);
}
goto exit;
}
@@ -619,7 +546,9 @@ static void mct_u232_read_int_callback(struct urb *urb)
priv->last_msr = data[MCT_U232_MSR_INDEX];
/* Record Control Line states */
- mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
+ mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
+
+ mct_u232_msr_to_icount(&port->icount, priv->last_msr);
#if 0
/* Not yet handled. See belkin_sa.c for further information */
@@ -647,6 +576,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
tty_kref_put(tty);
}
#endif
+ wake_up_interruptible(&port->port.delta_msr_wait);
spin_unlock_irqrestore(&priv->lock, flags);
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -662,7 +592,7 @@ static void mct_u232_set_termios(struct tty_struct *tty,
{
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
unsigned int cflag = termios->c_cflag;
unsigned int old_cflag = old_termios->c_cflag;
unsigned long flags;
@@ -684,18 +614,18 @@ static void mct_u232_set_termios(struct tty_struct *tty,
/* reassert DTR and RTS on transition from B0 */
if ((old_cflag & CBAUD) == B0) {
- dbg("%s: baud was B0", __func__);
+ dev_dbg(&port->dev, "%s: baud was B0\n", __func__);
control_state |= TIOCM_DTR | TIOCM_RTS;
- mct_u232_set_modem_ctrl(serial, control_state);
+ mct_u232_set_modem_ctrl(port, control_state);
}
mct_u232_set_baud_rate(tty, serial, port, tty_get_baud_rate(tty));
if ((cflag & CBAUD) == B0) {
- dbg("%s: baud is B0", __func__);
+ dev_dbg(&port->dev, "%s: baud is B0\n", __func__);
/* Drop RTS and DTR */
control_state &= ~(TIOCM_DTR | TIOCM_RTS);
- mct_u232_set_modem_ctrl(serial, control_state);
+ mct_u232_set_modem_ctrl(port, control_state);
}
/*
@@ -732,7 +662,7 @@ static void mct_u232_set_termios(struct tty_struct *tty,
last_lcr |= (cflag & CSTOPB) ?
MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
- mct_u232_set_line_ctrl(serial, last_lcr);
+ mct_u232_set_line_ctrl(port, last_lcr);
/* save off the modified port settings */
spin_lock_irqsave(&priv->lock, flags);
@@ -744,13 +674,10 @@ static void mct_u232_set_termios(struct tty_struct *tty,
static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
- struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned char lcr;
unsigned long flags;
- dbg("%sstate=%d", __func__, break_state);
-
spin_lock_irqsave(&priv->lock, flags);
lcr = priv->last_lcr;
@@ -758,19 +685,17 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
lcr |= MCT_U232_SET_BREAK;
spin_unlock_irqrestore(&priv->lock, flags);
- mct_u232_set_line_ctrl(serial, lcr);
+ mct_u232_set_line_ctrl(port, lcr);
} /* mct_u232_break_ctl */
-static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file)
+static int mct_u232_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned int control_state;
unsigned long flags;
- dbg("%s", __func__);
-
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -778,17 +703,14 @@ static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file)
return control_state;
}
-static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file,
+static int mct_u232_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
- struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned int control_state;
unsigned long flags;
- dbg("%s", __func__);
-
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
@@ -803,7 +725,7 @@ static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file,
priv->control_state = control_state;
spin_unlock_irqrestore(&priv->lock, flags);
- return mct_u232_set_modem_ctrl(serial, control_state);
+ return mct_u232_set_modem_ctrl(port, control_state);
}
static void mct_u232_throttle(struct tty_struct *tty)
@@ -812,72 +734,38 @@ static void mct_u232_throttle(struct tty_struct *tty)
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned int control_state;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irq(&priv->lock);
priv->rx_flags |= THROTTLED;
if (C_CRTSCTS(tty)) {
priv->control_state &= ~TIOCM_RTS;
control_state = priv->control_state;
spin_unlock_irq(&priv->lock);
- (void) mct_u232_set_modem_ctrl(port->serial, control_state);
+ mct_u232_set_modem_ctrl(port, control_state);
} else {
spin_unlock_irq(&priv->lock);
}
}
-
static void mct_u232_unthrottle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned int control_state;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irq(&priv->lock);
if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
priv->rx_flags &= ~THROTTLED;
priv->control_state |= TIOCM_RTS;
control_state = priv->control_state;
spin_unlock_irq(&priv->lock);
- (void) mct_u232_set_modem_ctrl(port->serial, control_state);
+ mct_u232_set_modem_ctrl(port, control_state);
} else {
spin_unlock_irq(&priv->lock);
}
}
-static int __init mct_u232_init(void)
-{
- int retval;
- retval = usb_serial_register(&mct_u232_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&mct_u232_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&mct_u232_device);
-failed_usb_serial_register:
- return retval;
-}
-
-
-static void __exit mct_u232_exit(void)
-{
- usb_deregister(&mct_u232_driver);
- usb_serial_deregister(&mct_u232_device);
-}
-
-module_init(mct_u232_init);
-module_exit(mct_u232_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c
new file mode 100644
index 00000000000..39e683096e9
--- /dev/null
+++ b/drivers/usb/serial/metro-usb.c
@@ -0,0 +1,399 @@
+/*
+ Some of this code is credited to Linux USB open source files that are
+ distributed with Linux.
+
+ Copyright: 2007 Metrologic Instruments. All rights reserved.
+ Copyright: 2011 Azimut Ltd. <http://azimutrzn.ru/>
+*/
+
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/usb/serial.h>
+
+#define DRIVER_DESC "Metrologic Instruments Inc. - USB-POS driver"
+
+/* Product information. */
+#define FOCUS_VENDOR_ID 0x0C2E
+#define FOCUS_PRODUCT_ID_BI 0x0720
+#define FOCUS_PRODUCT_ID_UNI 0x0700
+
+#define METROUSB_SET_REQUEST_TYPE 0x40
+#define METROUSB_SET_MODEM_CTRL_REQUEST 10
+#define METROUSB_SET_BREAK_REQUEST 0x40
+#define METROUSB_MCR_NONE 0x08 /* Deactivate DTR and RTS. */
+#define METROUSB_MCR_RTS 0x0a /* Activate RTS. */
+#define METROUSB_MCR_DTR 0x09 /* Activate DTR. */
+#define WDR_TIMEOUT 5000 /* default urb timeout. */
+
+/* Private data structure. */
+struct metrousb_private {
+ spinlock_t lock;
+ int throttled;
+ unsigned long control_state;
+};
+
+/* Device table list. */
+static const struct usb_device_id id_table[] = {
+ { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_BI) },
+ { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) },
+ { }, /* Terminating entry. */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/* UNI-Directional mode commands for device configure */
+#define UNI_CMD_OPEN 0x80
+#define UNI_CMD_CLOSE 0xFF
+
+static inline int metrousb_is_unidirectional_mode(struct usb_serial_port *port)
+{
+ __u16 product_id = le16_to_cpu(
+ port->serial->dev->descriptor.idProduct);
+
+ return product_id == FOCUS_PRODUCT_ID_UNI;
+}
+
+static int metrousb_send_unidirectional_cmd(u8 cmd, struct usb_serial_port *port)
+{
+ int ret;
+ int actual_len;
+ u8 *buffer_cmd = NULL;
+
+ if (!metrousb_is_unidirectional_mode(port))
+ return 0;
+
+ buffer_cmd = kzalloc(sizeof(cmd), GFP_KERNEL);
+ if (!buffer_cmd)
+ return -ENOMEM;
+
+ *buffer_cmd = cmd;
+
+ ret = usb_interrupt_msg(port->serial->dev,
+ usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress),
+ buffer_cmd, sizeof(cmd),
+ &actual_len, USB_CTRL_SET_TIMEOUT);
+
+ kfree(buffer_cmd);
+
+ if (ret < 0)
+ return ret;
+ else if (actual_len != sizeof(cmd))
+ return -EIO;
+ return 0;
+}
+
+static void metrousb_read_int_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+ struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
+ unsigned char *data = urb->transfer_buffer;
+ int throttled = 0;
+ int result = 0;
+ unsigned long flags = 0;
+
+ dev_dbg(&port->dev, "%s\n", __func__);
+
+ switch (urb->status) {
+ case 0:
+ /* Success status, read from the port. */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* urb has been terminated. */
+ dev_dbg(&port->dev,
+ "%s - urb shutting down, error code=%d\n",
+ __func__, urb->status);
+ return;
+ default:
+ dev_dbg(&port->dev,
+ "%s - non-zero urb received, error code=%d\n",
+ __func__, urb->status);
+ goto exit;
+ }
+
+
+ /* Set the data read from the usb port into the serial port buffer. */
+ if (urb->actual_length) {
+ /* Loop through the data copying each byte to the tty layer. */
+ tty_insert_flip_string(&port->port, data, urb->actual_length);
+
+ /* Force the data to the tty layer. */
+ tty_flip_buffer_push(&port->port);
+ }
+
+ /* Set any port variables. */
+ spin_lock_irqsave(&metro_priv->lock, flags);
+ throttled = metro_priv->throttled;
+ spin_unlock_irqrestore(&metro_priv->lock, flags);
+
+ /* Continue trying to read if set. */
+ if (!throttled) {
+ usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
+ usb_rcvintpipe(port->serial->dev, port->interrupt_in_endpointAddress),
+ port->interrupt_in_urb->transfer_buffer,
+ port->interrupt_in_urb->transfer_buffer_length,
+ metrousb_read_int_callback, port, 1);
+
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+
+ if (result)
+ dev_err(&port->dev,
+ "%s - failed submitting interrupt in urb, error code=%d\n",
+ __func__, result);
+ }
+ return;
+
+exit:
+ /* Try to resubmit the urb. */
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&port->dev,
+ "%s - failed submitting interrupt in urb, error code=%d\n",
+ __func__, result);
+}
+
+static void metrousb_write_int_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+
+ dev_warn(&port->dev, "%s not implemented yet.\n",
+ __func__);
+}
+
+static void metrousb_cleanup(struct usb_serial_port *port)
+{
+ dev_dbg(&port->dev, "%s\n", __func__);
+
+ usb_unlink_urb(port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_in_urb);
+
+ metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
+}
+
+static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+ struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
+ unsigned long flags = 0;
+ int result = 0;
+
+ dev_dbg(&port->dev, "%s\n", __func__);
+
+ /* Make sure the urb is initialized. */
+ if (!port->interrupt_in_urb) {
+ dev_err(&port->dev, "%s - interrupt urb not initialized\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ /* Set the private data information for the port. */
+ spin_lock_irqsave(&metro_priv->lock, flags);
+ metro_priv->control_state = 0;
+ metro_priv->throttled = 0;
+ spin_unlock_irqrestore(&metro_priv->lock, flags);
+
+ /* Clear the urb pipe. */
+ usb_clear_halt(serial->dev, port->interrupt_in_urb->pipe);
+
+ /* Start reading from the device */
+ usb_fill_int_urb(port->interrupt_in_urb, serial->dev,
+ usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress),
+ port->interrupt_in_urb->transfer_buffer,
+ port->interrupt_in_urb->transfer_buffer_length,
+ metrousb_read_int_callback, port, 1);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+
+ if (result) {
+ dev_err(&port->dev,
+ "%s - failed submitting interrupt in urb, error code=%d\n",
+ __func__, result);
+ goto exit;
+ }
+
+ /* Send activate cmd to device */
+ result = metrousb_send_unidirectional_cmd(UNI_CMD_OPEN, port);
+ if (result) {
+ dev_err(&port->dev,
+ "%s - failed to configure device, error code=%d\n",
+ __func__, result);
+ goto exit;
+ }
+
+ dev_dbg(&port->dev, "%s - port open\n", __func__);
+exit:
+ return result;
+}
+
+static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int control_state)
+{
+ int retval = 0;
+ unsigned char mcr = METROUSB_MCR_NONE;
+
+ dev_dbg(&serial->dev->dev, "%s - control state = %d\n",
+ __func__, control_state);
+
+ /* Set the modem control value. */
+ if (control_state & TIOCM_DTR)
+ mcr |= METROUSB_MCR_DTR;
+ if (control_state & TIOCM_RTS)
+ mcr |= METROUSB_MCR_RTS;
+
+ /* Send the command to the usb port. */
+ retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ METROUSB_SET_REQUEST_TYPE, METROUSB_SET_MODEM_CTRL_REQUEST,
+ control_state, 0, NULL, 0, WDR_TIMEOUT);
+ if (retval < 0)
+ dev_err(&serial->dev->dev,
+ "%s - set modem ctrl=0x%x failed, error code=%d\n",
+ __func__, mcr, retval);
+
+ return retval;
+}
+
+static int metrousb_port_probe(struct usb_serial_port *port)
+{
+ struct metrousb_private *metro_priv;
+
+ metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL);
+ if (!metro_priv)
+ return -ENOMEM;
+
+ spin_lock_init(&metro_priv->lock);
+
+ usb_set_serial_port_data(port, metro_priv);
+
+ return 0;
+}
+
+static int metrousb_port_remove(struct usb_serial_port *port)
+{
+ struct metrousb_private *metro_priv;
+
+ metro_priv = usb_get_serial_port_data(port);
+ kfree(metro_priv);
+
+ return 0;
+}
+
+static void metrousb_throttle(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
+ unsigned long flags = 0;
+
+ dev_dbg(tty->dev, "%s\n", __func__);
+
+ /* Set the private information for the port to stop reading data. */
+ spin_lock_irqsave(&metro_priv->lock, flags);
+ metro_priv->throttled = 1;
+ spin_unlock_irqrestore(&metro_priv->lock, flags);
+}
+
+static int metrousb_tiocmget(struct tty_struct *tty)
+{
+ unsigned long control_state = 0;
+ struct usb_serial_port *port = tty->driver_data;
+ struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
+ unsigned long flags = 0;
+
+ dev_dbg(tty->dev, "%s\n", __func__);
+
+ spin_lock_irqsave(&metro_priv->lock, flags);
+ control_state = metro_priv->control_state;
+ spin_unlock_irqrestore(&metro_priv->lock, flags);
+
+ return control_state;
+}
+
+static int metrousb_tiocmset(struct tty_struct *tty,
+ unsigned int set, unsigned int clear)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct usb_serial *serial = port->serial;
+ struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
+ unsigned long flags = 0;
+ unsigned long control_state = 0;
+
+ dev_dbg(tty->dev, "%s - set=%d, clear=%d\n", __func__, set, clear);
+
+ spin_lock_irqsave(&metro_priv->lock, flags);
+ control_state = metro_priv->control_state;
+
+ /* Set the RTS and DTR values. */
+ if (set & TIOCM_RTS)
+ control_state |= TIOCM_RTS;
+ if (set & TIOCM_DTR)
+ control_state |= TIOCM_DTR;
+ if (clear & TIOCM_RTS)
+ control_state &= ~TIOCM_RTS;
+ if (clear & TIOCM_DTR)
+ control_state &= ~TIOCM_DTR;
+
+ metro_priv->control_state = control_state;
+ spin_unlock_irqrestore(&metro_priv->lock, flags);
+ return metrousb_set_modem_ctrl(serial, control_state);
+}
+
+static void metrousb_unthrottle(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
+ unsigned long flags = 0;
+ int result = 0;
+
+ dev_dbg(tty->dev, "%s\n", __func__);
+
+ /* Set the private information for the port to resume reading data. */
+ spin_lock_irqsave(&metro_priv->lock, flags);
+ metro_priv->throttled = 0;
+ spin_unlock_irqrestore(&metro_priv->lock, flags);
+
+ /* Submit the urb to read from the port. */
+ port->interrupt_in_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ if (result)
+ dev_err(tty->dev,
+ "failed submitting interrupt in urb error code=%d\n",
+ result);
+}
+
+static struct usb_serial_driver metrousb_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "metro-usb",
+ },
+ .description = "Metrologic USB to Serial",
+ .id_table = id_table,
+ .num_ports = 1,
+ .open = metrousb_open,
+ .close = metrousb_cleanup,
+ .read_int_callback = metrousb_read_int_callback,
+ .write_int_callback = metrousb_write_int_callback,
+ .port_probe = metrousb_port_probe,
+ .port_remove = metrousb_port_remove,
+ .throttle = metrousb_throttle,
+ .unthrottle = metrousb_unthrottle,
+ .tiocmget = metrousb_tiocmget,
+ .tiocmset = metrousb_tiocmset,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+ &metrousb_device,
+ NULL,
+};
+
+module_usb_serial_driver(serial_drivers, id_table);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Philip Nicastro");
+MODULE_AUTHOR("Aleksey Babahin <tamerlan311@gmail.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 7d3bc9a3e2b..dfd728a263d 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -1,6 +1,6 @@
/*
* mos7720.c
- * Controls the Moschip 7720 usb to dual port serial convertor
+ * Controls the Moschip 7720 usb to dual port serial converter
*
* Copyright 2006 Moschip Semiconductor Tech. Ltd.
*
@@ -22,7 +22,6 @@
*/
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -36,21 +35,17 @@
#include <linux/uaccess.h>
#include <linux/parport.h>
-/*
- * Version Information
- */
-#define DRIVER_VERSION "2.1"
#define DRIVER_AUTHOR "Aspire Communications pvt Ltd."
#define DRIVER_DESC "Moschip USB Serial Driver"
/* default urb timeout */
-#define MOS_WDR_TIMEOUT (HZ * 5)
+#define MOS_WDR_TIMEOUT 5000
#define MOS_MAX_PORT 0x02
#define MOS_WRITE 0x0E
#define MOS_READ 0x0D
-/* Interrupt Rotinue Defines */
+/* Interrupt Routines Defines */
#define SERIAL_IIR_RLS 0x06
#define SERIAL_IIR_RDA 0x04
#define SERIAL_IIR_CTI 0x0c
@@ -66,25 +61,22 @@ struct moschip_port {
__u8 shadowMCR; /* last MCR value received */
__u8 shadowMSR; /* last MSR value received */
char open;
- struct async_icount icount;
struct usb_serial_port *port; /* loop back to the owner */
struct urb *write_urb_pool[NUM_URBS];
};
-static int debug;
-
static struct usb_serial_driver moschip7720_2port_driver;
#define USB_VENDOR_ID_MOSCHIP 0x9710
#define MOSCHIP_DEVICE_ID_7720 0x7720
#define MOSCHIP_DEVICE_ID_7715 0x7715
-static const struct usb_device_id moschip_port_id_table[] = {
+static const struct usb_device_id id_table[] = {
{ USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7720) },
{ USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7715) },
{ } /* terminating entry */
};
-MODULE_DEVICE_TABLE(usb, moschip_port_id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
#ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
@@ -97,6 +89,7 @@ struct urbtracker {
struct list_head urblist_entry;
struct kref ref_count;
struct urb *urb;
+ struct usb_ctrlrequest *setup;
};
enum mos7715_pp_modes {
@@ -216,7 +209,7 @@ static int write_mos_reg(struct usb_serial *serial, unsigned int serial_portnum,
index, NULL, 0, MOS_WDR_TIMEOUT);
if (status < 0)
dev_err(&usbdev->dev,
- "mos7720: usb_control_msg() failed: %d", status);
+ "mos7720: usb_control_msg() failed: %d\n", status);
return status;
}
@@ -234,11 +227,22 @@ static int read_mos_reg(struct usb_serial *serial, unsigned int serial_portnum,
__u8 requesttype = (__u8)0xc0;
__u16 index = get_reg_index(reg);
__u16 value = get_reg_value(reg, serial_portnum);
- int status = usb_control_msg(usbdev, pipe, request, requesttype, value,
- index, data, 1, MOS_WDR_TIMEOUT);
- if (status < 0)
+ u8 *buf;
+ int status;
+
+ buf = kmalloc(1, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ status = usb_control_msg(usbdev, pipe, request, requesttype, value,
+ index, buf, 1, MOS_WDR_TIMEOUT);
+ if (status == 1)
+ *data = *buf;
+ else if (status < 0)
dev_err(&usbdev->dev,
- "mos7720: usb_control_msg() failed: %d", status);
+ "mos7720: usb_control_msg() failed: %d\n", status);
+ kfree(buf);
+
return status;
}
@@ -257,7 +261,6 @@ static void destroy_mos_parport(struct kref *kref)
struct mos7715_parport *mos_parport =
container_of(kref, struct mos7715_parport, ref_count);
- dbg("%s called", __func__);
kfree(mos_parport);
}
@@ -266,8 +269,9 @@ static void destroy_urbtracker(struct kref *kref)
struct urbtracker *urbtrack =
container_of(kref, struct urbtracker, ref_count);
struct mos7715_parport *mos_parport = urbtrack->mos_parport;
- dbg("%s called", __func__);
+
usb_free_urb(urbtrack->urb);
+ kfree(urbtrack->setup);
kfree(urbtrack);
kref_put(&mos_parport->ref_count, destroy_mos_parport);
}
@@ -282,18 +286,19 @@ static void send_deferred_urbs(unsigned long _mos_parport)
int ret_val;
unsigned long flags;
struct mos7715_parport *mos_parport = (void *)_mos_parport;
- struct urbtracker *urbtrack;
+ struct urbtracker *urbtrack, *tmp;
struct list_head *cursor, *next;
-
- dbg("%s called", __func__);
+ struct device *dev;
/* if release function ran, game over */
if (unlikely(mos_parport->serial == NULL))
return;
+ dev = &mos_parport->serial->dev->dev;
+
/* try again to get the mutex */
if (!mutex_trylock(&mos_parport->serial->disc_mutex)) {
- dbg("%s: rescheduling tasklet", __func__);
+ dev_dbg(dev, "%s: rescheduling tasklet\n", __func__);
tasklet_schedule(&mos_parport->urb_tasklet);
return;
}
@@ -308,20 +313,19 @@ static void send_deferred_urbs(unsigned long _mos_parport)
if (list_empty(&mos_parport->deferred_urbs)) {
spin_unlock_irqrestore(&mos_parport->listlock, flags);
mutex_unlock(&mos_parport->serial->disc_mutex);
- dbg("%s: deferred_urbs list empty", __func__);
+ dev_dbg(dev, "%s: deferred_urbs list empty\n", __func__);
return;
}
/* move contents of deferred_urbs list to active_urbs list and submit */
list_for_each_safe(cursor, next, &mos_parport->deferred_urbs)
list_move_tail(cursor, &mos_parport->active_urbs);
- list_for_each_entry(urbtrack, &mos_parport->active_urbs,
+ list_for_each_entry_safe(urbtrack, tmp, &mos_parport->active_urbs,
urblist_entry) {
ret_val = usb_submit_urb(urbtrack->urb, GFP_ATOMIC);
- dbg("%s: urb submitted", __func__);
+ dev_dbg(dev, "%s: urb submitted\n", __func__);
if (ret_val) {
- dev_err(&mos_parport->serial->dev->dev,
- "usb_submit_urb() failed: %d", ret_val);
+ dev_err(dev, "usb_submit_urb() failed: %d\n", ret_val);
list_del(&urbtrack->urblist_entry);
kref_put(&urbtrack->ref_count, destroy_urbtracker);
}
@@ -335,9 +339,9 @@ static void async_complete(struct urb *urb)
{
struct urbtracker *urbtrack = urb->context;
int status = urb->status;
- dbg("%s called", __func__);
+
if (unlikely(status))
- dbg("%s - nonzero urb status received: %d", __func__, status);
+ dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __func__, status);
/* remove the urbtracker from the active_urbs list */
spin_lock(&urbtrack->mos_parport->listlock);
@@ -352,33 +356,35 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
struct urbtracker *urbtrack;
int ret_val;
unsigned long flags;
- struct usb_ctrlrequest setup;
struct usb_serial *serial = mos_parport->serial;
struct usb_device *usbdev = serial->dev;
- dbg("%s called", __func__);
/* create and initialize the control urb and containing urbtracker */
urbtrack = kmalloc(sizeof(struct urbtracker), GFP_ATOMIC);
- if (urbtrack == NULL) {
- dev_err(&usbdev->dev, "out of memory");
+ if (!urbtrack)
return -ENOMEM;
- }
+
kref_get(&mos_parport->ref_count);
urbtrack->mos_parport = mos_parport;
urbtrack->urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (urbtrack->urb == NULL) {
- dev_err(&usbdev->dev, "out of urbs");
+ if (!urbtrack->urb) {
kfree(urbtrack);
return -ENOMEM;
}
- setup.bRequestType = (__u8)0x40;
- setup.bRequest = (__u8)0x0e;
- setup.wValue = get_reg_value(reg, dummy);
- setup.wIndex = get_reg_index(reg);
- setup.wLength = 0;
+ urbtrack->setup = kmalloc(sizeof(*urbtrack->setup), GFP_ATOMIC);
+ if (!urbtrack->setup) {
+ usb_free_urb(urbtrack->urb);
+ kfree(urbtrack);
+ return -ENOMEM;
+ }
+ urbtrack->setup->bRequestType = (__u8)0x40;
+ urbtrack->setup->bRequest = (__u8)0x0e;
+ urbtrack->setup->wValue = cpu_to_le16(get_reg_value(reg, dummy));
+ urbtrack->setup->wIndex = cpu_to_le16(get_reg_index(reg));
+ urbtrack->setup->wLength = 0;
usb_fill_control_urb(urbtrack->urb, usbdev,
usb_sndctrlpipe(usbdev, 0),
- (unsigned char *)&setup,
+ (unsigned char *)urbtrack->setup,
NULL, 0, async_complete, urbtrack);
kref_init(&urbtrack->ref_count);
INIT_LIST_HEAD(&urbtrack->urblist_entry);
@@ -393,7 +399,7 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
&mos_parport->deferred_urbs);
spin_unlock_irqrestore(&mos_parport->listlock, flags);
tasklet_schedule(&mos_parport->urb_tasklet);
- dbg("tasklet scheduled");
+ dev_dbg(&usbdev->dev, "tasklet scheduled\n");
return 0;
}
@@ -412,7 +418,7 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
mutex_unlock(&serial->disc_mutex);
if (ret_val) {
dev_err(&usbdev->dev,
- "%s: submit_urb() failed: %d", __func__, ret_val);
+ "%s: submit_urb() failed: %d\n", __func__, ret_val);
spin_lock_irqsave(&mos_parport->listlock, flags);
list_del(&urbtrack->urblist_entry);
spin_unlock_irqrestore(&mos_parport->listlock, flags);
@@ -431,7 +437,7 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
* not called the release function yet because someone has a serial port open.
* The shared release_lock prevents the first, and the mutex and disconnected
* flag maintained by usbserial covers the second. We also use the msg_pending
- * flag to ensure that all synchronous usb messgage calls have completed before
+ * flag to ensure that all synchronous usb message calls have completed before
* our release function can return.
*/
static int parport_prologue(struct parport *pp)
@@ -446,7 +452,7 @@ static int parport_prologue(struct parport *pp)
return -1;
}
mos_parport->msg_pending = true; /* synch usb call pending */
- INIT_COMPLETION(mos_parport->syncmsg_compl);
+ reinit_completion(&mos_parport->syncmsg_compl);
spin_unlock(&release_lock);
mutex_lock(&mos_parport->serial->disc_mutex);
@@ -462,7 +468,7 @@ static int parport_prologue(struct parport *pp)
}
/*
- * This is the the common bottom part of all parallel port functions that send
+ * This is the common bottom part of all parallel port functions that send
* synchronous messages to the device.
*/
static inline void parport_epilogue(struct parport *pp)
@@ -476,7 +482,7 @@ static inline void parport_epilogue(struct parport *pp)
static void parport_mos7715_write_data(struct parport *pp, unsigned char d)
{
struct mos7715_parport *mos_parport = pp->private_data;
- dbg("%s called: %2.2x", __func__, d);
+
if (parport_prologue(pp) < 0)
return;
mos7715_change_mode(mos_parport, SPP);
@@ -488,7 +494,7 @@ static unsigned char parport_mos7715_read_data(struct parport *pp)
{
struct mos7715_parport *mos_parport = pp->private_data;
unsigned char d;
- dbg("%s called", __func__);
+
if (parport_prologue(pp) < 0)
return 0;
read_mos_reg(mos_parport->serial, dummy, DPR, &d);
@@ -500,7 +506,7 @@ static void parport_mos7715_write_control(struct parport *pp, unsigned char d)
{
struct mos7715_parport *mos_parport = pp->private_data;
__u8 data;
- dbg("%s called: %2.2x", __func__, d);
+
if (parport_prologue(pp) < 0)
return;
data = ((__u8)d & 0x0f) | (mos_parport->shadowDCR & 0xf0);
@@ -513,7 +519,7 @@ static unsigned char parport_mos7715_read_control(struct parport *pp)
{
struct mos7715_parport *mos_parport = pp->private_data;
__u8 dcr;
- dbg("%s called", __func__);
+
spin_lock(&release_lock);
mos_parport = pp->private_data;
if (unlikely(mos_parport == NULL)) {
@@ -531,7 +537,7 @@ static unsigned char parport_mos7715_frob_control(struct parport *pp,
{
struct mos7715_parport *mos_parport = pp->private_data;
__u8 dcr;
- dbg("%s called", __func__);
+
mask &= 0x0f;
val &= 0x0f;
if (parport_prologue(pp) < 0)
@@ -547,7 +553,7 @@ static unsigned char parport_mos7715_read_status(struct parport *pp)
{
unsigned char status;
struct mos7715_parport *mos_parport = pp->private_data;
- dbg("%s called", __func__);
+
spin_lock(&release_lock);
mos_parport = pp->private_data;
if (unlikely(mos_parport == NULL)) { /* release called */
@@ -561,17 +567,16 @@ static unsigned char parport_mos7715_read_status(struct parport *pp)
static void parport_mos7715_enable_irq(struct parport *pp)
{
- dbg("%s called", __func__);
}
+
static void parport_mos7715_disable_irq(struct parport *pp)
{
- dbg("%s called", __func__);
}
static void parport_mos7715_data_forward(struct parport *pp)
{
struct mos7715_parport *mos_parport = pp->private_data;
- dbg("%s called", __func__);
+
if (parport_prologue(pp) < 0)
return;
mos7715_change_mode(mos_parport, PS2);
@@ -583,7 +588,7 @@ static void parport_mos7715_data_forward(struct parport *pp)
static void parport_mos7715_data_reverse(struct parport *pp)
{
struct mos7715_parport *mos_parport = pp->private_data;
- dbg("%s called", __func__);
+
if (parport_prologue(pp) < 0)
return;
mos7715_change_mode(mos_parport, PS2);
@@ -595,7 +600,6 @@ static void parport_mos7715_data_reverse(struct parport *pp)
static void parport_mos7715_init_state(struct pardevice *dev,
struct parport_state *s)
{
- dbg("%s called", __func__);
s->u.pc.ctr = DCR_INIT_VAL;
s->u.pc.ecr = ECR_INIT_VAL;
}
@@ -605,7 +609,7 @@ static void parport_mos7715_save_state(struct parport *pp,
struct parport_state *s)
{
struct mos7715_parport *mos_parport;
- dbg("%s called", __func__);
+
spin_lock(&release_lock);
mos_parport = pp->private_data;
if (unlikely(mos_parport == NULL)) { /* release called */
@@ -622,7 +626,7 @@ static void parport_mos7715_restore_state(struct parport *pp,
struct parport_state *s)
{
struct mos7715_parport *mos_parport;
- dbg("%s called", __func__);
+
spin_lock(&release_lock);
mos_parport = pp->private_data;
if (unlikely(mos_parport == NULL)) { /* release called */
@@ -641,7 +645,7 @@ static size_t parport_mos7715_write_compat(struct parport *pp,
int retval;
struct mos7715_parport *mos_parport = pp->private_data;
int actual_len;
- dbg("%s called: %u chars", __func__, (unsigned int)len);
+
if (parport_prologue(pp) < 0)
return 0;
mos7715_change_mode(mos_parport, PPF);
@@ -652,7 +656,7 @@ static size_t parport_mos7715_write_compat(struct parport *pp,
parport_epilogue(pp);
if (retval) {
dev_err(&mos_parport->serial->dev->dev,
- "mos7720: usb_bulk_msg() failed: %d", retval);
+ "mos7720: usb_bulk_msg() failed: %d\n", retval);
return 0;
}
return actual_len;
@@ -695,10 +699,9 @@ static int mos7715_parport_init(struct usb_serial *serial)
/* allocate and initialize parallel port control struct */
mos_parport = kzalloc(sizeof(struct mos7715_parport), GFP_KERNEL);
- if (mos_parport == NULL) {
- dbg("mos7715_parport_init: kzalloc failed");
+ if (!mos_parport)
return -ENOMEM;
- }
+
mos_parport->msg_pending = false;
kref_init(&mos_parport->ref_count);
spin_lock_init(&mos_parport->listlock);
@@ -749,6 +752,7 @@ static void mos7720_interrupt_callback(struct urb *urb)
int result;
int length;
int status = urb->status;
+ struct device *dev = &urb->dev->dev;
__u8 *data;
__u8 sp1;
__u8 sp2;
@@ -761,12 +765,10 @@ static void mos7720_interrupt_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__,
- status);
+ dev_dbg(dev, "%s - urb shutting down with status: %d\n", __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __func__,
- status);
+ dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status);
goto exit;
}
@@ -783,7 +785,7 @@ static void mos7720_interrupt_callback(struct urb *urb)
* oneukum 2007-03-14 */
if (unlikely(length != 4)) {
- dbg("Wrong data !!!");
+ dev_dbg(dev, "Wrong data !!!\n");
return;
}
@@ -792,31 +794,29 @@ static void mos7720_interrupt_callback(struct urb *urb)
if ((sp1 | sp2) & 0x01) {
/* No Interrupt Pending in both the ports */
- dbg("No Interrupt !!!");
+ dev_dbg(dev, "No Interrupt !!!\n");
} else {
switch (sp1 & 0x0f) {
case SERIAL_IIR_RLS:
- dbg("Serial Port 1: Receiver status error or address "
- "bit detected in 9-bit mode\n");
+ dev_dbg(dev, "Serial Port 1: Receiver status error or address bit detected in 9-bit mode\n");
break;
case SERIAL_IIR_CTI:
- dbg("Serial Port 1: Receiver time out");
+ dev_dbg(dev, "Serial Port 1: Receiver time out\n");
break;
case SERIAL_IIR_MS:
- /* dbg("Serial Port 1: Modem status change"); */
+ /* dev_dbg(dev, "Serial Port 1: Modem status change\n"); */
break;
}
switch (sp2 & 0x0f) {
case SERIAL_IIR_RLS:
- dbg("Serial Port 2: Receiver status error or address "
- "bit detected in 9-bit mode");
+ dev_dbg(dev, "Serial Port 2: Receiver status error or address bit detected in 9-bit mode\n");
break;
case SERIAL_IIR_CTI:
- dbg("Serial Port 2: Receiver time out");
+ dev_dbg(dev, "Serial Port 2: Receiver time out\n");
break;
case SERIAL_IIR_MS:
- /* dbg("Serial Port 2: Modem status change"); */
+ /* dev_dbg(dev, "Serial Port 2: Modem status change\n"); */
break;
}
}
@@ -824,9 +824,7 @@ static void mos7720_interrupt_callback(struct urb *urb)
exit:
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
- dev_err(&urb->dev->dev,
- "%s - Error %d submitting control urb\n",
- __func__, result);
+ dev_err(dev, "%s - Error %d submitting control urb\n", __func__, result);
}
/*
@@ -839,6 +837,7 @@ static void mos7715_interrupt_callback(struct urb *urb)
int result;
int length;
int status = urb->status;
+ struct device *dev = &urb->dev->dev;
__u8 *data;
__u8 iir;
@@ -851,12 +850,10 @@ static void mos7715_interrupt_callback(struct urb *urb)
case -ESHUTDOWN:
case -ENODEV:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__,
- status);
+ dev_dbg(dev, "%s - urb shutting down with status: %d\n", __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __func__,
- status);
+ dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status);
goto exit;
}
@@ -870,7 +867,7 @@ static void mos7715_interrupt_callback(struct urb *urb)
* Byte 4: FIFO status for both */
if (unlikely(length != 4)) {
- dbg("Wrong data !!!");
+ dev_dbg(dev, "Wrong data !!!\n");
return;
}
@@ -878,14 +875,13 @@ static void mos7715_interrupt_callback(struct urb *urb)
if (!(iir & 0x01)) { /* serial port interrupt pending */
switch (iir & 0x0f) {
case SERIAL_IIR_RLS:
- dbg("Serial Port: Receiver status error or address "
- "bit detected in 9-bit mode\n");
+ dev_dbg(dev, "Serial Port: Receiver status error or address bit detected in 9-bit mode\n");
break;
case SERIAL_IIR_CTI:
- dbg("Serial Port: Receiver time out");
+ dev_dbg(dev, "Serial Port: Receiver time out\n");
break;
case SERIAL_IIR_MS:
- /* dbg("Serial Port: Modem status change"); */
+ /* dev_dbg(dev, "Serial Port: Modem status change\n"); */
break;
}
}
@@ -903,9 +899,7 @@ static void mos7715_interrupt_callback(struct urb *urb)
exit:
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
- dev_err(&urb->dev->dev,
- "%s - Error %d submitting control urb\n",
- __func__, result);
+ dev_err(dev, "%s - Error %d submitting control urb\n", __func__, result);
}
/*
@@ -918,39 +912,28 @@ static void mos7720_bulk_in_callback(struct urb *urb)
int retval;
unsigned char *data ;
struct usb_serial_port *port;
- struct tty_struct *tty;
int status = urb->status;
if (status) {
- dbg("nonzero read bulk status received: %d", status);
+ dev_dbg(&urb->dev->dev, "nonzero read bulk status received: %d\n", status);
return;
}
port = urb->context;
- dbg("Entering...%s", __func__);
+ dev_dbg(&port->dev, "Entering...%s\n", __func__);
data = urb->transfer_buffer;
- tty = tty_port_tty_get(&port->port);
- if (tty && urb->actual_length) {
- tty_insert_flip_string(tty, data, urb->actual_length);
- tty_flip_buffer_push(tty);
- }
- tty_kref_put(tty);
-
- if (!port->read_urb) {
- dbg("URB KILLED !!!");
- return;
+ if (urb->actual_length) {
+ tty_insert_flip_string(&port->port, data, urb->actual_length);
+ tty_flip_buffer_push(&port->port);
}
if (port->read_urb->status != -EINPROGRESS) {
- port->read_urb->dev = port->serial->dev;
-
retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (retval)
- dbg("usb_submit_urb(read bulk) failed, retval = %d",
- retval);
+ dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, retval = %d\n", retval);
}
}
@@ -962,25 +945,21 @@ static void mos7720_bulk_in_callback(struct urb *urb)
static void mos7720_bulk_out_data_callback(struct urb *urb)
{
struct moschip_port *mos7720_port;
- struct tty_struct *tty;
int status = urb->status;
if (status) {
- dbg("nonzero write bulk status received:%d", status);
+ dev_dbg(&urb->dev->dev, "nonzero write bulk status received:%d\n", status);
return;
}
mos7720_port = urb->context;
if (!mos7720_port) {
- dbg("NULL mos7720_port pointer");
+ dev_dbg(&urb->dev->dev, "NULL mos7720_port pointer\n");
return ;
}
- tty = tty_port_tty_get(&mos7720_port->port->port);
-
- if (tty && mos7720_port->open)
- tty_wakeup(tty);
- tty_kref_put(tty);
+ if (mos7720_port->open)
+ tty_port_tty_wakeup(&mos7720_port->port->port);
}
/*
@@ -1014,7 +993,6 @@ static int mos77xx_calc_num_ports(struct usb_serial *serial)
static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct usb_serial *serial;
- struct usb_serial_port *port0;
struct urb *urb;
struct moschip_port *mos7720_port;
int response;
@@ -1029,8 +1007,6 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
if (mos7720_port == NULL)
return -ENODEV;
- port0 = serial->port[0];
-
usb_clear_halt(serial->dev, port->write_urb->pipe);
usb_clear_halt(serial->dev, port->read_urb->pipe);
@@ -1038,18 +1014,12 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
for (j = 0; j < NUM_URBS; ++j) {
urb = usb_alloc_urb(0, GFP_KERNEL);
mos7720_port->write_urb_pool[j] = urb;
-
- if (urb == NULL) {
- dev_err(&port->dev, "No more urbs???\n");
+ if (!urb)
continue;
- }
urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
GFP_KERNEL);
if (!urb->transfer_buffer) {
- dev_err(&port->dev,
- "%s-out of memory for urb buffers.\n",
- __func__);
usb_free_urb(mos7720_port->write_urb_pool[j]);
mos7720_port->write_urb_pool[j] = NULL;
continue;
@@ -1074,12 +1044,10 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
*
* 0x08 : SP1/2 Control Reg
*/
- port_number = port->number - port->serial->minor;
+ port_number = port->port_number;
read_mos_reg(serial, port_number, LSR, &data);
- dbg("SS::%p LSR:%x", mos7720_port, data);
-
- dbg("Check:Sending Command ..........");
+ dev_dbg(&port->dev, "SS::%p LSR:%x\n", mos7720_port, data);
write_mos_reg(serial, dummy, SP1_REG, 0x02);
write_mos_reg(serial, dummy, SP2_REG, 0x02);
@@ -1095,7 +1063,7 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
write_mos_reg(serial, port_number, SP_CONTROL_REG, 0x00);
read_mos_reg(serial, dummy, SP_CONTROL_REG, &data);
- data = data | (port->number - port->serial->minor + 1);
+ data = data | (port->port_number + 1);
write_mos_reg(serial, dummy, SP_CONTROL_REG, data);
mos7720_port->shadowLCR = 0x83;
write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR);
@@ -1110,9 +1078,6 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
dev_err(&port->dev, "%s - Error %d submitting read urb\n",
__func__, response);
- /* initialize our icount structure */
- memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount));
-
/* initialize our port settings */
mos7720_port->shadowMCR = UART_MCR_OUT2; /* Must set to enable ints! */
@@ -1138,20 +1103,16 @@ static int mos7720_chars_in_buffer(struct tty_struct *tty)
int chars = 0;
struct moschip_port *mos7720_port;
- dbg("%s:entering ...........", __func__);
-
mos7720_port = usb_get_serial_port_data(port);
- if (mos7720_port == NULL) {
- dbg("%s:leaving ...........", __func__);
+ if (mos7720_port == NULL)
return 0;
- }
for (i = 0; i < NUM_URBS; ++i) {
if (mos7720_port->write_urb_pool[i] &&
mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
chars += URB_TRANSFER_BUFFER_SIZE;
}
- dbg("%s - returns %d", __func__, chars);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
return chars;
}
@@ -1161,8 +1122,6 @@ static void mos7720_close(struct usb_serial_port *port)
struct moschip_port *mos7720_port;
int j;
- dbg("mos7720_close:entering...");
-
serial = port->serial;
mos7720_port = usb_get_serial_port_data(port);
@@ -1182,24 +1141,13 @@ static void mos7720_close(struct usb_serial_port *port)
/* While closing port, shutdown all bulk read, write *
* and interrupt read if they exists, otherwise nop */
- dbg("Shutdown bulk write");
usb_kill_urb(port->write_urb);
- dbg("Shutdown bulk read");
usb_kill_urb(port->read_urb);
- mutex_lock(&serial->disc_mutex);
- /* these commands must not be issued if the device has
- * been disconnected */
- if (!serial->disconnected) {
- write_mos_reg(serial, port->number - port->serial->minor,
- MCR, 0x00);
- write_mos_reg(serial, port->number - port->serial->minor,
- IER, 0x00);
- }
- mutex_unlock(&serial->disc_mutex);
- mos7720_port->open = 0;
+ write_mos_reg(serial, port->port_number, MCR, 0x00);
+ write_mos_reg(serial, port->port_number, IER, 0x00);
- dbg("Leaving %s", __func__);
+ mos7720_port->open = 0;
}
static void mos7720_break(struct tty_struct *tty, int break_state)
@@ -1209,8 +1157,6 @@ static void mos7720_break(struct tty_struct *tty, int break_state)
struct usb_serial *serial;
struct moschip_port *mos7720_port;
- dbg("Entering %s", __func__);
-
serial = port->serial;
mos7720_port = usb_get_serial_port_data(port);
@@ -1223,8 +1169,7 @@ static void mos7720_break(struct tty_struct *tty, int break_state)
data = mos7720_port->shadowLCR & ~UART_LCR_SBC;
mos7720_port->shadowLCR = data;
- write_mos_reg(serial, port->number - port->serial->minor,
- LCR, mos7720_port->shadowLCR);
+ write_mos_reg(serial, port->port_number, LCR, mos7720_port->shadowLCR);
}
/*
@@ -1241,13 +1186,9 @@ static int mos7720_write_room(struct tty_struct *tty)
int room = 0;
int i;
- dbg("%s:entering ...........", __func__);
-
mos7720_port = usb_get_serial_port_data(port);
- if (mos7720_port == NULL) {
- dbg("%s:leaving ...........", __func__);
+ if (mos7720_port == NULL)
return -ENODEV;
- }
/* FIXME: Locking */
for (i = 0; i < NUM_URBS; ++i) {
@@ -1256,7 +1197,7 @@ static int mos7720_write_room(struct tty_struct *tty)
room += URB_TRANSFER_BUFFER_SIZE;
}
- dbg("%s - returns %d", __func__, room);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, room);
return room;
}
@@ -1273,15 +1214,11 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port,
struct urb *urb;
const unsigned char *current_position = data;
- dbg("%s:entering ...........", __func__);
-
serial = port->serial;
mos7720_port = usb_get_serial_port_data(port);
- if (mos7720_port == NULL) {
- dbg("mos7720_port is NULL");
+ if (mos7720_port == NULL)
return -ENODEV;
- }
/* try to find a free urb in the list */
urb = NULL;
@@ -1290,29 +1227,26 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port,
if (mos7720_port->write_urb_pool[i] &&
mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) {
urb = mos7720_port->write_urb_pool[i];
- dbg("URB:%d", i);
+ dev_dbg(&port->dev, "URB:%d\n", i);
break;
}
}
if (urb == NULL) {
- dbg("%s - no more free urbs", __func__);
+ dev_dbg(&port->dev, "%s - no more free urbs\n", __func__);
goto exit;
}
if (urb->transfer_buffer == NULL) {
urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
GFP_KERNEL);
- if (urb->transfer_buffer == NULL) {
- dev_err(&port->dev, "%s no more kernel memory...\n",
- __func__);
+ if (!urb->transfer_buffer)
goto exit;
- }
}
transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
memcpy(urb->transfer_buffer, current_position, transfer_size);
- usb_serial_debug_data(debug, &port->dev, __func__, transfer_size,
+ usb_serial_debug_data(&port->dev, __func__, transfer_size,
urb->transfer_buffer);
/* fill urb with data and submit */
@@ -1325,7 +1259,7 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port,
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
- dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+ dev_err_console(port, "%s - usb_submit_urb(write bulk) failed "
"with status = %d\n", __func__, status);
bytes_sent = status;
goto exit;
@@ -1342,20 +1276,16 @@ static void mos7720_throttle(struct tty_struct *tty)
struct moschip_port *mos7720_port;
int status;
- dbg("%s- port %d", __func__, port->number);
-
mos7720_port = usb_get_serial_port_data(port);
if (mos7720_port == NULL)
return;
if (!mos7720_port->open) {
- dbg("port not opened");
+ dev_dbg(&port->dev, "%s - port not opened\n", __func__);
return;
}
- dbg("%s: Entering ..........", __func__);
-
/* if we are implementing XON/XOFF, send the stop character */
if (I_IXOFF(tty)) {
unsigned char stop_char = STOP_CHAR(tty);
@@ -1365,10 +1295,10 @@ static void mos7720_throttle(struct tty_struct *tty)
}
/* if we are implementing RTS/CTS, toggle that line */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
mos7720_port->shadowMCR &= ~UART_MCR_RTS;
- write_mos_reg(port->serial, port->number - port->serial->minor,
- MCR, mos7720_port->shadowMCR);
+ write_mos_reg(port->serial, port->port_number, MCR,
+ mos7720_port->shadowMCR);
if (status != 0)
return;
}
@@ -1384,12 +1314,10 @@ static void mos7720_unthrottle(struct tty_struct *tty)
return;
if (!mos7720_port->open) {
- dbg("%s - port not opened", __func__);
+ dev_dbg(&port->dev, "%s - port not opened\n", __func__);
return;
}
- dbg("%s: Entering ..........", __func__);
-
/* if we are implementing XON/XOFF, send the start character */
if (I_IXOFF(tty)) {
unsigned char start_char = START_CHAR(tty);
@@ -1399,10 +1327,10 @@ static void mos7720_unthrottle(struct tty_struct *tty)
}
/* if we are implementing RTS/CTS, toggle that line */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
mos7720_port->shadowMCR |= UART_MCR_RTS;
- write_mos_reg(port->serial, port->number - port->serial->minor,
- MCR, mos7720_port->shadowMCR);
+ write_mos_reg(port->serial, port->port_number, MCR,
+ mos7720_port->shadowMCR);
if (status != 0)
return;
}
@@ -1425,8 +1353,8 @@ static int set_higher_rates(struct moschip_port *mos7720_port,
/***********************************************
* Init Sequence for higher rates
***********************************************/
- dbg("Sending Setting Commands ..........");
- port_number = port->number - port->serial->minor;
+ dev_dbg(&port->dev, "Sending Setting Commands ..........\n");
+ port_number = port->port_number;
write_mos_reg(serial, port_number, IER, 0x00);
write_mos_reg(serial, port_number, FCR, 0x00);
@@ -1494,7 +1422,7 @@ static struct divisor_table_entry divisor_table[] = {
* this function calculates the proper baud rate divisor for the specified
* baud rate.
*****************************************************************************/
-static int calc_baud_rate_divisor(int baudrate, int *divisor)
+static int calc_baud_rate_divisor(struct usb_serial_port *port, int baudrate, int *divisor)
{
int i;
__u16 custom;
@@ -1502,7 +1430,7 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor)
__u16 round;
- dbg("%s - %d", __func__, baudrate);
+ dev_dbg(&port->dev, "%s - %d\n", __func__, baudrate);
for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
if (divisor_table[i].baudrate == baudrate) {
@@ -1524,11 +1452,11 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor)
custom++;
*divisor = custom;
- dbg("Baud %d = %d", baudrate, custom);
+ dev_dbg(&port->dev, "Baud %d = %d\n", baudrate, custom);
return 0;
}
- dbg("Baud calculation Failed...");
+ dev_dbg(&port->dev, "Baud calculation Failed...\n");
return -EINVAL;
}
@@ -1552,13 +1480,11 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
port = mos7720_port->port;
serial = port->serial;
- dbg("%s: Entering ..........", __func__);
-
- number = port->number - port->serial->minor;
- dbg("%s - port = %d, baud = %d", __func__, port->number, baudrate);
+ number = port->port_number;
+ dev_dbg(&port->dev, "%s - baud = %d\n", __func__, baudrate);
/* Calculate the Divisor */
- status = calc_baud_rate_divisor(baudrate, &divisor);
+ status = calc_baud_rate_divisor(port, baudrate, &divisor);
if (status) {
dev_err(&port->dev, "%s - bad baud rate\n", __func__);
return status;
@@ -1605,23 +1531,19 @@ static void change_port_settings(struct tty_struct *tty,
port = mos7720_port->port;
serial = port->serial;
- port_number = port->number - port->serial->minor;
-
- dbg("%s - port %d", __func__, port->number);
+ port_number = port->port_number;
if (!mos7720_port->open) {
- dbg("%s - port not opened", __func__);
+ dev_dbg(&port->dev, "%s - port not opened\n", __func__);
return;
}
- dbg("%s: Entering ..........", __func__);
-
lData = UART_LCR_WLEN8;
lStop = 0x00; /* 1 stop bit */
lParity = 0x00; /* No parity */
- cflag = tty->termios->c_cflag;
- iflag = tty->termios->c_iflag;
+ cflag = tty->termios.c_cflag;
+ iflag = tty->termios.c_iflag;
/* Change the number of bits */
switch (cflag & CSIZE) {
@@ -1649,14 +1571,14 @@ static void change_port_settings(struct tty_struct *tty,
if (cflag & PARENB) {
if (cflag & PARODD) {
lParity = UART_LCR_PARITY;
- dbg("%s - parity = odd", __func__);
+ dev_dbg(&port->dev, "%s - parity = odd\n", __func__);
} else {
lParity = (UART_LCR_EPAR | UART_LCR_PARITY);
- dbg("%s - parity = even", __func__);
+ dev_dbg(&port->dev, "%s - parity = even\n", __func__);
}
} else {
- dbg("%s - parity = none", __func__);
+ dev_dbg(&port->dev, "%s - parity = none\n", __func__);
}
if (cflag & CMSPAR)
@@ -1665,10 +1587,10 @@ static void change_port_settings(struct tty_struct *tty,
/* Change the Stop bit */
if (cflag & CSTOPB) {
lStop = UART_LCR_STOP;
- dbg("%s - stop bits = 2", __func__);
+ dev_dbg(&port->dev, "%s - stop bits = 2\n", __func__);
} else {
lStop = 0x00;
- dbg("%s - stop bits = 1", __func__);
+ dev_dbg(&port->dev, "%s - stop bits = 1\n", __func__);
}
#define LCR_BITS_MASK 0x03 /* Mask for bits/char field */
@@ -1700,7 +1622,7 @@ static void change_port_settings(struct tty_struct *tty,
mos7720_port->shadowMCR |= (UART_MCR_XONANY);
/* To set hardware flow control to the specified *
* serial port, in SP1/2_CONTROL_REG */
- if (port->number)
+ if (port_number)
write_mos_reg(serial, dummy, SP_CONTROL_REG, 0x01);
else
write_mos_reg(serial, dummy, SP_CONTROL_REG, 0x02);
@@ -1714,7 +1636,7 @@ static void change_port_settings(struct tty_struct *tty,
baud = tty_get_baud_rate(tty);
if (!baud) {
/* pick a default, any default... */
- dbg("Picked default baud...");
+ dev_dbg(&port->dev, "Picked default baud...\n");
baud = 9600;
}
@@ -1725,7 +1647,7 @@ static void change_port_settings(struct tty_struct *tty,
return;
}
- dbg("%s - baud rate = %d", __func__, baud);
+ dev_dbg(&port->dev, "%s - baud rate = %d\n", __func__, baud);
status = send_cmd_write_baud_rate(mos7720_port, baud);
/* FIXME: needs to write actual resulting baud back not just
blindly do so */
@@ -1735,12 +1657,9 @@ static void change_port_settings(struct tty_struct *tty,
write_mos_reg(serial, port_number, IER, 0x0c);
if (port->read_urb->status != -EINPROGRESS) {
- port->read_urb->dev = serial->dev;
-
status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (status)
- dbg("usb_submit_urb(read bulk) failed, status = %d",
- status);
+ dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, status = %d\n", status);
}
}
@@ -1765,38 +1684,27 @@ static void mos7720_set_termios(struct tty_struct *tty,
return;
if (!mos7720_port->open) {
- dbg("%s - port not opened", __func__);
+ dev_dbg(&port->dev, "%s - port not opened\n", __func__);
return;
}
- dbg("%s\n", "setting termios - ASPIRE");
-
- cflag = tty->termios->c_cflag;
+ dev_dbg(&port->dev, "setting termios - ASPIRE\n");
- dbg("%s - cflag %08x iflag %08x", __func__,
- tty->termios->c_cflag,
- RELEVANT_IFLAG(tty->termios->c_iflag));
+ cflag = tty->termios.c_cflag;
- dbg("%s - old cflag %08x old iflag %08x", __func__,
- old_termios->c_cflag,
- RELEVANT_IFLAG(old_termios->c_iflag));
+ dev_dbg(&port->dev, "%s - cflag %08x iflag %08x\n", __func__,
+ tty->termios.c_cflag, RELEVANT_IFLAG(tty->termios.c_iflag));
- dbg("%s - port %d", __func__, port->number);
+ dev_dbg(&port->dev, "%s - old cflag %08x old iflag %08x\n", __func__,
+ old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
/* change the port settings to the new ones specified */
change_port_settings(tty, mos7720_port, old_termios);
- if (!port->read_urb) {
- dbg("%s", "URB KILLED !!!!!");
- return;
- }
-
if (port->read_urb->status != -EINPROGRESS) {
- port->read_urb->dev = serial->dev;
status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (status)
- dbg("usb_submit_urb(read bulk) failed, status = %d",
- status);
+ dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, status = %d\n", status);
}
}
@@ -1816,7 +1724,7 @@ static int get_lsr_info(struct tty_struct *tty,
struct usb_serial_port *port = tty->driver_data;
unsigned int result = 0;
unsigned char data = 0;
- int port_number = port->number - port->serial->minor;
+ int port_number = port->port_number;
int count;
count = mos7720_chars_in_buffer(tty);
@@ -1824,7 +1732,7 @@ static int get_lsr_info(struct tty_struct *tty,
read_mos_reg(port->serial, port_number, LSR, &data);
if ((data & (UART_LSR_TEMT | UART_LSR_THRE))
== (UART_LSR_TEMT | UART_LSR_THRE)) {
- dbg("%s -- Empty", __func__);
+ dev_dbg(&port->dev, "%s -- Empty\n", __func__);
result = TIOCSER_TEMT;
}
}
@@ -1833,7 +1741,7 @@ static int get_lsr_info(struct tty_struct *tty,
return 0;
}
-static int mos7720_tiocmget(struct tty_struct *tty, struct file *file)
+static int mos7720_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
@@ -1841,8 +1749,6 @@ static int mos7720_tiocmget(struct tty_struct *tty, struct file *file)
unsigned int mcr ;
unsigned int msr ;
- dbg("%s - port %d", __func__, port->number);
-
mcr = mos7720_port->shadowMCR;
msr = mos7720_port->shadowMSR;
@@ -1853,19 +1759,15 @@ static int mos7720_tiocmget(struct tty_struct *tty, struct file *file)
| ((msr & UART_MSR_RI) ? TIOCM_RI : 0) /* 0x080 */
| ((msr & UART_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */
- dbg("%s -- %x", __func__, result);
-
return result;
}
-static int mos7720_tiocmset(struct tty_struct *tty, struct file *file,
+static int mos7720_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
unsigned int mcr ;
- dbg("%s - port %d", __func__, port->number);
- dbg("he was at tiocmget");
mcr = mos7720_port->shadowMCR;
@@ -1884,36 +1786,9 @@ static int mos7720_tiocmset(struct tty_struct *tty, struct file *file,
mcr &= ~UART_MCR_LOOP;
mos7720_port->shadowMCR = mcr;
- write_mos_reg(port->serial, port->number - port->serial->minor,
- MCR, mos7720_port->shadowMCR);
-
- return 0;
-}
-
-static int mos7720_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct moschip_port *mos7720_port;
- struct async_icount cnow;
+ write_mos_reg(port->serial, port->port_number, MCR,
+ mos7720_port->shadowMCR);
- mos7720_port = usb_get_serial_port_data(port);
- cnow = mos7720_port->icount;
-
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
-
- dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
- port->number, icount->rx, icount->tx);
return 0;
}
@@ -1956,8 +1831,8 @@ static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
}
mos7720_port->shadowMCR = mcr;
- write_mos_reg(port->serial, port->number - port->serial->minor,
- MCR, mos7720_port->shadowMCR);
+ write_mos_reg(port->serial, port->port_number, MCR,
+ mos7720_port->shadowMCR);
return 0;
}
@@ -1973,8 +1848,8 @@ static int get_serial_info(struct moschip_port *mos7720_port,
memset(&tmp, 0, sizeof(tmp));
tmp.type = PORT_16550A;
- tmp.line = mos7720_port->port->serial->minor;
- tmp.port = mos7720_port->port->number;
+ tmp.line = mos7720_port->port->minor;
+ tmp.port = mos7720_port->port->port_number;
tmp.irq = 0;
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
@@ -1987,60 +1862,33 @@ static int get_serial_info(struct moschip_port *mos7720_port,
return 0;
}
-static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
+static int mos7720_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7720_port;
- struct async_icount cnow;
- struct async_icount cprev;
mos7720_port = usb_get_serial_port_data(port);
if (mos7720_port == NULL)
return -ENODEV;
- dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
-
switch (cmd) {
case TIOCSERGETLSR:
- dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
+ dev_dbg(&port->dev, "%s TIOCSERGETLSR\n", __func__);
return get_lsr_info(tty, mos7720_port,
(unsigned int __user *)arg);
- return 0;
/* FIXME: These should be using the mode methods */
case TIOCMBIS:
case TIOCMBIC:
- dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET",
- __func__, port->number);
+ dev_dbg(&port->dev, "%s TIOCMSET/TIOCMBIC/TIOCMSET\n", __func__);
return set_modem_info(mos7720_port, cmd,
(unsigned int __user *)arg);
case TIOCGSERIAL:
- dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
+ dev_dbg(&port->dev, "%s TIOCGSERIAL\n", __func__);
return get_serial_info(mos7720_port,
(struct serial_struct __user *)arg);
-
- case TIOCMIWAIT:
- dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
- cprev = mos7720_port->icount;
- while (1) {
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = mos7720_port->icount;
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
- return 0;
- }
- cprev = cnow;
- }
- /* NOTREACHED */
- break;
}
return -ENOIOCTLCMD;
@@ -2048,20 +1896,12 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
static int mos7720_startup(struct usb_serial *serial)
{
- struct moschip_port *mos7720_port;
struct usb_device *dev;
- int i;
char data;
- u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
+ u16 product;
int ret_val;
- dbg("%s: Entering ..........", __func__);
-
- if (!serial) {
- dbg("Invalid Handler");
- return -ENODEV;
- }
-
+ product = le16_to_cpu(serial->dev->descriptor.idProduct);
dev = serial->dev;
/*
@@ -2087,32 +1927,9 @@ static int mos7720_startup(struct usb_serial *serial)
serial->port[1]->interrupt_in_buffer = NULL;
}
-
- /* set up serial port private structures */
- for (i = 0; i < serial->num_ports; ++i) {
- mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
- if (mos7720_port == NULL) {
- dev_err(&dev->dev, "%s - Out of memory\n", __func__);
- return -ENOMEM;
- }
-
- /* Initialize all port interrupt end point to port 0 int
- * endpoint. Our device has only one interrupt endpoint
- * common to all ports */
- serial->port[i]->interrupt_in_endpointAddress =
- serial->port[0]->interrupt_in_endpointAddress;
-
- mos7720_port->port = serial->port[i];
- usb_set_serial_port_data(serial->port[i], mos7720_port);
-
- dbg("port number is %d", serial->port[i]->number);
- dbg("serial number is %d", serial->minor);
- }
-
-
/* setting configuration feature to one */
usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ);
+ (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000);
/* start the interrupt urb */
ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL);
@@ -2130,15 +1947,13 @@ static int mos7720_startup(struct usb_serial *serial)
#endif
/* LSR For Port 1 */
read_mos_reg(serial, 0, LSR, &data);
- dbg("LSR:%x", data);
+ dev_dbg(&dev->dev, "LSR:%x\n", data);
return 0;
}
static void mos7720_release(struct usb_serial *serial)
{
- int i;
-
#ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
/* close the parallel port */
@@ -2157,7 +1972,7 @@ static void mos7720_release(struct usb_serial *serial)
/* wait for synchronous usb calls to return */
if (mos_parport->msg_pending)
wait_for_completion_timeout(&mos_parport->syncmsg_compl,
- MOS_WDR_TIMEOUT);
+ msecs_to_jiffies(MOS_WDR_TIMEOUT));
parport_remove_port(mos_parport->pp);
usb_set_serial_data(serial, NULL);
@@ -2177,18 +1992,37 @@ static void mos7720_release(struct usb_serial *serial)
kref_put(&mos_parport->ref_count, destroy_mos_parport);
}
#endif
- /* free private structure allocated for serial port */
- for (i = 0; i < serial->num_ports; ++i)
- kfree(usb_get_serial_port_data(serial->port[i]));
}
-static struct usb_driver usb_driver = {
- .name = "moschip7720",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = moschip_port_id_table,
- .no_dynamic_id = 1,
-};
+static int mos7720_port_probe(struct usb_serial_port *port)
+{
+ struct moschip_port *mos7720_port;
+
+ mos7720_port = kzalloc(sizeof(*mos7720_port), GFP_KERNEL);
+ if (!mos7720_port)
+ return -ENOMEM;
+
+ /* Initialize all port interrupt end point to port 0 int endpoint.
+ * Our device has only one interrupt endpoint common to all ports.
+ */
+ port->interrupt_in_endpointAddress =
+ port->serial->port[0]->interrupt_in_endpointAddress;
+ mos7720_port->port = port;
+
+ usb_set_serial_port_data(port, mos7720_port);
+
+ return 0;
+}
+
+static int mos7720_port_remove(struct usb_serial_port *port)
+{
+ struct moschip_port *mos7720_port;
+
+ mos7720_port = usb_get_serial_port_data(port);
+ kfree(mos7720_port);
+
+ return 0;
+}
static struct usb_serial_driver moschip7720_2port_driver = {
.driver = {
@@ -2196,8 +2030,7 @@ static struct usb_serial_driver moschip7720_2port_driver = {
.name = "moschip7720",
},
.description = "Moschip 2 port adapter",
- .usb_driver = &usb_driver,
- .id_table = moschip_port_id_table,
+ .id_table = id_table,
.calc_num_ports = mos77xx_calc_num_ports,
.open = mos7720_open,
.close = mos7720_close,
@@ -2206,10 +2039,11 @@ static struct usb_serial_driver moschip7720_2port_driver = {
.probe = mos77xx_probe,
.attach = mos7720_startup,
.release = mos7720_release,
+ .port_probe = mos7720_port_probe,
+ .port_remove = mos7720_port_remove,
.ioctl = mos7720_ioctl,
.tiocmget = mos7720_tiocmget,
.tiocmset = mos7720_tiocmset,
- .get_icount = mos7720_get_icount,
.set_termios = mos7720_set_termios,
.write = mos7720_write,
.write_room = mos7720_write_room,
@@ -2219,47 +2053,12 @@ static struct usb_serial_driver moschip7720_2port_driver = {
.read_int_callback = NULL /* dynamically assigned in probe() */
};
-static int __init moschip7720_init(void)
-{
- int retval;
-
- dbg("%s: Entering ..........", __func__);
-
- /* Register with the usb serial */
- retval = usb_serial_register(&moschip7720_2port_driver);
- if (retval)
- goto failed_port_device_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- /* Register with the usb */
- retval = usb_register(&usb_driver);
- if (retval)
- goto failed_usb_register;
-
- return 0;
-
-failed_usb_register:
- usb_serial_deregister(&moschip7720_2port_driver);
-
-failed_port_device_register:
- return retval;
-}
-
-static void __exit moschip7720_exit(void)
-{
- usb_deregister(&usb_driver);
- usb_serial_deregister(&moschip7720_2port_driver);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &moschip7720_2port_driver, NULL
+};
-module_init(moschip7720_init);
-module_exit(moschip7720_exit);
+module_usb_serial_driver(serial_drivers, id_table);
-/* Module information */
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 5627993f9e4..393be562d87 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -24,7 +24,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -35,10 +34,6 @@
#include <linux/usb/serial.h>
#include <linux/uaccess.h>
-/*
- * Version Information
- */
-#define DRIVER_VERSION "1.3.2"
#define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver"
/*
@@ -82,8 +77,7 @@
* Defines used for sending commands to port
*/
-#define WAIT_FOR_EVER (HZ * 0) /* timeout urb is wait for ever */
-#define MOS_WDR_TIMEOUT (HZ * 5) /* default urb timeout */
+#define MOS_WDR_TIMEOUT 5000 /* default urb timeout */
#define MOS_PORT1 0x0200
#define MOS_PORT2 0x0300
@@ -114,10 +108,10 @@
#define USB_VENDOR_ID_MOSCHIP 0x9710
#define MOSCHIP_DEVICE_ID_7840 0x7840
#define MOSCHIP_DEVICE_ID_7820 0x7820
+#define MOSCHIP_DEVICE_ID_7810 0x7810
/* The native component can have its vendor/device id's overridden
* in vendor-specific implementations. Such devices can be handled
- * by making a change here, in moschip_port_id_table, and in
- * moschip_id_table_combined
+ * by making a change here, in id_table.
*/
#define USB_VENDOR_ID_BANDB 0x0856
#define BANDB_DEVICE_ID_USO9ML2_2 0xAC22
@@ -174,6 +168,7 @@
#define CLK_MULTI_REGISTER ((__u16)(0x02))
#define CLK_START_VALUE_REGISTER ((__u16)(0x03))
+#define GPIO_REGISTER ((__u16)(0x07))
#define SERIAL_LCR_DLAB ((__u16)(0x0080))
@@ -183,31 +178,19 @@
#define NUM_URBS 16 /* URB Count */
#define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */
+/* LED on/off milliseconds*/
+#define LED_ON_MS 500
+#define LED_OFF_MS 500
-static const struct usb_device_id moschip_port_id_table[] = {
- {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
- {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)},
- {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
- {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
- {} /* terminating entry */
+enum mos7840_flag {
+ MOS7840_FLAG_CTRL_BUSY,
+ MOS7840_FLAG_LED_BUSY,
};
-static const struct usb_device_id moschip_id_table_combined[] __devinitconst = {
+static const struct usb_device_id id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
+ {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7810)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)},
@@ -225,8 +208,7 @@ static const struct usb_device_id moschip_id_table_combined[] __devinitconst = {
{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
{} /* terminating entry */
};
-
-MODULE_DEVICE_TABLE(usb, moschip_id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table);
/* This structure holds all of the local port information */
@@ -234,16 +216,10 @@ struct moschip_port {
int port_num; /*Actual port number in the device(1,2,etc) */
struct urb *write_urb; /* write URB for this port */
struct urb *read_urb; /* read URB for this port */
- struct urb *int_urb;
__u8 shadowLCR; /* last LCR value received */
__u8 shadowMCR; /* last MCR value received */
char open;
char open_ports;
- char zombie;
- wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */
- wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */
- int delta_msr_cond;
- struct async_icount icount;
struct usb_serial_port *port; /* loop back to the owner of this object */
/* Offsets */
@@ -260,10 +236,16 @@ struct moschip_port {
struct urb *write_urb_pool[NUM_URBS];
char busy[NUM_URBS];
bool read_urb_busy;
-};
+ /* For device(s) with LED indicator */
+ bool has_led;
+ struct timer_list led_timer1; /* Timer for LED on */
+ struct timer_list led_timer2; /* Timer for LED off */
+ struct urb *led_urb;
+ struct usb_ctrlrequest *led_dr;
-static int debug;
+ unsigned long flags;
+};
/*
* mos7840_set_reg_sync
@@ -276,7 +258,7 @@ static int mos7840_set_reg_sync(struct usb_serial_port *port, __u16 reg,
{
struct usb_device *dev = port->serial->dev;
val = val & 0x00ff;
- dbg("mos7840_set_reg_sync offset is %x, value %x", reg, val);
+ dev_dbg(&port->dev, "mos7840_set_reg_sync offset is %x, value %x\n", reg, val);
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,
MCS_WR_RTYPE, val, reg, NULL, 0,
@@ -304,7 +286,7 @@ static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg,
MCS_RD_RTYPE, 0, reg, buf, VENDOR_READ_LENGTH,
MOS_WDR_TIMEOUT);
*val = buf[0];
- dbg("mos7840_get_reg_sync offset is %x, return val %x", reg, *val);
+ dev_dbg(&port->dev, "%s offset is %x, return val %x\n", __func__, reg, *val);
kfree(buf);
return ret;
@@ -325,23 +307,15 @@ static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg,
/* For the UART control registers, the application number need
to be Or'ed */
if (port->serial->num_ports == 4) {
- val |= (((__u16) port->number -
- (__u16) (port->serial->minor)) + 1) << 8;
- dbg("mos7840_set_uart_reg application number is %x", val);
+ val |= ((__u16)port->port_number + 1) << 8;
} else {
- if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {
- val |= (((__u16) port->number -
- (__u16) (port->serial->minor)) + 1) << 8;
- dbg("mos7840_set_uart_reg application number is %x",
- val);
+ if (port->port_number == 0) {
+ val |= ((__u16)port->port_number + 1) << 8;
} else {
- val |=
- (((__u16) port->number -
- (__u16) (port->serial->minor)) + 2) << 8;
- dbg("mos7840_set_uart_reg application number is %x",
- val);
+ val |= ((__u16)port->port_number + 2) << 8;
}
}
+ dev_dbg(&port->dev, "%s application number is %x\n", __func__, val);
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,
MCS_WR_RTYPE, val, reg, NULL, 0,
MOS_WDR_TIMEOUT);
@@ -365,27 +339,17 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg,
if (!buf)
return -ENOMEM;
- /* dbg("application number is %4x",
- (((__u16)port->number - (__u16)(port->serial->minor))+1)<<8); */
/* Wval is same as application number */
if (port->serial->num_ports == 4) {
- Wval =
- (((__u16) port->number - (__u16) (port->serial->minor)) +
- 1) << 8;
- dbg("mos7840_get_uart_reg application number is %x", Wval);
+ Wval = ((__u16)port->port_number + 1) << 8;
} else {
- if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {
- Wval = (((__u16) port->number -
- (__u16) (port->serial->minor)) + 1) << 8;
- dbg("mos7840_get_uart_reg application number is %x",
- Wval);
+ if (port->port_number == 0) {
+ Wval = ((__u16)port->port_number + 1) << 8;
} else {
- Wval = (((__u16) port->number -
- (__u16) (port->serial->minor)) + 2) << 8;
- dbg("mos7840_get_uart_reg application number is %x",
- Wval);
+ Wval = ((__u16)port->port_number + 2) << 8;
}
}
+ dev_dbg(&port->dev, "%s application number is %x\n", __func__, Wval);
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
MCS_RD_RTYPE, Wval, reg, buf, VENDOR_READ_LENGTH,
MOS_WDR_TIMEOUT);
@@ -395,14 +359,13 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg,
return ret;
}
-static void mos7840_dump_serial_port(struct moschip_port *mos7840_port)
+static void mos7840_dump_serial_port(struct usb_serial_port *port,
+ struct moschip_port *mos7840_port)
{
- dbg("***************************************");
- dbg("SpRegOffset is %2x", mos7840_port->SpRegOffset);
- dbg("ControlRegOffset is %2x", mos7840_port->ControlRegOffset);
- dbg("DCRRegOffset is %2x", mos7840_port->DcrRegOffset);
- dbg("***************************************");
+ dev_dbg(&port->dev, "SpRegOffset is %2x\n", mos7840_port->SpRegOffset);
+ dev_dbg(&port->dev, "ControlRegOffset is %2x\n", mos7840_port->ControlRegOffset);
+ dev_dbg(&port->dev, "DCRRegOffset is %2x\n", mos7840_port->DcrRegOffset);
}
@@ -431,29 +394,22 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
struct moschip_port *mos7840_port;
struct async_icount *icount;
mos7840_port = port;
- icount = &mos7840_port->icount;
if (new_msr &
(MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI |
MOS_MSR_DELTA_CD)) {
- icount = &mos7840_port->icount;
+ icount = &mos7840_port->port->icount;
/* update input line counters */
- if (new_msr & MOS_MSR_DELTA_CTS) {
+ if (new_msr & MOS_MSR_DELTA_CTS)
icount->cts++;
- smp_wmb();
- }
- if (new_msr & MOS_MSR_DELTA_DSR) {
+ if (new_msr & MOS_MSR_DELTA_DSR)
icount->dsr++;
- smp_wmb();
- }
- if (new_msr & MOS_MSR_DELTA_CD) {
+ if (new_msr & MOS_MSR_DELTA_CD)
icount->dcd++;
- smp_wmb();
- }
- if (new_msr & MOS_MSR_DELTA_RI) {
+ if (new_msr & MOS_MSR_DELTA_RI)
icount->rng++;
- smp_wmb();
- }
+
+ wake_up_interruptible(&port->port->port.delta_msr_wait);
}
}
@@ -461,8 +417,6 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
{
struct async_icount *icount;
- dbg("%s - %02x", __func__, new_lsr);
-
if (new_lsr & SERIAL_LSR_BI) {
/*
* Parity and Framing errors only count if they
@@ -473,23 +427,15 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
}
/* update input line counters */
- icount = &port->icount;
- if (new_lsr & SERIAL_LSR_BI) {
+ icount = &port->port->icount;
+ if (new_lsr & SERIAL_LSR_BI)
icount->brk++;
- smp_wmb();
- }
- if (new_lsr & SERIAL_LSR_OE) {
+ if (new_lsr & SERIAL_LSR_OE)
icount->overrun++;
- smp_wmb();
- }
- if (new_lsr & SERIAL_LSR_PE) {
+ if (new_lsr & SERIAL_LSR_PE)
icount->parity++;
- smp_wmb();
- }
- if (new_lsr & SERIAL_LSR_FE) {
+ if (new_lsr & SERIAL_LSR_FE)
icount->frame++;
- smp_wmb();
- }
}
/************************************************************************/
@@ -503,8 +449,8 @@ static void mos7840_control_callback(struct urb *urb)
{
unsigned char *data;
struct moschip_port *mos7840_port;
+ struct device *dev = &urb->dev->dev;
__u8 regval = 0x0;
- int result = 0;
int status = urb->status;
mos7840_port = urb->context;
@@ -517,36 +463,25 @@ static void mos7840_control_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__,
- status);
- return;
+ dev_dbg(dev, "%s - urb shutting down with status: %d\n", __func__, status);
+ goto out;
default:
- dbg("%s - nonzero urb status received: %d", __func__,
- status);
- goto exit;
+ dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status);
+ goto out;
}
- dbg("%s urb buffer size is %d", __func__, urb->actual_length);
- dbg("%s mos7840_port->MsrLsr is %d port %d", __func__,
- mos7840_port->MsrLsr, mos7840_port->port_num);
+ dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length);
+ dev_dbg(dev, "%s mos7840_port->MsrLsr is %d port %d\n", __func__,
+ mos7840_port->MsrLsr, mos7840_port->port_num);
data = urb->transfer_buffer;
regval = (__u8) data[0];
- dbg("%s data is %x", __func__, regval);
+ dev_dbg(dev, "%s data is %x\n", __func__, regval);
if (mos7840_port->MsrLsr == 0)
mos7840_handle_new_msr(mos7840_port, regval);
else if (mos7840_port->MsrLsr == 1)
mos7840_handle_new_lsr(mos7840_port, regval);
-
-exit:
- spin_lock(&mos7840_port->pool_lock);
- if (!mos7840_port->zombie)
- result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC);
- spin_unlock(&mos7840_port->pool_lock);
- if (result) {
- dev_err(&urb->dev->dev,
- "%s - Error %d submitting interrupt urb\n",
- __func__, result);
- }
+out:
+ clear_bit_unlock(MOS7840_FLAG_CTRL_BUSY, &mos7840_port->flags);
}
static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
@@ -557,6 +492,9 @@ static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
unsigned char *buffer = mcs->ctrl_buf;
int ret;
+ if (test_and_set_bit_lock(MOS7840_FLAG_CTRL_BUSY, &mcs->flags))
+ return -EBUSY;
+
dr->bRequestType = MCS_RD_RTYPE;
dr->bRequest = MCS_RDREQ;
dr->wValue = cpu_to_le16(Wval); /* 0 */
@@ -568,9 +506,87 @@ static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
mos7840_control_callback, mcs);
mcs->control_urb->transfer_buffer_length = 2;
ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC);
+ if (ret)
+ clear_bit_unlock(MOS7840_FLAG_CTRL_BUSY, &mcs->flags);
+
return ret;
}
+static void mos7840_set_led_callback(struct urb *urb)
+{
+ switch (urb->status) {
+ case 0:
+ /* Success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* This urb is terminated, clean up */
+ dev_dbg(&urb->dev->dev, "%s - urb shutting down: %d\n",
+ __func__, urb->status);
+ break;
+ default:
+ dev_dbg(&urb->dev->dev, "%s - nonzero urb status: %d\n",
+ __func__, urb->status);
+ }
+}
+
+static void mos7840_set_led_async(struct moschip_port *mcs, __u16 wval,
+ __u16 reg)
+{
+ struct usb_device *dev = mcs->port->serial->dev;
+ struct usb_ctrlrequest *dr = mcs->led_dr;
+
+ dr->bRequestType = MCS_WR_RTYPE;
+ dr->bRequest = MCS_WRREQ;
+ dr->wValue = cpu_to_le16(wval);
+ dr->wIndex = cpu_to_le16(reg);
+ dr->wLength = cpu_to_le16(0);
+
+ usb_fill_control_urb(mcs->led_urb, dev, usb_sndctrlpipe(dev, 0),
+ (unsigned char *)dr, NULL, 0, mos7840_set_led_callback, NULL);
+
+ usb_submit_urb(mcs->led_urb, GFP_ATOMIC);
+}
+
+static void mos7840_set_led_sync(struct usb_serial_port *port, __u16 reg,
+ __u16 val)
+{
+ struct usb_device *dev = port->serial->dev;
+
+ usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, MCS_WR_RTYPE,
+ val, reg, NULL, 0, MOS_WDR_TIMEOUT);
+}
+
+static void mos7840_led_off(unsigned long arg)
+{
+ struct moschip_port *mcs = (struct moschip_port *) arg;
+
+ /* Turn off LED */
+ mos7840_set_led_async(mcs, 0x0300, MODEM_CONTROL_REGISTER);
+ mod_timer(&mcs->led_timer2,
+ jiffies + msecs_to_jiffies(LED_OFF_MS));
+}
+
+static void mos7840_led_flag_off(unsigned long arg)
+{
+ struct moschip_port *mcs = (struct moschip_port *) arg;
+
+ clear_bit_unlock(MOS7840_FLAG_LED_BUSY, &mcs->flags);
+}
+
+static void mos7840_led_activity(struct usb_serial_port *port)
+{
+ struct moschip_port *mos7840_port = usb_get_serial_port_data(port);
+
+ if (test_and_set_bit_lock(MOS7840_FLAG_LED_BUSY, &mos7840_port->flags))
+ return;
+
+ mos7840_set_led_async(mos7840_port, 0x0301, MODEM_CONTROL_REGISTER);
+ mod_timer(&mos7840_port->led_timer1,
+ jiffies + msecs_to_jiffies(LED_ON_MS));
+}
+
/*****************************************************************************
* mos7840_interrupt_callback
* this is the callback function for when we have received data on the
@@ -590,8 +606,6 @@ static void mos7840_interrupt_callback(struct urb *urb)
__u16 wval, wreg = 0;
int status = urb->status;
- dbg("%s", " : Entering");
-
switch (status) {
case 0:
/* success */
@@ -600,12 +614,12 @@ static void mos7840_interrupt_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__,
- status);
+ dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __func__,
- status);
+ dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
goto exit;
}
@@ -622,7 +636,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
* Byte 5 FIFO status for both */
if (length && length > 5) {
- dbg("%s", "Wrong data !!!");
+ dev_dbg(&urb->dev->dev, "%s", "Wrong data !!!\n");
return;
}
@@ -634,34 +648,25 @@ static void mos7840_interrupt_callback(struct urb *urb)
for (i = 0; i < serial->num_ports; i++) {
mos7840_port = mos7840_get_port_private(serial->port[i]);
- wval =
- (((__u16) serial->port[i]->number -
- (__u16) (serial->minor)) + 1) << 8;
+ wval = ((__u16)serial->port[i]->port_number + 1) << 8;
if (mos7840_port->open) {
if (sp[i] & 0x01) {
- dbg("SP%d No Interrupt !!!", i);
+ dev_dbg(&urb->dev->dev, "SP%d No Interrupt !!!\n", i);
} else {
switch (sp[i] & 0x0f) {
case SERIAL_IIR_RLS:
- dbg("Serial Port %d: Receiver status error or ", i);
- dbg("address bit detected in 9-bit mode");
+ dev_dbg(&urb->dev->dev, "Serial Port %d: Receiver status error or \n", i);
+ dev_dbg(&urb->dev->dev, "address bit detected in 9-bit mode\n");
mos7840_port->MsrLsr = 1;
wreg = LINE_STATUS_REGISTER;
break;
case SERIAL_IIR_MS:
- dbg("Serial Port %d: Modem status change", i);
+ dev_dbg(&urb->dev->dev, "Serial Port %d: Modem status change\n", i);
mos7840_port->MsrLsr = 0;
wreg = MODEM_STATUS_REGISTER;
break;
}
- spin_lock(&mos7840_port->pool_lock);
- if (!mos7840_port->zombie) {
- rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
- } else {
- spin_unlock(&mos7840_port->pool_lock);
- return;
- }
- spin_unlock(&mos7840_port->pool_lock);
+ rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
}
}
}
@@ -681,11 +686,11 @@ static int mos7840_port_paranoia_check(struct usb_serial_port *port,
const char *function)
{
if (!port) {
- dbg("%s - port == NULL", function);
+ pr_debug("%s - port == NULL\n", function);
return -1;
}
if (!port->serial) {
- dbg("%s - port->serial == NULL", function);
+ pr_debug("%s - port->serial == NULL\n", function);
return -1;
}
@@ -697,11 +702,11 @@ static int mos7840_serial_paranoia_check(struct usb_serial *serial,
const char *function)
{
if (!serial) {
- dbg("%s - serial == NULL", function);
+ pr_debug("%s - serial == NULL\n", function);
return -1;
}
if (!serial->type) {
- dbg("%s - serial->type == NULL!", function);
+ pr_debug("%s - serial->type == NULL!\n", function);
return -1;
}
@@ -736,69 +741,55 @@ static void mos7840_bulk_in_callback(struct urb *urb)
struct usb_serial *serial;
struct usb_serial_port *port;
struct moschip_port *mos7840_port;
- struct tty_struct *tty;
int status = urb->status;
mos7840_port = urb->context;
- if (!mos7840_port) {
- dbg("%s", "NULL mos7840_port pointer");
+ if (!mos7840_port)
return;
- }
if (status) {
- dbg("nonzero read bulk status received: %d", status);
+ dev_dbg(&urb->dev->dev, "nonzero read bulk status received: %d\n", status);
mos7840_port->read_urb_busy = false;
return;
}
- port = (struct usb_serial_port *)mos7840_port->port;
+ port = mos7840_port->port;
if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Port Paranoia failed");
mos7840_port->read_urb_busy = false;
return;
}
serial = mos7840_get_usb_serial(port, __func__);
if (!serial) {
- dbg("%s", "Bad serial pointer");
mos7840_port->read_urb_busy = false;
return;
}
- dbg("%s", "Entering... ");
-
data = urb->transfer_buffer;
-
- dbg("%s", "Entering ...........");
+ usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
if (urb->actual_length) {
- tty = tty_port_tty_get(&mos7840_port->port->port);
- if (tty) {
- tty_insert_flip_string(tty, data, urb->actual_length);
- dbg(" %s ", data);
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
- }
- mos7840_port->icount.rx += urb->actual_length;
- smp_wmb();
- dbg("mos7840_port->icount.rx is %d:",
- mos7840_port->icount.rx);
+ struct tty_port *tport = &mos7840_port->port->port;
+ tty_insert_flip_string(tport, data, urb->actual_length);
+ tty_flip_buffer_push(tport);
+ port->icount.rx += urb->actual_length;
+ dev_dbg(&port->dev, "icount.rx is %d:\n", port->icount.rx);
}
if (!mos7840_port->read_urb) {
- dbg("%s", "URB KILLED !!!");
+ dev_dbg(&port->dev, "%s", "URB KILLED !!!\n");
mos7840_port->read_urb_busy = false;
return;
}
-
- mos7840_port->read_urb->dev = serial->dev;
+ if (mos7840_port->has_led)
+ mos7840_led_activity(port);
mos7840_port->read_urb_busy = true;
retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
if (retval) {
- dbg("usb_submit_urb(read bulk) failed, retval = %d", retval);
+ dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, retval = %d\n", retval);
mos7840_port->read_urb_busy = false;
}
}
@@ -812,11 +803,12 @@ static void mos7840_bulk_in_callback(struct urb *urb)
static void mos7840_bulk_out_data_callback(struct urb *urb)
{
struct moschip_port *mos7840_port;
- struct tty_struct *tty;
+ struct usb_serial_port *port;
int status = urb->status;
int i;
mos7840_port = urb->context;
+ port = mos7840_port->port;
spin_lock(&mos7840_port->pool_lock);
for (i = 0; i < NUM_URBS; i++) {
if (urb == mos7840_port->write_urb_pool[i]) {
@@ -827,39 +819,21 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
spin_unlock(&mos7840_port->pool_lock);
if (status) {
- dbg("nonzero write bulk status received:%d", status);
+ dev_dbg(&port->dev, "nonzero write bulk status received:%d\n", status);
return;
}
- if (mos7840_port_paranoia_check(mos7840_port->port, __func__)) {
- dbg("%s", "Port Paranoia failed");
+ if (mos7840_port_paranoia_check(port, __func__))
return;
- }
- dbg("%s", "Entering .........");
-
- tty = tty_port_tty_get(&mos7840_port->port->port);
- if (tty && mos7840_port->open)
- tty_wakeup(tty);
- tty_kref_put(tty);
+ if (mos7840_port->open)
+ tty_port_tty_wakeup(&port->port);
}
/************************************************************************/
/* D R I V E R T T Y I N T E R F A C E F U N C T I O N S */
/************************************************************************/
-#ifdef MCSSerialProbe
-static int mos7840_serial_probe(struct usb_serial *serial,
- const struct usb_device_id *id)
-{
-
- /*need to implement the mode_reg reading and updating\
- structures usb_serial_ device_type\
- (i.e num_ports, num_bulkin,bulkout etc) */
- /* Also we can update the changes attach */
- return 1;
-}
-#endif
/*****************************************************************************
* mos7840_open
@@ -879,19 +853,13 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
struct moschip_port *mos7840_port;
struct moschip_port *port0;
- dbg ("%s enter", __func__);
-
- if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Port Paranoia failed");
+ if (mos7840_port_paranoia_check(port, __func__))
return -ENODEV;
- }
serial = port->serial;
- if (mos7840_serial_paranoia_check(serial, __func__)) {
- dbg("%s", "Serial Paranoia failed");
+ if (mos7840_serial_paranoia_check(serial, __func__))
return -ENODEV;
- }
mos7840_port = mos7840_get_port_private(port);
port0 = mos7840_get_port_private(serial->port[0]);
@@ -907,20 +875,14 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
for (j = 0; j < NUM_URBS; ++j) {
urb = usb_alloc_urb(0, GFP_KERNEL);
mos7840_port->write_urb_pool[j] = urb;
-
- if (urb == NULL) {
- dev_err(&port->dev, "No more urbs???\n");
+ if (!urb)
continue;
- }
urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
GFP_KERNEL);
if (!urb->transfer_buffer) {
usb_free_urb(urb);
mos7840_port->write_urb_pool[j] = NULL;
- dev_err(&port->dev,
- "%s-out of memory for urb buffers.\n",
- __func__);
continue;
}
}
@@ -942,21 +904,21 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
Data = 0x0;
status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
if (status < 0) {
- dbg("Reading Spreg failed");
- return -1;
+ dev_dbg(&port->dev, "Reading Spreg failed\n");
+ goto err;
}
Data |= 0x80;
status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
if (status < 0) {
- dbg("writing Spreg failed");
- return -1;
+ dev_dbg(&port->dev, "writing Spreg failed\n");
+ goto err;
}
Data &= ~0x80;
status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
if (status < 0) {
- dbg("writing Spreg failed");
- return -1;
+ dev_dbg(&port->dev, "writing Spreg failed\n");
+ goto err;
}
/* End of block to be checked */
@@ -964,16 +926,16 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset,
&Data);
if (status < 0) {
- dbg("Reading Controlreg failed");
- return -1;
+ dev_dbg(&port->dev, "Reading Controlreg failed\n");
+ goto err;
}
Data |= 0x08; /* Driver done bit */
Data |= 0x20; /* rx_disable */
status = mos7840_set_reg_sync(port,
mos7840_port->ControlRegOffset, Data);
if (status < 0) {
- dbg("writing Controlreg failed");
- return -1;
+ dev_dbg(&port->dev, "writing Controlreg failed\n");
+ goto err;
}
/* do register settings here */
/* Set all regs to the device default values. */
@@ -983,22 +945,22 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
Data = 0x00;
status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
if (status < 0) {
- dbg("disabling interrupts failed");
- return -1;
+ dev_dbg(&port->dev, "disabling interrupts failed\n");
+ goto err;
}
/* Set FIFO_CONTROL_REGISTER to the default value */
Data = 0x00;
status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
if (status < 0) {
- dbg("Writing FIFO_CONTROL_REGISTER failed");
- return -1;
+ dev_dbg(&port->dev, "Writing FIFO_CONTROL_REGISTER failed\n");
+ goto err;
}
Data = 0xcf;
status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
if (status < 0) {
- dbg("Writing FIFO_CONTROL_REGISTER failed");
- return -1;
+ dev_dbg(&port->dev, "Writing FIFO_CONTROL_REGISTER failed\n");
+ goto err;
}
Data = 0x03;
@@ -1094,26 +1056,34 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
* (can't set it up in mos7840_startup as the *
* structures were not set up at that time.) */
- dbg("port number is %d", port->number);
- dbg("serial number is %d", port->serial->minor);
- dbg("Bulkin endpoint is %d", port->bulk_in_endpointAddress);
- dbg("BulkOut endpoint is %d", port->bulk_out_endpointAddress);
- dbg("Interrupt endpoint is %d", port->interrupt_in_endpointAddress);
- dbg("port's number in the device is %d", mos7840_port->port_num);
+ dev_dbg(&port->dev, "port number is %d\n", port->port_number);
+ dev_dbg(&port->dev, "minor number is %d\n", port->minor);
+ dev_dbg(&port->dev, "Bulkin endpoint is %d\n", port->bulk_in_endpointAddress);
+ dev_dbg(&port->dev, "BulkOut endpoint is %d\n", port->bulk_out_endpointAddress);
+ dev_dbg(&port->dev, "Interrupt endpoint is %d\n", port->interrupt_in_endpointAddress);
+ dev_dbg(&port->dev, "port's number in the device is %d\n", mos7840_port->port_num);
mos7840_port->read_urb = port->read_urb;
/* set up our bulk in urb */
+ if ((serial->num_ports == 2) && (((__u16)port->port_number % 2) != 0)) {
+ usb_fill_bulk_urb(mos7840_port->read_urb,
+ serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ (port->bulk_in_endpointAddress) + 2),
+ port->bulk_in_buffer,
+ mos7840_port->read_urb->transfer_buffer_length,
+ mos7840_bulk_in_callback, mos7840_port);
+ } else {
+ usb_fill_bulk_urb(mos7840_port->read_urb,
+ serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
+ port->bulk_in_buffer,
+ mos7840_port->read_urb->transfer_buffer_length,
+ mos7840_bulk_in_callback, mos7840_port);
+ }
- usb_fill_bulk_urb(mos7840_port->read_urb,
- serial->dev,
- usb_rcvbulkpipe(serial->dev,
- port->bulk_in_endpointAddress),
- port->bulk_in_buffer,
- mos7840_port->read_urb->transfer_buffer_length,
- mos7840_bulk_in_callback, mos7840_port);
-
- dbg("mos7840_open: bulkin endpoint is %d",
- port->bulk_in_endpointAddress);
+ dev_dbg(&port->dev, "%s: bulkin endpoint is %d\n", __func__, port->bulk_in_endpointAddress);
mos7840_port->read_urb_busy = true;
response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL);
if (response) {
@@ -1122,29 +1092,23 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
mos7840_port->read_urb_busy = false;
}
- /* initialize our wait queues */
- init_waitqueue_head(&mos7840_port->wait_chase);
- init_waitqueue_head(&mos7840_port->delta_msr_wait);
-
- /* initialize our icount structure */
- memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
-
/* initialize our port settings */
/* Must set to enable ints! */
mos7840_port->shadowMCR = MCR_MASTER_IE;
/* send a open port command */
mos7840_port->open = 1;
/* mos7840_change_port_settings(mos7840_port,old_termios); */
- mos7840_port->icount.tx = 0;
- mos7840_port->icount.rx = 0;
-
- dbg("usb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p",
- serial, mos7840_port, port);
-
- dbg ("%s leave", __func__);
return 0;
-
+err:
+ for (j = 0; j < NUM_URBS; ++j) {
+ urb = mos7840_port->write_urb_pool[j];
+ if (!urb)
+ continue;
+ kfree(urb->transfer_buffer);
+ usb_free_urb(urb);
+ }
+ return status;
}
/*****************************************************************************
@@ -1165,25 +1129,22 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty)
unsigned long flags;
struct moschip_port *mos7840_port;
- dbg("%s", " mos7840_chars_in_buffer:entering ...........");
-
- if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Invalid port");
+ if (mos7840_port_paranoia_check(port, __func__))
return 0;
- }
mos7840_port = mos7840_get_port_private(port);
- if (mos7840_port == NULL) {
- dbg("%s", "mos7840_break:leaving ...........");
+ if (mos7840_port == NULL)
return 0;
- }
spin_lock_irqsave(&mos7840_port->pool_lock, flags);
- for (i = 0; i < NUM_URBS; ++i)
- if (mos7840_port->busy[i])
- chars += URB_TRANSFER_BUFFER_SIZE;
+ for (i = 0; i < NUM_URBS; ++i) {
+ if (mos7840_port->busy[i]) {
+ struct urb *urb = mos7840_port->write_urb_pool[i];
+ chars += urb->transfer_buffer_length;
+ }
+ }
spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
- dbg("%s - returns %d", __func__, chars);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
return chars;
}
@@ -1201,18 +1162,12 @@ static void mos7840_close(struct usb_serial_port *port)
int j;
__u16 Data;
- dbg("%s", "mos7840_close:entering...");
-
- if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Port Paranoia failed");
+ if (mos7840_port_paranoia_check(port, __func__))
return;
- }
serial = mos7840_get_usb_serial(port, __func__);
- if (!serial) {
- dbg("%s", "Serial Paranoia failed");
+ if (!serial)
return;
- }
mos7840_port = mos7840_get_port_private(port);
port0 = mos7840_get_port_private(serial->port[0]);
@@ -1234,39 +1189,22 @@ static void mos7840_close(struct usb_serial_port *port)
}
}
- /* While closing port, shutdown all bulk read, write *
- * and interrupt read if they exists */
- if (serial->dev) {
- if (mos7840_port->write_urb) {
- dbg("%s", "Shutdown bulk write");
- usb_kill_urb(mos7840_port->write_urb);
- }
- if (mos7840_port->read_urb) {
- dbg("%s", "Shutdown bulk read");
- usb_kill_urb(mos7840_port->read_urb);
- mos7840_port->read_urb_busy = false;
- }
- if ((&mos7840_port->control_urb)) {
- dbg("%s", "Shutdown control read");
- /*/ usb_kill_urb (mos7840_port->control_urb); */
- }
- }
-/* if(mos7840_port->ctrl_buf != NULL) */
-/* kfree(mos7840_port->ctrl_buf); */
+ usb_kill_urb(mos7840_port->write_urb);
+ usb_kill_urb(mos7840_port->read_urb);
+ mos7840_port->read_urb_busy = false;
+
port0->open_ports--;
- dbg("mos7840_num_open_ports in close%d:in port%d",
- port0->open_ports, port->number);
+ dev_dbg(&port->dev, "%s in close%d\n", __func__, port0->open_ports);
if (port0->open_ports == 0) {
if (serial->port[0]->interrupt_in_urb) {
- dbg("%s", "Shutdown interrupt_in_urb");
+ dev_dbg(&port->dev, "Shutdown interrupt_in_urb\n");
usb_kill_urb(serial->port[0]->interrupt_in_urb);
}
}
if (mos7840_port->write_urb) {
/* if this urb had a transfer buffer already (old tx) free it */
- if (mos7840_port->write_urb->transfer_buffer != NULL)
- kfree(mos7840_port->write_urb->transfer_buffer);
+ kfree(mos7840_port->write_urb->transfer_buffer);
usb_free_urb(mos7840_port->write_urb);
}
@@ -1277,49 +1215,6 @@ static void mos7840_close(struct usb_serial_port *port)
mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
mos7840_port->open = 0;
-
- dbg("%s", "Leaving ............");
-}
-
-/************************************************************************
- *
- * mos7840_block_until_chase_response
- *
- * This function will block the close until one of the following:
- * 1. Response to our Chase comes from mos7840
- * 2. A timeout of 10 seconds without activity has expired
- * (1K of mos7840 data @ 2400 baud ==> 4 sec to empty)
- *
- ************************************************************************/
-
-static void mos7840_block_until_chase_response(struct tty_struct *tty,
- struct moschip_port *mos7840_port)
-{
- int timeout = 1 * HZ;
- int wait = 10;
- int count;
-
- while (1) {
- count = mos7840_chars_in_buffer(tty);
-
- /* Check for Buffer status */
- if (count <= 0)
- return;
-
- /* Block the thread for a while */
- interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
- timeout);
- /* No activity.. count down section */
- wait--;
- if (wait == 0) {
- dbg("%s - TIMEOUT", __func__);
- return;
- } else {
- /* Reset timeout value back to seconds */
- wait = 10;
- }
- }
-
}
/*****************************************************************************
@@ -1333,29 +1228,18 @@ static void mos7840_break(struct tty_struct *tty, int break_state)
struct usb_serial *serial;
struct moschip_port *mos7840_port;
- dbg("%s", "Entering ...........");
- dbg("mos7840_break: Start");
-
- if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Port Paranoia failed");
+ if (mos7840_port_paranoia_check(port, __func__))
return;
- }
serial = mos7840_get_usb_serial(port, __func__);
- if (!serial) {
- dbg("%s", "Serial Paranoia failed");
+ if (!serial)
return;
- }
mos7840_port = mos7840_get_port_private(port);
if (mos7840_port == NULL)
return;
- if (serial->dev)
- /* flush and block until tx is empty */
- mos7840_block_until_chase_response(tty, mos7840_port);
-
if (break_state == -1)
data = mos7840_port->shadowLCR | LCR_SET_BREAK;
else
@@ -1363,8 +1247,7 @@ static void mos7840_break(struct tty_struct *tty, int break_state)
/* FIXME: no locking on shadowLCR anywhere in driver */
mos7840_port->shadowLCR = data;
- dbg("mcs7840_break mos7840_port->shadowLCR is %x",
- mos7840_port->shadowLCR);
+ dev_dbg(&port->dev, "%s mos7840_port->shadowLCR is %x\n", __func__, mos7840_port->shadowLCR);
mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER,
mos7840_port->shadowLCR);
}
@@ -1385,19 +1268,12 @@ static int mos7840_write_room(struct tty_struct *tty)
unsigned long flags;
struct moschip_port *mos7840_port;
- dbg("%s", " mos7840_write_room:entering ...........");
-
- if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Invalid port");
- dbg("%s", " mos7840_write_room:leaving ...........");
+ if (mos7840_port_paranoia_check(port, __func__))
return -1;
- }
mos7840_port = mos7840_get_port_private(port);
- if (mos7840_port == NULL) {
- dbg("%s", "mos7840_break:leaving ...........");
+ if (mos7840_port == NULL)
return -1;
- }
spin_lock_irqsave(&mos7840_port->pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
@@ -1407,7 +1283,7 @@ static int mos7840_write_room(struct tty_struct *tty)
spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
room = (room == 0) ? 0 : room - URB_TRANSFER_BUFFER_SIZE + 1;
- dbg("%s - returns %d", __func__, room);
+ dev_dbg(&mos7840_port->port->dev, "%s - returns %d\n", __func__, room);
return room;
}
@@ -1435,17 +1311,13 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
/* __u16 Data; */
const unsigned char *current_position = data;
unsigned char *data1;
- dbg("%s", "entering ...........");
- /* dbg("mos7840_write: mos7840_port->shadowLCR is %x",
- mos7840_port->shadowLCR); */
#ifdef NOTMOS7840
Data = 0x00;
status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
mos7840_port->shadowLCR = Data;
- dbg("mos7840_write: LINE_CONTROL_REGISTER is %x", Data);
- dbg("mos7840_write: mos7840_port->shadowLCR is %x",
- mos7840_port->shadowLCR);
+ dev_dbg(&port->dev, "%s: LINE_CONTROL_REGISTER is %x\n", __func__, Data);
+ dev_dbg(&port->dev, "%s: mos7840_port->shadowLCR is %x\n", __func__, mos7840_port->shadowLCR);
/* Data = 0x03; */
/* status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data); */
@@ -1458,34 +1330,27 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
/* status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data); */
Data = 0x00;
status = mos7840_get_uart_reg(port, DIVISOR_LATCH_LSB, &Data);
- dbg("mos7840_write:DLL value is %x", Data);
+ dev_dbg(&port->dev, "%s: DLL value is %x\n", __func__, Data);
Data = 0x0;
status = mos7840_get_uart_reg(port, DIVISOR_LATCH_MSB, &Data);
- dbg("mos7840_write:DLM value is %x", Data);
+ dev_dbg(&port->dev, "%s: DLM value is %x\n", __func__, Data);
Data = Data & ~SERIAL_LCR_DLAB;
- dbg("mos7840_write: mos7840_port->shadowLCR is %x",
- mos7840_port->shadowLCR);
+ dev_dbg(&port->dev, "%s: mos7840_port->shadowLCR is %x\n", __func__, mos7840_port->shadowLCR);
status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
#endif
- if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Port Paranoia failed");
+ if (mos7840_port_paranoia_check(port, __func__))
return -1;
- }
serial = port->serial;
- if (mos7840_serial_paranoia_check(serial, __func__)) {
- dbg("%s", "Serial Paranoia failed");
+ if (mos7840_serial_paranoia_check(serial, __func__))
return -1;
- }
mos7840_port = mos7840_get_port_private(port);
- if (mos7840_port == NULL) {
- dbg("%s", "mos7840_port is NULL");
+ if (mos7840_port == NULL)
return -1;
- }
/* try to find a free urb in the list */
urb = NULL;
@@ -1495,57 +1360,65 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
if (!mos7840_port->busy[i]) {
mos7840_port->busy[i] = 1;
urb = mos7840_port->write_urb_pool[i];
- dbg("URB:%d", i);
+ dev_dbg(&port->dev, "URB:%d\n", i);
break;
}
}
spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
if (urb == NULL) {
- dbg("%s - no more free urbs", __func__);
+ dev_dbg(&port->dev, "%s - no more free urbs\n", __func__);
goto exit;
}
if (urb->transfer_buffer == NULL) {
urb->transfer_buffer =
kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
-
- if (urb->transfer_buffer == NULL) {
- dev_err(&port->dev, "%s no more kernel memory...\n",
- __func__);
+ if (!urb->transfer_buffer)
goto exit;
- }
}
transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
memcpy(urb->transfer_buffer, current_position, transfer_size);
/* fill urb with data and submit */
- usb_fill_bulk_urb(urb,
- serial->dev,
- usb_sndbulkpipe(serial->dev,
- port->bulk_out_endpointAddress),
- urb->transfer_buffer,
- transfer_size,
- mos7840_bulk_out_data_callback, mos7840_port);
+ if ((serial->num_ports == 2) && (((__u16)port->port_number % 2) != 0)) {
+ usb_fill_bulk_urb(urb,
+ serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ (port->bulk_out_endpointAddress) + 2),
+ urb->transfer_buffer,
+ transfer_size,
+ mos7840_bulk_out_data_callback, mos7840_port);
+ } else {
+ usb_fill_bulk_urb(urb,
+ serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ port->bulk_out_endpointAddress),
+ urb->transfer_buffer,
+ transfer_size,
+ mos7840_bulk_out_data_callback, mos7840_port);
+ }
data1 = urb->transfer_buffer;
- dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress);
+ dev_dbg(&port->dev, "bulkout endpoint is %d\n", port->bulk_out_endpointAddress);
+
+ if (mos7840_port->has_led)
+ mos7840_led_activity(port);
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
mos7840_port->busy[i] = 0;
- dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+ dev_err_console(port, "%s - usb_submit_urb(write bulk) failed "
"with status = %d\n", __func__, status);
bytes_sent = status;
goto exit;
}
bytes_sent = transfer_size;
- mos7840_port->icount.tx += transfer_size;
- smp_wmb();
- dbg("mos7840_port->icount.tx is %d:", mos7840_port->icount.tx);
+ port->icount.tx += transfer_size;
+ dev_dbg(&port->dev, "icount.tx is %d:\n", port->icount.tx);
exit:
return bytes_sent;
@@ -1563,12 +1436,8 @@ static void mos7840_throttle(struct tty_struct *tty)
struct moschip_port *mos7840_port;
int status;
- if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Invalid port");
+ if (mos7840_port_paranoia_check(port, __func__))
return;
- }
-
- dbg("- port %d", port->number);
mos7840_port = mos7840_get_port_private(port);
@@ -1576,12 +1445,10 @@ static void mos7840_throttle(struct tty_struct *tty)
return;
if (!mos7840_port->open) {
- dbg("%s", "port not opened");
+ dev_dbg(&port->dev, "%s", "port not opened\n");
return;
}
- dbg("%s", "Entering ..........");
-
/* if we are implementing XON/XOFF, send the stop character */
if (I_IXOFF(tty)) {
unsigned char stop_char = STOP_CHAR(tty);
@@ -1590,7 +1457,7 @@ static void mos7840_throttle(struct tty_struct *tty)
return;
}
/* if we are implementing RTS/CTS, toggle that line */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
mos7840_port->shadowMCR &= ~MCR_RTS;
status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
mos7840_port->shadowMCR);
@@ -1611,21 +1478,17 @@ static void mos7840_unthrottle(struct tty_struct *tty)
int status;
struct moschip_port *mos7840_port = mos7840_get_port_private(port);
- if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Invalid port");
+ if (mos7840_port_paranoia_check(port, __func__))
return;
- }
if (mos7840_port == NULL)
return;
if (!mos7840_port->open) {
- dbg("%s - port not opened", __func__);
+ dev_dbg(&port->dev, "%s - port not opened\n", __func__);
return;
}
- dbg("%s", "Entering ..........");
-
/* if we are implementing XON/XOFF, send the start character */
if (I_IXOFF(tty)) {
unsigned char start_char = START_CHAR(tty);
@@ -1635,7 +1498,7 @@ static void mos7840_unthrottle(struct tty_struct *tty)
}
/* if we are implementing RTS/CTS, toggle that line */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
mos7840_port->shadowMCR |= MCR_RTS;
status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
mos7840_port->shadowMCR);
@@ -1644,7 +1507,7 @@ static void mos7840_unthrottle(struct tty_struct *tty)
}
}
-static int mos7840_tiocmget(struct tty_struct *tty, struct file *file)
+static int mos7840_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7840_port;
@@ -1654,13 +1517,15 @@ static int mos7840_tiocmget(struct tty_struct *tty, struct file *file)
int status;
mos7840_port = mos7840_get_port_private(port);
- dbg("%s - port %d", __func__, port->number);
-
if (mos7840_port == NULL)
return -ENODEV;
status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr);
+ if (status != 1)
+ return -EIO;
status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr);
+ if (status != 1)
+ return -EIO;
result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)
| ((mcr & MCR_RTS) ? TIOCM_RTS : 0)
| ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0)
@@ -1669,12 +1534,12 @@ static int mos7840_tiocmget(struct tty_struct *tty, struct file *file)
| ((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)
| ((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0);
- dbg("%s - 0x%04X", __func__, result);
+ dev_dbg(&port->dev, "%s - 0x%04X\n", __func__, result);
return result;
}
-static int mos7840_tiocmset(struct tty_struct *tty, struct file *file,
+static int mos7840_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
@@ -1682,8 +1547,6 @@ static int mos7840_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int mcr;
int status;
- dbg("%s - port %d", __func__, port->number);
-
mos7840_port = mos7840_get_port_private(port);
if (mos7840_port == NULL)
@@ -1709,7 +1572,7 @@ static int mos7840_tiocmset(struct tty_struct *tty, struct file *file,
status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr);
if (status < 0) {
- dbg("setting MODEM_CONTROL_REGISTER Failed");
+ dev_dbg(&port->dev, "setting MODEM_CONTROL_REGISTER Failed\n");
return status;
}
@@ -1721,11 +1584,11 @@ static int mos7840_tiocmset(struct tty_struct *tty, struct file *file,
* this function calculates the proper baud rate divisor for the specified
* baud rate.
*****************************************************************************/
-static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
+static int mos7840_calc_baud_rate_divisor(struct usb_serial_port *port,
+ int baudRate, int *divisor,
__u16 *clk_sel_val)
{
-
- dbg("%s - %d", __func__, baudRate);
+ dev_dbg(&port->dev, "%s - %d\n", __func__, baudRate);
if (baudRate <= 115200) {
*divisor = 115200 / baudRate;
@@ -1778,11 +1641,11 @@ static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
custom++;
*divisor = custom;
- dbg(" Baud %d = %d", baudrate, custom);
+ dev_dbg(&port->dev, " Baud %d = %d\n", baudrate, custom);
return 0;
}
- dbg("%s", " Baud calculation Failed...");
+ dev_dbg(&port->dev, "%s", " Baud calculation Failed...\n");
return -1;
#endif
}
@@ -1806,23 +1669,16 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
if (mos7840_port == NULL)
return -1;
- port = (struct usb_serial_port *)mos7840_port->port;
- if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Invalid port");
+ port = mos7840_port->port;
+ if (mos7840_port_paranoia_check(port, __func__))
return -1;
- }
- if (mos7840_serial_paranoia_check(port->serial, __func__)) {
- dbg("%s", "Invalid Serial");
+ if (mos7840_serial_paranoia_check(port->serial, __func__))
return -1;
- }
-
- dbg("%s", "Entering ..........");
- number = mos7840_port->port->number - mos7840_port->port->serial->minor;
+ number = mos7840_port->port->port_number;
- dbg("%s - port = %d, baud = %d", __func__,
- mos7840_port->port->number, baudRate);
+ dev_dbg(&port->dev, "%s - baud = %d\n", __func__, baudRate);
/* reset clk_uart_sel in spregOffset */
if (baudRate > 115200) {
#ifdef HW_flow_control
@@ -1833,20 +1689,20 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
Data);
if (status < 0) {
- dbg("Writing spreg failed in set_serial_baud");
+ dev_dbg(&port->dev, "Writing spreg failed in set_serial_baud\n");
return -1;
}
#endif
} else {
#ifdef HW_flow_control
- / *setting h/w flow control bit to 0 */
+ /* setting h/w flow control bit to 0 */
Data = 0xb;
mos7840_port->shadowMCR = Data;
status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
Data);
if (status < 0) {
- dbg("Writing spreg failed in set_serial_baud");
+ dev_dbg(&port->dev, "Writing spreg failed in set_serial_baud\n");
return -1;
}
#endif
@@ -1856,19 +1712,19 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
if (1) { /* baudRate <= 115200) */
clk_sel_val = 0x0;
Data = 0x0;
- status = mos7840_calc_baud_rate_divisor(baudRate, &divisor,
+ status = mos7840_calc_baud_rate_divisor(port, baudRate, &divisor,
&clk_sel_val);
status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset,
&Data);
if (status < 0) {
- dbg("reading spreg failed in set_serial_baud");
+ dev_dbg(&port->dev, "reading spreg failed in set_serial_baud\n");
return -1;
}
Data = (Data & 0x8f) | clk_sel_val;
status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset,
Data);
if (status < 0) {
- dbg("Writing spreg failed in set_serial_baud");
+ dev_dbg(&port->dev, "Writing spreg failed in set_serial_baud\n");
return -1;
}
/* Calculate the Divisor */
@@ -1884,11 +1740,11 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
/* Write the divisor */
Data = (unsigned char)(divisor & 0xff);
- dbg("set_serial_baud Value to write DLL is %x", Data);
+ dev_dbg(&port->dev, "set_serial_baud Value to write DLL is %x\n", Data);
mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data);
Data = (unsigned char)((divisor & 0xff00) >> 8);
- dbg("set_serial_baud Value to write DLM is %x", Data);
+ dev_dbg(&port->dev, "set_serial_baud Value to write DLM is %x\n", Data);
mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data);
/* Disable access to divisor latch */
@@ -1923,68 +1779,60 @@ static void mos7840_change_port_settings(struct tty_struct *tty,
if (mos7840_port == NULL)
return;
- port = (struct usb_serial_port *)mos7840_port->port;
+ port = mos7840_port->port;
- if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Invalid port");
+ if (mos7840_port_paranoia_check(port, __func__))
return;
- }
- if (mos7840_serial_paranoia_check(port->serial, __func__)) {
- dbg("%s", "Invalid Serial");
+ if (mos7840_serial_paranoia_check(port->serial, __func__))
return;
- }
serial = port->serial;
- dbg("%s - port %d", __func__, mos7840_port->port->number);
-
if (!mos7840_port->open) {
- dbg("%s - port not opened", __func__);
+ dev_dbg(&port->dev, "%s - port not opened\n", __func__);
return;
}
- dbg("%s", "Entering ..........");
-
lData = LCR_BITS_8;
lStop = LCR_STOP_1;
lParity = LCR_PAR_NONE;
- cflag = tty->termios->c_cflag;
- iflag = tty->termios->c_iflag;
+ cflag = tty->termios.c_cflag;
+ iflag = tty->termios.c_iflag;
/* Change the number of bits */
- if (cflag & CSIZE) {
- switch (cflag & CSIZE) {
- case CS5:
- lData = LCR_BITS_5;
- break;
+ switch (cflag & CSIZE) {
+ case CS5:
+ lData = LCR_BITS_5;
+ break;
- case CS6:
- lData = LCR_BITS_6;
- break;
+ case CS6:
+ lData = LCR_BITS_6;
+ break;
- case CS7:
- lData = LCR_BITS_7;
- break;
- default:
- case CS8:
- lData = LCR_BITS_8;
- break;
- }
+ case CS7:
+ lData = LCR_BITS_7;
+ break;
+
+ default:
+ case CS8:
+ lData = LCR_BITS_8;
+ break;
}
+
/* Change the Parity bit */
if (cflag & PARENB) {
if (cflag & PARODD) {
lParity = LCR_PAR_ODD;
- dbg("%s - parity = odd", __func__);
+ dev_dbg(&port->dev, "%s - parity = odd\n", __func__);
} else {
lParity = LCR_PAR_EVEN;
- dbg("%s - parity = even", __func__);
+ dev_dbg(&port->dev, "%s - parity = even\n", __func__);
}
} else {
- dbg("%s - parity = none", __func__);
+ dev_dbg(&port->dev, "%s - parity = none\n", __func__);
}
if (cflag & CMSPAR)
@@ -1993,10 +1841,10 @@ static void mos7840_change_port_settings(struct tty_struct *tty,
/* Change the Stop bit */
if (cflag & CSTOPB) {
lStop = LCR_STOP_2;
- dbg("%s - stop bits = 2", __func__);
+ dev_dbg(&port->dev, "%s - stop bits = 2\n", __func__);
} else {
lStop = LCR_STOP_1;
- dbg("%s - stop bits = 1", __func__);
+ dev_dbg(&port->dev, "%s - stop bits = 1\n", __func__);
}
/* Update the LCR with the correct value */
@@ -2004,8 +1852,8 @@ static void mos7840_change_port_settings(struct tty_struct *tty,
~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
mos7840_port->shadowLCR |= (lData | lParity | lStop);
- dbg("mos7840_change_port_settings mos7840_port->shadowLCR is %x",
- mos7840_port->shadowLCR);
+ dev_dbg(&port->dev, "%s - mos7840_port->shadowLCR is %x\n", __func__,
+ mos7840_port->shadowLCR);
/* Disable Interrupts */
Data = 0x00;
mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
@@ -2046,11 +1894,11 @@ static void mos7840_change_port_settings(struct tty_struct *tty,
if (!baud) {
/* pick a default, any default... */
- dbg("%s", "Picked default baud...");
+ dev_dbg(&port->dev, "%s", "Picked default baud...\n");
baud = 9600;
}
- dbg("%s - baud rate = %d", __func__, baud);
+ dev_dbg(&port->dev, "%s - baud rate = %d\n", __func__, baud);
status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud);
/* Enable Interrupts */
@@ -2058,19 +1906,16 @@ static void mos7840_change_port_settings(struct tty_struct *tty,
mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
if (mos7840_port->read_urb_busy == false) {
- mos7840_port->read_urb->dev = serial->dev;
mos7840_port->read_urb_busy = true;
status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
if (status) {
- dbg("usb_submit_urb(read bulk) failed, status = %d",
+ dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, status = %d\n",
status);
mos7840_port->read_urb_busy = false;
}
}
- wake_up(&mos7840_port->delta_msr_wait);
- mos7840_port->delta_msr_cond = 1;
- dbg("mos7840_change_port_settings mos7840_port->shadowLCR is End %x",
- mos7840_port->shadowLCR);
+ dev_dbg(&port->dev, "%s - mos7840_port->shadowLCR is End %x\n", __func__,
+ mos7840_port->shadowLCR);
}
/*****************************************************************************
@@ -2087,18 +1932,14 @@ static void mos7840_set_termios(struct tty_struct *tty,
unsigned int cflag;
struct usb_serial *serial;
struct moschip_port *mos7840_port;
- dbg("mos7840_set_termios: START");
- if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Invalid port");
+
+ if (mos7840_port_paranoia_check(port, __func__))
return;
- }
serial = port->serial;
- if (mos7840_serial_paranoia_check(serial, __func__)) {
- dbg("%s", "Invalid Serial");
+ if (mos7840_serial_paranoia_check(serial, __func__))
return;
- }
mos7840_port = mos7840_get_port_private(port);
@@ -2106,35 +1947,33 @@ static void mos7840_set_termios(struct tty_struct *tty,
return;
if (!mos7840_port->open) {
- dbg("%s - port not opened", __func__);
+ dev_dbg(&port->dev, "%s - port not opened\n", __func__);
return;
}
- dbg("%s", "setting termios - ");
+ dev_dbg(&port->dev, "%s", "setting termios - \n");
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
- dbg("%s - clfag %08x iflag %08x", __func__,
- tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
- dbg("%s - old clfag %08x old iflag %08x", __func__,
- old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
- dbg("%s - port %d", __func__, port->number);
+ dev_dbg(&port->dev, "%s - clfag %08x iflag %08x\n", __func__,
+ tty->termios.c_cflag, RELEVANT_IFLAG(tty->termios.c_iflag));
+ dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__,
+ old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
/* change the port settings to the new ones specified */
mos7840_change_port_settings(tty, mos7840_port, old_termios);
if (!mos7840_port->read_urb) {
- dbg("%s", "URB KILLED !!!!!");
+ dev_dbg(&port->dev, "%s", "URB KILLED !!!!!\n");
return;
}
if (mos7840_port->read_urb_busy == false) {
- mos7840_port->read_urb->dev = serial->dev;
mos7840_port->read_urb_busy = true;
status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
if (status) {
- dbg("usb_submit_urb(read bulk) failed, status = %d",
+ dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, status = %d\n",
status);
mos7840_port->read_urb_busy = false;
}
@@ -2159,10 +1998,8 @@ static int mos7840_get_lsr_info(struct tty_struct *tty,
unsigned int result = 0;
count = mos7840_chars_in_buffer(tty);
- if (count == 0) {
- dbg("%s -- Empty", __func__);
+ if (count == 0)
result = TIOCSER_TEMT;
- }
if (copy_to_user(value, &result, sizeof(int)))
return -EFAULT;
@@ -2188,8 +2025,8 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
memset(&tmp, 0, sizeof(tmp));
tmp.type = PORT_16550A;
- tmp.line = mos7840_port->port->serial->minor;
- tmp.port = mos7840_port->port->number;
+ tmp.line = mos7840_port->port->minor;
+ tmp.port = mos7840_port->port->port_number;
tmp.irq = 0;
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
@@ -2202,458 +2039,407 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
return 0;
}
-static int mos7840_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct moschip_port *mos7840_port;
- struct async_icount cnow;
-
- mos7840_port = mos7840_get_port_private(port);
- cnow = mos7840_port->icount;
-
- smp_rmb();
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
-
- dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
- port->number, icount->rx, icount->tx);
- return 0;
-}
-
/*****************************************************************************
* SerialIoctl
* this function handles any ioctl calls to the driver
*****************************************************************************/
-static int mos7840_ioctl(struct tty_struct *tty, struct file *file,
+static int mos7840_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
void __user *argp = (void __user *)arg;
struct moschip_port *mos7840_port;
- struct async_icount cnow;
- struct async_icount cprev;
-
- if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Invalid port");
+ if (mos7840_port_paranoia_check(port, __func__))
return -1;
- }
mos7840_port = mos7840_get_port_private(port);
if (mos7840_port == NULL)
return -1;
- dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
-
switch (cmd) {
/* return number of bytes available */
case TIOCSERGETLSR:
- dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
+ dev_dbg(&port->dev, "%s TIOCSERGETLSR\n", __func__);
return mos7840_get_lsr_info(tty, argp);
- return 0;
case TIOCGSERIAL:
- dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
+ dev_dbg(&port->dev, "%s TIOCGSERIAL\n", __func__);
return mos7840_get_serial_info(mos7840_port, argp);
case TIOCSSERIAL:
- dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
+ dev_dbg(&port->dev, "%s TIOCSSERIAL\n", __func__);
break;
-
- case TIOCMIWAIT:
- dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
- cprev = mos7840_port->icount;
- while (1) {
- /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */
- mos7840_port->delta_msr_cond = 0;
- wait_event_interruptible(mos7840_port->delta_msr_wait,
- (mos7840_port->
- delta_msr_cond == 1));
-
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = mos7840_port->icount;
- smp_rmb();
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
- return 0;
- }
- cprev = cnow;
- }
- /* NOTREACHED */
- break;
-
default:
break;
}
return -ENOIOCTLCMD;
}
+static int mos7810_check(struct usb_serial *serial)
+{
+ int i, pass_count = 0;
+ u8 *buf;
+ __u16 data = 0, mcr_data = 0;
+ __u16 test_pattern = 0x55AA;
+ int res;
+
+ buf = kmalloc(VENDOR_READ_LENGTH, GFP_KERNEL);
+ if (!buf)
+ return 0; /* failed to identify 7810 */
+
+ /* Store MCR setting */
+ res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ MCS_RDREQ, MCS_RD_RTYPE, 0x0300, MODEM_CONTROL_REGISTER,
+ buf, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+ if (res == VENDOR_READ_LENGTH)
+ mcr_data = *buf;
+
+ for (i = 0; i < 16; i++) {
+ /* Send the 1-bit test pattern out to MCS7810 test pin */
+ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ MCS_WRREQ, MCS_WR_RTYPE,
+ (0x0300 | (((test_pattern >> i) & 0x0001) << 1)),
+ MODEM_CONTROL_REGISTER, NULL, 0, MOS_WDR_TIMEOUT);
+
+ /* Read the test pattern back */
+ res = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0), MCS_RDREQ,
+ MCS_RD_RTYPE, 0, GPIO_REGISTER, buf,
+ VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+ if (res == VENDOR_READ_LENGTH)
+ data = *buf;
+
+ /* If this is a MCS7810 device, both test patterns must match */
+ if (((test_pattern >> i) ^ (~data >> 1)) & 0x0001)
+ break;
+
+ pass_count++;
+ }
+
+ /* Restore MCR setting */
+ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCS_WRREQ,
+ MCS_WR_RTYPE, 0x0300 | mcr_data, MODEM_CONTROL_REGISTER, NULL,
+ 0, MOS_WDR_TIMEOUT);
+
+ kfree(buf);
+
+ if (pass_count == 16)
+ return 1;
+
+ return 0;
+}
+
+static int mos7840_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
+{
+ u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
+ u8 *buf;
+ int device_type;
+
+ if (product == MOSCHIP_DEVICE_ID_7810 ||
+ product == MOSCHIP_DEVICE_ID_7820) {
+ device_type = product;
+ goto out;
+ }
+
+ buf = kzalloc(VENDOR_READ_LENGTH, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, buf,
+ VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+
+ /* For a MCS7840 device GPIO0 must be set to 1 */
+ if (buf[0] & 0x01)
+ device_type = MOSCHIP_DEVICE_ID_7840;
+ else if (mos7810_check(serial))
+ device_type = MOSCHIP_DEVICE_ID_7810;
+ else
+ device_type = MOSCHIP_DEVICE_ID_7820;
+
+ kfree(buf);
+out:
+ usb_set_serial_data(serial, (void *)(unsigned long)device_type);
+
+ return 0;
+}
+
static int mos7840_calc_num_ports(struct usb_serial *serial)
{
- int mos7840_num_ports = 0;
-
- dbg("numberofendpoints: cur %d, alt %d",
- (int)serial->interface->cur_altsetting->desc.bNumEndpoints,
- (int)serial->interface->altsetting->desc.bNumEndpoints);
- if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) {
- mos7840_num_ports = serial->num_ports = 2;
- } else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) {
- serial->num_bulk_in = 4;
- serial->num_bulk_out = 4;
- mos7840_num_ports = serial->num_ports = 4;
- }
- dbg ("mos7840_num_ports = %d", mos7840_num_ports);
+ int device_type = (unsigned long)usb_get_serial_data(serial);
+ int mos7840_num_ports;
+
+ mos7840_num_ports = (device_type >> 4) & 0x000F;
+
return mos7840_num_ports;
}
-/****************************************************************************
- * mos7840_startup
- ****************************************************************************/
-
-static int mos7840_startup(struct usb_serial *serial)
+static int mos7840_port_probe(struct usb_serial_port *port)
{
+ struct usb_serial *serial = port->serial;
+ int device_type = (unsigned long)usb_get_serial_data(serial);
struct moschip_port *mos7840_port;
- struct usb_device *dev;
- int i, status;
-
+ int status;
+ int pnum;
__u16 Data;
- dbg("%s", "mos7840_startup :Entering..........");
- if (!serial) {
- dbg("%s", "Invalid Handler");
- return -1;
- }
+ /* we set up the pointers to the endpoints in the mos7840_open *
+ * function, as the structures aren't created yet. */
- dev = serial->dev;
+ pnum = port->port_number;
- dbg("%s", "Entering...");
- dbg ("mos7840_startup: serial = %p", serial);
+ dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum);
+ mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
+ if (!mos7840_port)
+ return -ENOMEM;
- /* we set up the pointers to the endpoints in the mos7840_open *
- * function, as the structures aren't created yet. */
+ /* Initialize all port interrupt end point to port 0 int
+ * endpoint. Our device has only one interrupt end point
+ * common to all port */
+
+ mos7840_port->port = port;
+ mos7840_set_port_private(port, mos7840_port);
+ spin_lock_init(&mos7840_port->pool_lock);
+
+ /* minor is not initialised until later by
+ * usb-serial.c:get_free_serial() and cannot therefore be used
+ * to index device instances */
+ mos7840_port->port_num = pnum + 1;
+ dev_dbg(&port->dev, "port->minor = %d\n", port->minor);
+ dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num);
+
+ if (mos7840_port->port_num == 1) {
+ mos7840_port->SpRegOffset = 0x0;
+ mos7840_port->ControlRegOffset = 0x1;
+ mos7840_port->DcrRegOffset = 0x4;
+ } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 4)) {
+ mos7840_port->SpRegOffset = 0x8;
+ mos7840_port->ControlRegOffset = 0x9;
+ mos7840_port->DcrRegOffset = 0x16;
+ } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 2)) {
+ mos7840_port->SpRegOffset = 0xa;
+ mos7840_port->ControlRegOffset = 0xb;
+ mos7840_port->DcrRegOffset = 0x19;
+ } else if ((mos7840_port->port_num == 3) && (serial->num_ports == 4)) {
+ mos7840_port->SpRegOffset = 0xa;
+ mos7840_port->ControlRegOffset = 0xb;
+ mos7840_port->DcrRegOffset = 0x19;
+ } else if ((mos7840_port->port_num == 4) && (serial->num_ports == 4)) {
+ mos7840_port->SpRegOffset = 0xc;
+ mos7840_port->ControlRegOffset = 0xd;
+ mos7840_port->DcrRegOffset = 0x1c;
+ }
+ mos7840_dump_serial_port(port, mos7840_port);
+ mos7840_set_port_private(port, mos7840_port);
+
+ /* enable rx_disable bit in control register */
+ status = mos7840_get_reg_sync(port,
+ mos7840_port->ControlRegOffset, &Data);
+ if (status < 0) {
+ dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status);
+ goto out;
+ } else
+ dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status);
+ Data |= 0x08; /* setting driver done bit */
+ Data |= 0x04; /* sp1_bit to have cts change reflect in
+ modem status reg */
- /* set up port private structures */
- for (i = 0; i < serial->num_ports; ++i) {
- dbg ("mos7840_startup: configuring port %d............", i);
- mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
- if (mos7840_port == NULL) {
- dev_err(&dev->dev, "%s - Out of memory\n", __func__);
- status = -ENOMEM;
- i--; /* don't follow NULL pointer cleaning up */
- goto error;
- }
+ /* Data |= 0x20; //rx_disable bit */
+ status = mos7840_set_reg_sync(port,
+ mos7840_port->ControlRegOffset, Data);
+ if (status < 0) {
+ dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status);
+ goto out;
+ } else
+ dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status);
- /* Initialize all port interrupt end point to port 0 int
- * endpoint. Our device has only one interrupt end point
- * common to all port */
-
- mos7840_port->port = serial->port[i];
- mos7840_set_port_private(serial->port[i], mos7840_port);
- spin_lock_init(&mos7840_port->pool_lock);
-
- /* minor is not initialised until later by
- * usb-serial.c:get_free_serial() and cannot therefore be used
- * to index device instances */
- mos7840_port->port_num = i + 1;
- dbg ("serial->port[i]->number = %d", serial->port[i]->number);
- dbg ("serial->port[i]->serial->minor = %d", serial->port[i]->serial->minor);
- dbg ("mos7840_port->port_num = %d", mos7840_port->port_num);
- dbg ("serial->minor = %d", serial->minor);
-
- if (mos7840_port->port_num == 1) {
- mos7840_port->SpRegOffset = 0x0;
- mos7840_port->ControlRegOffset = 0x1;
- mos7840_port->DcrRegOffset = 0x4;
- } else if ((mos7840_port->port_num == 2)
- && (serial->num_ports == 4)) {
- mos7840_port->SpRegOffset = 0x8;
- mos7840_port->ControlRegOffset = 0x9;
- mos7840_port->DcrRegOffset = 0x16;
- } else if ((mos7840_port->port_num == 2)
- && (serial->num_ports == 2)) {
- mos7840_port->SpRegOffset = 0xa;
- mos7840_port->ControlRegOffset = 0xb;
- mos7840_port->DcrRegOffset = 0x19;
- } else if ((mos7840_port->port_num == 3)
- && (serial->num_ports == 4)) {
- mos7840_port->SpRegOffset = 0xa;
- mos7840_port->ControlRegOffset = 0xb;
- mos7840_port->DcrRegOffset = 0x19;
- } else if ((mos7840_port->port_num == 4)
- && (serial->num_ports == 4)) {
- mos7840_port->SpRegOffset = 0xc;
- mos7840_port->ControlRegOffset = 0xd;
- mos7840_port->DcrRegOffset = 0x1c;
- }
- mos7840_dump_serial_port(mos7840_port);
- mos7840_set_port_private(serial->port[i], mos7840_port);
+ /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
+ and 0x24 in DCR3 */
+ Data = 0x01;
+ status = mos7840_set_reg_sync(port,
+ (__u16) (mos7840_port->DcrRegOffset + 0), Data);
+ if (status < 0) {
+ dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status);
+ goto out;
+ } else
+ dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status);
- /* enable rx_disable bit in control register */
- status = mos7840_get_reg_sync(serial->port[i],
- mos7840_port->ControlRegOffset, &Data);
- if (status < 0) {
- dbg("Reading ControlReg failed status-0x%x", status);
- break;
- } else
- dbg("ControlReg Reading success val is %x, status%d",
- Data, status);
- Data |= 0x08; /* setting driver done bit */
- Data |= 0x04; /* sp1_bit to have cts change reflect in
- modem status reg */
-
- /* Data |= 0x20; //rx_disable bit */
- status = mos7840_set_reg_sync(serial->port[i],
- mos7840_port->ControlRegOffset, Data);
- if (status < 0) {
- dbg("Writing ControlReg failed(rx_disable) status-0x%x", status);
- break;
- } else
- dbg("ControlReg Writing success(rx_disable) status%d",
- status);
+ Data = 0x05;
+ status = mos7840_set_reg_sync(port,
+ (__u16) (mos7840_port->DcrRegOffset + 1), Data);
+ if (status < 0) {
+ dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status);
+ goto out;
+ } else
+ dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status);
- /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
- and 0x24 in DCR3 */
- Data = 0x01;
- status = mos7840_set_reg_sync(serial->port[i],
- (__u16) (mos7840_port->DcrRegOffset + 0), Data);
- if (status < 0) {
- dbg("Writing DCR0 failed status-0x%x", status);
- break;
- } else
- dbg("DCR0 Writing success status%d", status);
+ Data = 0x24;
+ status = mos7840_set_reg_sync(port,
+ (__u16) (mos7840_port->DcrRegOffset + 2), Data);
+ if (status < 0) {
+ dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status);
+ goto out;
+ } else
+ dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status);
- Data = 0x05;
- status = mos7840_set_reg_sync(serial->port[i],
- (__u16) (mos7840_port->DcrRegOffset + 1), Data);
- if (status < 0) {
- dbg("Writing DCR1 failed status-0x%x", status);
- break;
- } else
- dbg("DCR1 Writing success status%d", status);
+ /* write values in clkstart0x0 and clkmulti 0x20 */
+ Data = 0x0;
+ status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data);
+ if (status < 0) {
+ dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
+ goto out;
+ } else
+ dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status);
- Data = 0x24;
- status = mos7840_set_reg_sync(serial->port[i],
- (__u16) (mos7840_port->DcrRegOffset + 2), Data);
- if (status < 0) {
- dbg("Writing DCR2 failed status-0x%x", status);
- break;
- } else
- dbg("DCR2 Writing success status%d", status);
+ Data = 0x20;
+ status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data);
+ if (status < 0) {
+ dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status);
+ goto error;
+ } else
+ dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status);
- /* write values in clkstart0x0 and clkmulti 0x20 */
- Data = 0x0;
- status = mos7840_set_reg_sync(serial->port[i],
- CLK_START_VALUE_REGISTER, Data);
+ /* write value 0x0 to scratchpad register */
+ Data = 0x00;
+ status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data);
+ if (status < 0) {
+ dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status);
+ goto out;
+ } else
+ dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status);
+
+ /* Zero Length flag register */
+ if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) {
+ Data = 0xff;
+ status = mos7840_set_reg_sync(port,
+ (__u16) (ZLP_REG1 +
+ ((__u16)mos7840_port->port_num)), Data);
+ dev_dbg(&port->dev, "ZLIP offset %x\n",
+ (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num)));
if (status < 0) {
- dbg("Writing CLK_START_VALUE_REGISTER failed status-0x%x", status);
- break;
+ dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status);
+ goto out;
} else
- dbg("CLK_START_VALUE_REGISTER Writing success status%d", status);
-
- Data = 0x20;
- status = mos7840_set_reg_sync(serial->port[i],
- CLK_MULTI_REGISTER, Data);
+ dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status);
+ } else {
+ Data = 0xff;
+ status = mos7840_set_reg_sync(port,
+ (__u16) (ZLP_REG1 +
+ ((__u16)mos7840_port->port_num) - 0x1), Data);
+ dev_dbg(&port->dev, "ZLIP offset %x\n",
+ (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1));
if (status < 0) {
- dbg("Writing CLK_MULTI_REGISTER failed status-0x%x",
- status);
- goto error;
+ dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status);
+ goto out;
} else
- dbg("CLK_MULTI_REGISTER Writing success status%d",
- status);
+ dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status);
- /* write value 0x0 to scratchpad register */
- Data = 0x00;
- status = mos7840_set_uart_reg(serial->port[i],
- SCRATCH_PAD_REGISTER, Data);
- if (status < 0) {
- dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x",
- status);
- break;
- } else
- dbg("SCRATCH_PAD_REGISTER Writing success status%d",
- status);
+ }
+ mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
+ mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
+ mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest),
+ GFP_KERNEL);
+ if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf ||
+ !mos7840_port->dr) {
+ status = -ENOMEM;
+ goto error;
+ }
- /* Zero Length flag register */
- if ((mos7840_port->port_num != 1)
- && (serial->num_ports == 2)) {
-
- Data = 0xff;
- status = mos7840_set_reg_sync(serial->port[i],
- (__u16) (ZLP_REG1 +
- ((__u16)mos7840_port->port_num)), Data);
- dbg("ZLIP offset %x",
- (__u16) (ZLP_REG1 +
- ((__u16) mos7840_port->port_num)));
- if (status < 0) {
- dbg("Writing ZLP_REG%d failed status-0x%x",
- i + 2, status);
- break;
- } else
- dbg("ZLP_REG%d Writing success status%d",
- i + 2, status);
- } else {
- Data = 0xff;
- status = mos7840_set_reg_sync(serial->port[i],
- (__u16) (ZLP_REG1 +
- ((__u16)mos7840_port->port_num) - 0x1), Data);
- dbg("ZLIP offset %x",
- (__u16) (ZLP_REG1 +
- ((__u16) mos7840_port->port_num) - 0x1));
- if (status < 0) {
- dbg("Writing ZLP_REG%d failed status-0x%x",
- i + 1, status);
- break;
- } else
- dbg("ZLP_REG%d Writing success status%d",
- i + 1, status);
+ mos7840_port->has_led = false;
- }
- mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
- mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
- mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest),
+ /* Initialize LED timers */
+ if (device_type == MOSCHIP_DEVICE_ID_7810) {
+ mos7840_port->has_led = true;
+
+ mos7840_port->led_urb = usb_alloc_urb(0, GFP_KERNEL);
+ mos7840_port->led_dr = kmalloc(sizeof(*mos7840_port->led_dr),
GFP_KERNEL);
- if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf ||
- !mos7840_port->dr) {
+ if (!mos7840_port->led_urb || !mos7840_port->led_dr) {
status = -ENOMEM;
goto error;
}
- }
- dbg ("mos7840_startup: all ports configured...........");
- /* Zero Length flag enable */
- Data = 0x0f;
- status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
- if (status < 0) {
- dbg("Writing ZLP_REG5 failed status-0x%x", status);
- goto error;
- } else
- dbg("ZLP_REG5 Writing success status%d", status);
+ init_timer(&mos7840_port->led_timer1);
+ mos7840_port->led_timer1.function = mos7840_led_off;
+ mos7840_port->led_timer1.expires =
+ jiffies + msecs_to_jiffies(LED_ON_MS);
+ mos7840_port->led_timer1.data = (unsigned long)mos7840_port;
+
+ init_timer(&mos7840_port->led_timer2);
+ mos7840_port->led_timer2.function = mos7840_led_flag_off;
+ mos7840_port->led_timer2.expires =
+ jiffies + msecs_to_jiffies(LED_OFF_MS);
+ mos7840_port->led_timer2.data = (unsigned long)mos7840_port;
+
+ /* Turn off LED */
+ mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);
+ }
+out:
+ if (pnum == serial->num_ports - 1) {
+ /* Zero Length flag enable */
+ Data = 0x0f;
+ status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
+ if (status < 0) {
+ dev_dbg(&port->dev, "Writing ZLP_REG5 failed status-0x%x\n", status);
+ goto error;
+ } else
+ dev_dbg(&port->dev, "ZLP_REG5 Writing success status%d\n", status);
- /* setting configuration feature to one */
- usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ);
+ /* setting configuration feature to one */
+ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ 0x03, 0x00, 0x01, 0x00, NULL, 0x00,
+ MOS_WDR_TIMEOUT);
+ }
return 0;
error:
- for (/* nothing */; i >= 0; i--) {
- mos7840_port = mos7840_get_port_private(serial->port[i]);
+ kfree(mos7840_port->led_dr);
+ usb_free_urb(mos7840_port->led_urb);
+ kfree(mos7840_port->dr);
+ kfree(mos7840_port->ctrl_buf);
+ usb_free_urb(mos7840_port->control_urb);
+ kfree(mos7840_port);
- kfree(mos7840_port->dr);
- kfree(mos7840_port->ctrl_buf);
- usb_free_urb(mos7840_port->control_urb);
- kfree(mos7840_port);
- serial->port[i] = NULL;
- }
return status;
}
-/****************************************************************************
- * mos7840_disconnect
- * This function is called whenever the device is removed from the usb bus.
- ****************************************************************************/
-
-static void mos7840_disconnect(struct usb_serial *serial)
+static int mos7840_port_remove(struct usb_serial_port *port)
{
- int i;
- unsigned long flags;
struct moschip_port *mos7840_port;
- dbg("%s", " disconnect :entering..........");
-
- if (!serial) {
- dbg("%s", "Invalid Handler");
- return;
- }
-
- /* check for the ports to be closed,close the ports and disconnect */
-
- /* free private structure allocated for serial port *
- * stop reads and writes on all ports */
-
- for (i = 0; i < serial->num_ports; ++i) {
- mos7840_port = mos7840_get_port_private(serial->port[i]);
- dbg ("mos7840_port %d = %p", i, mos7840_port);
- if (mos7840_port) {
- spin_lock_irqsave(&mos7840_port->pool_lock, flags);
- mos7840_port->zombie = 1;
- spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
- usb_kill_urb(mos7840_port->control_urb);
- }
- }
- dbg("%s", "Thank u :: ");
+ mos7840_port = mos7840_get_port_private(port);
-}
+ if (mos7840_port->has_led) {
+ /* Turn off LED */
+ mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);
-/****************************************************************************
- * mos7840_release
- * This function is called when the usb_serial structure is freed.
- ****************************************************************************/
+ del_timer_sync(&mos7840_port->led_timer1);
+ del_timer_sync(&mos7840_port->led_timer2);
-static void mos7840_release(struct usb_serial *serial)
-{
- int i;
- struct moschip_port *mos7840_port;
- dbg("%s", " release :entering..........");
-
- if (!serial) {
- dbg("%s", "Invalid Handler");
- return;
+ usb_kill_urb(mos7840_port->led_urb);
+ usb_free_urb(mos7840_port->led_urb);
+ kfree(mos7840_port->led_dr);
}
+ usb_kill_urb(mos7840_port->control_urb);
+ usb_free_urb(mos7840_port->control_urb);
+ kfree(mos7840_port->ctrl_buf);
+ kfree(mos7840_port->dr);
+ kfree(mos7840_port);
- /* check for the ports to be closed,close the ports and disconnect */
-
- /* free private structure allocated for serial port *
- * stop reads and writes on all ports */
-
- for (i = 0; i < serial->num_ports; ++i) {
- mos7840_port = mos7840_get_port_private(serial->port[i]);
- dbg("mos7840_port %d = %p", i, mos7840_port);
- if (mos7840_port) {
- kfree(mos7840_port->ctrl_buf);
- kfree(mos7840_port->dr);
- kfree(mos7840_port);
- }
- }
-
- dbg("%s", "Thank u :: ");
-
+ return 0;
}
-static struct usb_driver io_driver = {
- .name = "mos7840",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = moschip_id_table_combined,
- .no_dynamic_id = 1,
-};
-
static struct usb_serial_driver moschip7840_4port_device = {
.driver = {
.owner = THIS_MODULE,
.name = "mos7840",
},
.description = DRIVER_DESC,
- .usb_driver = &io_driver,
- .id_table = moschip_port_id_table,
+ .id_table = id_table,
.num_ports = 4,
.open = mos7840_open,
.close = mos7840_close,
@@ -2663,75 +2449,25 @@ static struct usb_serial_driver moschip7840_4port_device = {
.throttle = mos7840_throttle,
.unthrottle = mos7840_unthrottle,
.calc_num_ports = mos7840_calc_num_ports,
-#ifdef MCSSerialProbe
- .probe = mos7840_serial_probe,
-#endif
+ .probe = mos7840_probe,
.ioctl = mos7840_ioctl,
.set_termios = mos7840_set_termios,
.break_ctl = mos7840_break,
.tiocmget = mos7840_tiocmget,
.tiocmset = mos7840_tiocmset,
- .get_icount = mos7840_get_icount,
- .attach = mos7840_startup,
- .disconnect = mos7840_disconnect,
- .release = mos7840_release,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
+ .port_probe = mos7840_port_probe,
+ .port_remove = mos7840_port_remove,
.read_bulk_callback = mos7840_bulk_in_callback,
.read_int_callback = mos7840_interrupt_callback,
};
-/****************************************************************************
- * moschip7840_init
- * This is called by the module subsystem, or on startup to initialize us
- ****************************************************************************/
-static int __init moschip7840_init(void)
-{
- int retval;
-
- dbg("%s", " mos7840_init :entering..........");
-
- /* Register with the usb serial */
- retval = usb_serial_register(&moschip7840_4port_device);
-
- if (retval)
- goto failed_port_device_register;
-
- dbg("%s", "Entering...");
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- /* Register with the usb */
- retval = usb_register(&io_driver);
- if (retval == 0) {
- dbg("%s", "Leaving...");
- return 0;
- }
- usb_serial_deregister(&moschip7840_4port_device);
-failed_port_device_register:
- return retval;
-}
-
-/****************************************************************************
- * moschip7840_exit
- * Called when the driver is about to be unloaded.
- ****************************************************************************/
-static void __exit moschip7840_exit(void)
-{
-
- dbg("%s", " mos7840_exit :entering..........");
-
- usb_deregister(&io_driver);
-
- usb_serial_deregister(&moschip7840_4port_device);
-
- dbg("%s", "Entering...");
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &moschip7840_4port_device, NULL
+};
-module_init(moschip7840_init);
-module_exit(moschip7840_exit);
+module_usb_serial_driver(serial_drivers, id_table);
-/* Module information */
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c
deleted file mode 100644
index cf1718394e1..00000000000
--- a/drivers/usb/serial/moto_modem.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Motorola USB Phone driver
- *
- * Copyright (C) 2008 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 version 2 as
- * published by the Free Software Foundation.
- *
- * {sigh}
- * Motorola should be using the CDC ACM USB spec, but instead
- * they try to just "do their own thing"... This driver should handle a
- * few phones in which a basic "dumb serial connection" is needed to be
- * able to get a connection through to them.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-
-static const struct usb_device_id id_table[] = {
- { USB_DEVICE(0x05c6, 0x3197) }, /* unknown Motorola phone */
- { USB_DEVICE(0x0c44, 0x0022) }, /* unknown Mororola phone */
- { USB_DEVICE(0x22b8, 0x2a64) }, /* Motorola KRZR K1m */
- { USB_DEVICE(0x22b8, 0x2c64) }, /* Motorola V950 phone */
- { },
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static struct usb_driver moto_driver = {
- .name = "moto-modem",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
-static struct usb_serial_driver moto_device = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "moto-modem",
- },
- .id_table = id_table,
- .num_ports = 1,
-};
-
-static int __init moto_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&moto_device);
- if (retval)
- return retval;
- retval = usb_register(&moto_driver);
- if (retval)
- usb_serial_deregister(&moto_device);
- return retval;
-}
-
-static void __exit moto_exit(void)
-{
- usb_deregister(&moto_driver);
- usb_serial_deregister(&moto_device);
-}
-
-module_init(moto_init);
-module_exit(moto_exit);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c
new file mode 100644
index 00000000000..ab1d690274a
--- /dev/null
+++ b/drivers/usb/serial/mxuport.c
@@ -0,0 +1,1393 @@
+/*
+ * mxuport.c - MOXA UPort series driver
+ *
+ * Copyright (c) 2006 Moxa Technologies Co., Ltd.
+ * Copyright (c) 2013 Andrew Lunn <andrew@lunn.ch>
+ *
+ * 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.
+ *
+ * Supports the following Moxa USB to serial converters:
+ * 2 ports : UPort 1250, UPort 1250I
+ * 4 ports : UPort 1410, UPort 1450, UPort 1450I
+ * 8 ports : UPort 1610-8, UPort 1650-8
+ * 16 ports : UPort 1610-16, UPort 1650-16
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/jiffies.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <asm/unaligned.h>
+
+/* Definitions for the vendor ID and device ID */
+#define MX_USBSERIAL_VID 0x110A
+#define MX_UPORT1250_PID 0x1250
+#define MX_UPORT1251_PID 0x1251
+#define MX_UPORT1410_PID 0x1410
+#define MX_UPORT1450_PID 0x1450
+#define MX_UPORT1451_PID 0x1451
+#define MX_UPORT1618_PID 0x1618
+#define MX_UPORT1658_PID 0x1658
+#define MX_UPORT1613_PID 0x1613
+#define MX_UPORT1653_PID 0x1653
+
+/* Definitions for USB info */
+#define HEADER_SIZE 4
+#define EVENT_LENGTH 8
+#define DOWN_BLOCK_SIZE 64
+
+/* Definitions for firmware info */
+#define VER_ADDR_1 0x20
+#define VER_ADDR_2 0x24
+#define VER_ADDR_3 0x28
+
+/* Definitions for USB vendor request */
+#define RQ_VENDOR_NONE 0x00
+#define RQ_VENDOR_SET_BAUD 0x01 /* Set baud rate */
+#define RQ_VENDOR_SET_LINE 0x02 /* Set line status */
+#define RQ_VENDOR_SET_CHARS 0x03 /* Set Xon/Xoff chars */
+#define RQ_VENDOR_SET_RTS 0x04 /* Set RTS */
+#define RQ_VENDOR_SET_DTR 0x05 /* Set DTR */
+#define RQ_VENDOR_SET_XONXOFF 0x06 /* Set auto Xon/Xoff */
+#define RQ_VENDOR_SET_RX_HOST_EN 0x07 /* Set RX host enable */
+#define RQ_VENDOR_SET_OPEN 0x08 /* Set open/close port */
+#define RQ_VENDOR_PURGE 0x09 /* Purge Rx/Tx buffer */
+#define RQ_VENDOR_SET_MCR 0x0A /* Set MCR register */
+#define RQ_VENDOR_SET_BREAK 0x0B /* Set Break signal */
+
+#define RQ_VENDOR_START_FW_DOWN 0x0C /* Start firmware download */
+#define RQ_VENDOR_STOP_FW_DOWN 0x0D /* Stop firmware download */
+#define RQ_VENDOR_QUERY_FW_READY 0x0E /* Query if new firmware ready */
+
+#define RQ_VENDOR_SET_FIFO_DISABLE 0x0F /* Set fifo disable */
+#define RQ_VENDOR_SET_INTERFACE 0x10 /* Set interface */
+#define RQ_VENDOR_SET_HIGH_PERFOR 0x11 /* Set hi-performance */
+
+#define RQ_VENDOR_ERASE_BLOCK 0x12 /* Erase flash block */
+#define RQ_VENDOR_WRITE_PAGE 0x13 /* Write flash page */
+#define RQ_VENDOR_PREPARE_WRITE 0x14 /* Prepare write flash */
+#define RQ_VENDOR_CONFIRM_WRITE 0x15 /* Confirm write flash */
+#define RQ_VENDOR_LOCATE 0x16 /* Locate the device */
+
+#define RQ_VENDOR_START_ROM_DOWN 0x17 /* Start firmware download */
+#define RQ_VENDOR_ROM_DATA 0x18 /* Rom file data */
+#define RQ_VENDOR_STOP_ROM_DOWN 0x19 /* Stop firmware download */
+#define RQ_VENDOR_FW_DATA 0x20 /* Firmware data */
+
+#define RQ_VENDOR_RESET_DEVICE 0x23 /* Try to reset the device */
+#define RQ_VENDOR_QUERY_FW_CONFIG 0x24
+
+#define RQ_VENDOR_GET_VERSION 0x81 /* Get firmware version */
+#define RQ_VENDOR_GET_PAGE 0x82 /* Read flash page */
+#define RQ_VENDOR_GET_ROM_PROC 0x83 /* Get ROM process state */
+
+#define RQ_VENDOR_GET_INQUEUE 0x84 /* Data in input buffer */
+#define RQ_VENDOR_GET_OUTQUEUE 0x85 /* Data in output buffer */
+
+#define RQ_VENDOR_GET_MSR 0x86 /* Get modem status register */
+
+/* Definitions for UPort event type */
+#define UPORT_EVENT_NONE 0 /* None */
+#define UPORT_EVENT_TXBUF_THRESHOLD 1 /* Tx buffer threshold */
+#define UPORT_EVENT_SEND_NEXT 2 /* Send next */
+#define UPORT_EVENT_MSR 3 /* Modem status */
+#define UPORT_EVENT_LSR 4 /* Line status */
+#define UPORT_EVENT_MCR 5 /* Modem control */
+
+/* Definitions for serial event type */
+#define SERIAL_EV_CTS 0x0008 /* CTS changed state */
+#define SERIAL_EV_DSR 0x0010 /* DSR changed state */
+#define SERIAL_EV_RLSD 0x0020 /* RLSD changed state */
+
+/* Definitions for modem control event type */
+#define SERIAL_EV_XOFF 0x40 /* XOFF received */
+
+/* Definitions for line control of communication */
+#define MX_WORDLENGTH_5 5
+#define MX_WORDLENGTH_6 6
+#define MX_WORDLENGTH_7 7
+#define MX_WORDLENGTH_8 8
+
+#define MX_PARITY_NONE 0
+#define MX_PARITY_ODD 1
+#define MX_PARITY_EVEN 2
+#define MX_PARITY_MARK 3
+#define MX_PARITY_SPACE 4
+
+#define MX_STOP_BITS_1 0
+#define MX_STOP_BITS_1_5 1
+#define MX_STOP_BITS_2 2
+
+#define MX_RTS_DISABLE 0x0
+#define MX_RTS_ENABLE 0x1
+#define MX_RTS_HW 0x2
+#define MX_RTS_NO_CHANGE 0x3 /* Flag, not valid register value*/
+
+#define MX_INT_RS232 0
+#define MX_INT_2W_RS485 1
+#define MX_INT_RS422 2
+#define MX_INT_4W_RS485 3
+
+/* Definitions for holding reason */
+#define MX_WAIT_FOR_CTS 0x0001
+#define MX_WAIT_FOR_DSR 0x0002
+#define MX_WAIT_FOR_DCD 0x0004
+#define MX_WAIT_FOR_XON 0x0008
+#define MX_WAIT_FOR_START_TX 0x0010
+#define MX_WAIT_FOR_UNTHROTTLE 0x0020
+#define MX_WAIT_FOR_LOW_WATER 0x0040
+#define MX_WAIT_FOR_SEND_NEXT 0x0080
+
+#define MX_UPORT_2_PORT BIT(0)
+#define MX_UPORT_4_PORT BIT(1)
+#define MX_UPORT_8_PORT BIT(2)
+#define MX_UPORT_16_PORT BIT(3)
+
+/* This structure holds all of the local port information */
+struct mxuport_port {
+ u8 mcr_state; /* Last MCR state */
+ u8 msr_state; /* Last MSR state */
+ struct mutex mutex; /* Protects mcr_state */
+ spinlock_t spinlock; /* Protects msr_state */
+};
+
+/* Table of devices that work with this driver */
+static const struct usb_device_id mxuport_idtable[] = {
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1250_PID),
+ .driver_info = MX_UPORT_2_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1251_PID),
+ .driver_info = MX_UPORT_2_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1410_PID),
+ .driver_info = MX_UPORT_4_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1450_PID),
+ .driver_info = MX_UPORT_4_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1451_PID),
+ .driver_info = MX_UPORT_4_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1618_PID),
+ .driver_info = MX_UPORT_8_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1658_PID),
+ .driver_info = MX_UPORT_8_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1613_PID),
+ .driver_info = MX_UPORT_16_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1653_PID),
+ .driver_info = MX_UPORT_16_PORT },
+ {} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, mxuport_idtable);
+
+/*
+ * Add a four byte header containing the port number and the number of
+ * bytes of data in the message. Return the number of bytes in the
+ * buffer.
+ */
+static int mxuport_prepare_write_buffer(struct usb_serial_port *port,
+ void *dest, size_t size)
+{
+ u8 *buf = dest;
+ int count;
+
+ count = kfifo_out_locked(&port->write_fifo, buf + HEADER_SIZE,
+ size - HEADER_SIZE,
+ &port->lock);
+
+ put_unaligned_be16(port->port_number, buf);
+ put_unaligned_be16(count, buf + 2);
+
+ dev_dbg(&port->dev, "%s - size %zd count %d\n", __func__,
+ size, count);
+
+ return count + HEADER_SIZE;
+}
+
+/* Read the given buffer in from the control pipe. */
+static int mxuport_recv_ctrl_urb(struct usb_serial *serial,
+ u8 request, u16 value, u16 index,
+ u8 *data, size_t size)
+{
+ int status;
+
+ status = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ request,
+ (USB_DIR_IN | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE), value, index,
+ data, size,
+ USB_CTRL_GET_TIMEOUT);
+ if (status < 0) {
+ dev_err(&serial->interface->dev,
+ "%s - usb_control_msg failed (%d)\n",
+ __func__, status);
+ return status;
+ }
+
+ if (status != size) {
+ dev_err(&serial->interface->dev,
+ "%s - short read (%d / %zd)\n",
+ __func__, status, size);
+ return -EIO;
+ }
+
+ return status;
+}
+
+/* Write the given buffer out to the control pipe. */
+static int mxuport_send_ctrl_data_urb(struct usb_serial *serial,
+ u8 request,
+ u16 value, u16 index,
+ u8 *data, size_t size)
+{
+ int status;
+
+ status = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ request,
+ (USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE), value, index,
+ data, size,
+ USB_CTRL_SET_TIMEOUT);
+ if (status < 0) {
+ dev_err(&serial->interface->dev,
+ "%s - usb_control_msg failed (%d)\n",
+ __func__, status);
+ return status;
+ }
+
+ if (status != size) {
+ dev_err(&serial->interface->dev,
+ "%s - short write (%d / %zd)\n",
+ __func__, status, size);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/* Send a vendor request without any data */
+static int mxuport_send_ctrl_urb(struct usb_serial *serial,
+ u8 request, u16 value, u16 index)
+{
+ return mxuport_send_ctrl_data_urb(serial, request, value, index,
+ NULL, 0);
+}
+
+/*
+ * mxuport_throttle - throttle function of driver
+ *
+ * This function is called by the tty driver when it wants to stop the
+ * data being read from the port. Since all the data comes over one
+ * bulk in endpoint, we cannot stop submitting urbs by setting
+ * port->throttle. Instead tell the device to stop sending us data for
+ * the port.
+ */
+static void mxuport_throttle(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct usb_serial *serial = port->serial;
+
+ dev_dbg(&port->dev, "%s\n", __func__);
+
+ mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_RX_HOST_EN,
+ 0, port->port_number);
+}
+
+/*
+ * mxuport_unthrottle - unthrottle function of driver
+ *
+ * This function is called by the tty driver when it wants to resume
+ * the data being read from the port. Tell the device it can resume
+ * sending us received data from the port.
+ */
+static void mxuport_unthrottle(struct tty_struct *tty)
+{
+
+ struct usb_serial_port *port = tty->driver_data;
+ struct usb_serial *serial = port->serial;
+
+ dev_dbg(&port->dev, "%s\n", __func__);
+
+ mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_RX_HOST_EN,
+ 1, port->port_number);
+}
+
+/*
+ * Processes one chunk of data received for a port. Mostly a copy of
+ * usb_serial_generic_process_read_urb().
+ */
+static void mxuport_process_read_urb_data(struct usb_serial_port *port,
+ char *data, int size)
+{
+ int i;
+
+ if (!port->port.console || !port->sysrq) {
+ tty_insert_flip_string(&port->port, data, size);
+ } else {
+ for (i = 0; i < size; i++, data++) {
+ if (!usb_serial_handle_sysrq_char(port, *data))
+ tty_insert_flip_char(&port->port, *data,
+ TTY_NORMAL);
+ }
+ }
+ tty_flip_buffer_push(&port->port);
+}
+
+static void mxuport_msr_event(struct usb_serial_port *port, u8 buf[4])
+{
+ struct mxuport_port *mxport = usb_get_serial_port_data(port);
+ u8 rcv_msr_hold = buf[2] & 0xF0;
+ u16 rcv_msr_event = get_unaligned_be16(buf);
+ unsigned long flags;
+
+ if (rcv_msr_event == 0)
+ return;
+
+ /* Update MSR status */
+ spin_lock_irqsave(&mxport->spinlock, flags);
+
+ dev_dbg(&port->dev, "%s - current MSR status = 0x%x\n",
+ __func__, mxport->msr_state);
+
+ if (rcv_msr_hold & UART_MSR_CTS) {
+ mxport->msr_state |= UART_MSR_CTS;
+ dev_dbg(&port->dev, "%s - CTS high\n", __func__);
+ } else {
+ mxport->msr_state &= ~UART_MSR_CTS;
+ dev_dbg(&port->dev, "%s - CTS low\n", __func__);
+ }
+
+ if (rcv_msr_hold & UART_MSR_DSR) {
+ mxport->msr_state |= UART_MSR_DSR;
+ dev_dbg(&port->dev, "%s - DSR high\n", __func__);
+ } else {
+ mxport->msr_state &= ~UART_MSR_DSR;
+ dev_dbg(&port->dev, "%s - DSR low\n", __func__);
+ }
+
+ if (rcv_msr_hold & UART_MSR_DCD) {
+ mxport->msr_state |= UART_MSR_DCD;
+ dev_dbg(&port->dev, "%s - DCD high\n", __func__);
+ } else {
+ mxport->msr_state &= ~UART_MSR_DCD;
+ dev_dbg(&port->dev, "%s - DCD low\n", __func__);
+ }
+ spin_unlock_irqrestore(&mxport->spinlock, flags);
+
+ if (rcv_msr_event &
+ (SERIAL_EV_CTS | SERIAL_EV_DSR | SERIAL_EV_RLSD)) {
+
+ if (rcv_msr_event & SERIAL_EV_CTS) {
+ port->icount.cts++;
+ dev_dbg(&port->dev, "%s - CTS change\n", __func__);
+ }
+
+ if (rcv_msr_event & SERIAL_EV_DSR) {
+ port->icount.dsr++;
+ dev_dbg(&port->dev, "%s - DSR change\n", __func__);
+ }
+
+ if (rcv_msr_event & SERIAL_EV_RLSD) {
+ port->icount.dcd++;
+ dev_dbg(&port->dev, "%s - DCD change\n", __func__);
+ }
+ wake_up_interruptible(&port->port.delta_msr_wait);
+ }
+}
+
+static void mxuport_lsr_event(struct usb_serial_port *port, u8 buf[4])
+{
+ u8 lsr_event = buf[2];
+
+ if (lsr_event & UART_LSR_BI) {
+ port->icount.brk++;
+ dev_dbg(&port->dev, "%s - break error\n", __func__);
+ }
+
+ if (lsr_event & UART_LSR_FE) {
+ port->icount.frame++;
+ dev_dbg(&port->dev, "%s - frame error\n", __func__);
+ }
+
+ if (lsr_event & UART_LSR_PE) {
+ port->icount.parity++;
+ dev_dbg(&port->dev, "%s - parity error\n", __func__);
+ }
+
+ if (lsr_event & UART_LSR_OE) {
+ port->icount.overrun++;
+ dev_dbg(&port->dev, "%s - overrun error\n", __func__);
+ }
+}
+
+/*
+ * When something interesting happens, modem control lines XON/XOFF
+ * etc, the device sends an event. Process these events.
+ */
+static void mxuport_process_read_urb_event(struct usb_serial_port *port,
+ u8 buf[4], u32 event)
+{
+ dev_dbg(&port->dev, "%s - receive event : %04x\n", __func__, event);
+
+ switch (event) {
+ case UPORT_EVENT_SEND_NEXT:
+ /*
+ * Sent as part of the flow control on device buffers.
+ * Not currently used.
+ */
+ break;
+ case UPORT_EVENT_MSR:
+ mxuport_msr_event(port, buf);
+ break;
+ case UPORT_EVENT_LSR:
+ mxuport_lsr_event(port, buf);
+ break;
+ case UPORT_EVENT_MCR:
+ /*
+ * Event to indicate a change in XON/XOFF from the
+ * peer. Currently not used. We just continue
+ * sending the device data and it will buffer it if
+ * needed. This event could be used for flow control
+ * between the host and the device.
+ */
+ break;
+ default:
+ dev_dbg(&port->dev, "Unexpected event\n");
+ break;
+ }
+}
+
+/*
+ * One URB can contain data for multiple ports. Demultiplex the data,
+ * checking the port exists, is opened and the message is valid.
+ */
+static void mxuport_process_read_urb_demux_data(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+ struct usb_serial *serial = port->serial;
+ u8 *data = urb->transfer_buffer;
+ u8 *end = data + urb->actual_length;
+ struct usb_serial_port *demux_port;
+ u8 *ch;
+ u16 rcv_port;
+ u16 rcv_len;
+
+ while (data < end) {
+ if (data + HEADER_SIZE > end) {
+ dev_warn(&port->dev, "%s - message with short header\n",
+ __func__);
+ return;
+ }
+
+ rcv_port = get_unaligned_be16(data);
+ if (rcv_port >= serial->num_ports) {
+ dev_warn(&port->dev, "%s - message for invalid port\n",
+ __func__);
+ return;
+ }
+
+ demux_port = serial->port[rcv_port];
+ rcv_len = get_unaligned_be16(data + 2);
+ if (!rcv_len || data + HEADER_SIZE + rcv_len > end) {
+ dev_warn(&port->dev, "%s - short data\n", __func__);
+ return;
+ }
+
+ if (test_bit(ASYNCB_INITIALIZED, &demux_port->port.flags)) {
+ ch = data + HEADER_SIZE;
+ mxuport_process_read_urb_data(demux_port, ch, rcv_len);
+ } else {
+ dev_dbg(&demux_port->dev, "%s - data for closed port\n",
+ __func__);
+ }
+ data += HEADER_SIZE + rcv_len;
+ }
+}
+
+/*
+ * One URB can contain events for multiple ports. Demultiplex the event,
+ * checking the port exists, and is opened.
+ */
+static void mxuport_process_read_urb_demux_event(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+ struct usb_serial *serial = port->serial;
+ u8 *data = urb->transfer_buffer;
+ u8 *end = data + urb->actual_length;
+ struct usb_serial_port *demux_port;
+ u8 *ch;
+ u16 rcv_port;
+ u16 rcv_event;
+
+ while (data < end) {
+ if (data + EVENT_LENGTH > end) {
+ dev_warn(&port->dev, "%s - message with short event\n",
+ __func__);
+ return;
+ }
+
+ rcv_port = get_unaligned_be16(data);
+ if (rcv_port >= serial->num_ports) {
+ dev_warn(&port->dev, "%s - message for invalid port\n",
+ __func__);
+ return;
+ }
+
+ demux_port = serial->port[rcv_port];
+ if (test_bit(ASYNCB_INITIALIZED, &demux_port->port.flags)) {
+ ch = data + HEADER_SIZE;
+ rcv_event = get_unaligned_be16(data + 2);
+ mxuport_process_read_urb_event(demux_port, ch,
+ rcv_event);
+ } else {
+ dev_dbg(&demux_port->dev,
+ "%s - event for closed port\n", __func__);
+ }
+ data += EVENT_LENGTH;
+ }
+}
+
+/*
+ * This is called when we have received data on the bulk in
+ * endpoint. Depending on which port it was received on, it can
+ * contain serial data or events.
+ */
+static void mxuport_process_read_urb(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+ struct usb_serial *serial = port->serial;
+
+ if (port == serial->port[0])
+ mxuport_process_read_urb_demux_data(urb);
+
+ if (port == serial->port[1])
+ mxuport_process_read_urb_demux_event(urb);
+}
+
+/*
+ * Ask the device how many bytes it has queued to be sent out. If
+ * there are none, return true.
+ */
+static bool mxuport_tx_empty(struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+ bool is_empty = true;
+ u32 txlen;
+ u8 *len_buf;
+ int err;
+
+ len_buf = kzalloc(4, GFP_KERNEL);
+ if (!len_buf)
+ goto out;
+
+ err = mxuport_recv_ctrl_urb(serial, RQ_VENDOR_GET_OUTQUEUE, 0,
+ port->port_number, len_buf, 4);
+ if (err < 0)
+ goto out;
+
+ txlen = get_unaligned_be32(len_buf);
+ dev_dbg(&port->dev, "%s - tx len = %u\n", __func__, txlen);
+
+ if (txlen != 0)
+ is_empty = false;
+
+out:
+ kfree(len_buf);
+ return is_empty;
+}
+
+static int mxuport_set_mcr(struct usb_serial_port *port, u8 mcr_state)
+{
+ struct usb_serial *serial = port->serial;
+ int err;
+
+ dev_dbg(&port->dev, "%s - %02x\n", __func__, mcr_state);
+
+ err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_MCR,
+ mcr_state, port->port_number);
+ if (err)
+ dev_err(&port->dev, "%s - failed to change MCR\n", __func__);
+
+ return err;
+}
+
+static int mxuport_set_dtr(struct usb_serial_port *port, int on)
+{
+ struct mxuport_port *mxport = usb_get_serial_port_data(port);
+ struct usb_serial *serial = port->serial;
+ int err;
+
+ mutex_lock(&mxport->mutex);
+
+ err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_DTR,
+ !!on, port->port_number);
+ if (!err) {
+ if (on)
+ mxport->mcr_state |= UART_MCR_DTR;
+ else
+ mxport->mcr_state &= ~UART_MCR_DTR;
+ }
+
+ mutex_unlock(&mxport->mutex);
+
+ return err;
+}
+
+static int mxuport_set_rts(struct usb_serial_port *port, u8 state)
+{
+ struct mxuport_port *mxport = usb_get_serial_port_data(port);
+ struct usb_serial *serial = port->serial;
+ int err;
+ u8 mcr_state;
+
+ mutex_lock(&mxport->mutex);
+ mcr_state = mxport->mcr_state;
+
+ switch (state) {
+ case MX_RTS_DISABLE:
+ mcr_state &= ~UART_MCR_RTS;
+ break;
+ case MX_RTS_ENABLE:
+ mcr_state |= UART_MCR_RTS;
+ break;
+ case MX_RTS_HW:
+ /*
+ * Do not update mxport->mcr_state when doing hardware
+ * flow control.
+ */
+ break;
+ default:
+ /*
+ * Should not happen, but somebody might try passing
+ * MX_RTS_NO_CHANGE, which is not valid.
+ */
+ err = -EINVAL;
+ goto out;
+ }
+ err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_RTS,
+ state, port->port_number);
+ if (!err)
+ mxport->mcr_state = mcr_state;
+
+out:
+ mutex_unlock(&mxport->mutex);
+
+ return err;
+}
+
+static void mxuport_dtr_rts(struct usb_serial_port *port, int on)
+{
+ struct mxuport_port *mxport = usb_get_serial_port_data(port);
+ u8 mcr_state;
+ int err;
+
+ mutex_lock(&mxport->mutex);
+ mcr_state = mxport->mcr_state;
+
+ if (on)
+ mcr_state |= (UART_MCR_RTS | UART_MCR_DTR);
+ else
+ mcr_state &= ~(UART_MCR_RTS | UART_MCR_DTR);
+
+ err = mxuport_set_mcr(port, mcr_state);
+ if (!err)
+ mxport->mcr_state = mcr_state;
+
+ mutex_unlock(&mxport->mutex);
+}
+
+static int mxuport_tiocmset(struct tty_struct *tty, unsigned int set,
+ unsigned int clear)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct mxuport_port *mxport = usb_get_serial_port_data(port);
+ int err;
+ u8 mcr_state;
+
+ mutex_lock(&mxport->mutex);
+ mcr_state = mxport->mcr_state;
+
+ if (set & TIOCM_RTS)
+ mcr_state |= UART_MCR_RTS;
+
+ if (set & TIOCM_DTR)
+ mcr_state |= UART_MCR_DTR;
+
+ if (clear & TIOCM_RTS)
+ mcr_state &= ~UART_MCR_RTS;
+
+ if (clear & TIOCM_DTR)
+ mcr_state &= ~UART_MCR_DTR;
+
+ err = mxuport_set_mcr(port, mcr_state);
+ if (!err)
+ mxport->mcr_state = mcr_state;
+
+ mutex_unlock(&mxport->mutex);
+
+ return err;
+}
+
+static int mxuport_tiocmget(struct tty_struct *tty)
+{
+ struct mxuport_port *mxport;
+ struct usb_serial_port *port = tty->driver_data;
+ unsigned int result;
+ unsigned long flags;
+ unsigned int msr;
+ unsigned int mcr;
+
+ mxport = usb_get_serial_port_data(port);
+
+ mutex_lock(&mxport->mutex);
+ spin_lock_irqsave(&mxport->spinlock, flags);
+
+ msr = mxport->msr_state;
+ mcr = mxport->mcr_state;
+
+ spin_unlock_irqrestore(&mxport->spinlock, flags);
+ mutex_unlock(&mxport->mutex);
+
+ result = (((mcr & UART_MCR_DTR) ? TIOCM_DTR : 0) | /* 0x002 */
+ ((mcr & UART_MCR_RTS) ? TIOCM_RTS : 0) | /* 0x004 */
+ ((msr & UART_MSR_CTS) ? TIOCM_CTS : 0) | /* 0x020 */
+ ((msr & UART_MSR_DCD) ? TIOCM_CAR : 0) | /* 0x040 */
+ ((msr & UART_MSR_RI) ? TIOCM_RI : 0) | /* 0x080 */
+ ((msr & UART_MSR_DSR) ? TIOCM_DSR : 0)); /* 0x100 */
+
+ dev_dbg(&port->dev, "%s - 0x%04x\n", __func__, result);
+
+ return result;
+}
+
+static int mxuport_set_termios_flow(struct tty_struct *tty,
+ struct ktermios *old_termios,
+ struct usb_serial_port *port,
+ struct usb_serial *serial)
+{
+ u8 xon = START_CHAR(tty);
+ u8 xoff = STOP_CHAR(tty);
+ int enable;
+ int err;
+ u8 *buf;
+ u8 rts;
+
+ buf = kmalloc(2, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* S/W flow control settings */
+ if (I_IXOFF(tty) || I_IXON(tty)) {
+ enable = 1;
+ buf[0] = xon;
+ buf[1] = xoff;
+
+ err = mxuport_send_ctrl_data_urb(serial, RQ_VENDOR_SET_CHARS,
+ 0, port->port_number,
+ buf, 2);
+ if (err)
+ goto out;
+
+ dev_dbg(&port->dev, "%s - XON = 0x%02x, XOFF = 0x%02x\n",
+ __func__, xon, xoff);
+ } else {
+ enable = 0;
+ }
+
+ err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_XONXOFF,
+ enable, port->port_number);
+ if (err)
+ goto out;
+
+ rts = MX_RTS_NO_CHANGE;
+
+ /* H/W flow control settings */
+ if (!old_termios ||
+ C_CRTSCTS(tty) != (old_termios->c_cflag & CRTSCTS)) {
+ if (C_CRTSCTS(tty))
+ rts = MX_RTS_HW;
+ else
+ rts = MX_RTS_ENABLE;
+ }
+
+ if (C_BAUD(tty)) {
+ if (old_termios && (old_termios->c_cflag & CBAUD) == B0) {
+ /* Raise DTR and RTS */
+ if (C_CRTSCTS(tty))
+ rts = MX_RTS_HW;
+ else
+ rts = MX_RTS_ENABLE;
+ mxuport_set_dtr(port, 1);
+ }
+ } else {
+ /* Drop DTR and RTS */
+ rts = MX_RTS_DISABLE;
+ mxuport_set_dtr(port, 0);
+ }
+
+ if (rts != MX_RTS_NO_CHANGE)
+ err = mxuport_set_rts(port, rts);
+
+out:
+ kfree(buf);
+ return err;
+}
+
+static void mxuport_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ struct ktermios *old_termios)
+{
+ struct usb_serial *serial = port->serial;
+ u8 *buf;
+ u8 data_bits;
+ u8 stop_bits;
+ u8 parity;
+ int baud;
+ int err;
+
+ if (old_termios &&
+ !tty_termios_hw_change(&tty->termios, old_termios) &&
+ tty->termios.c_iflag == old_termios->c_iflag) {
+ dev_dbg(&port->dev, "%s - nothing to change\n", __func__);
+ return;
+ }
+
+ buf = kmalloc(4, GFP_KERNEL);
+ if (!buf)
+ return;
+
+ /* Set data bit of termios */
+ switch (C_CSIZE(tty)) {
+ case CS5:
+ data_bits = MX_WORDLENGTH_5;
+ break;
+ case CS6:
+ data_bits = MX_WORDLENGTH_6;
+ break;
+ case CS7:
+ data_bits = MX_WORDLENGTH_7;
+ break;
+ case CS8:
+ default:
+ data_bits = MX_WORDLENGTH_8;
+ break;
+ }
+
+ /* Set parity of termios */
+ if (C_PARENB(tty)) {
+ if (C_CMSPAR(tty)) {
+ if (C_PARODD(tty))
+ parity = MX_PARITY_MARK;
+ else
+ parity = MX_PARITY_SPACE;
+ } else {
+ if (C_PARODD(tty))
+ parity = MX_PARITY_ODD;
+ else
+ parity = MX_PARITY_EVEN;
+ }
+ } else {
+ parity = MX_PARITY_NONE;
+ }
+
+ /* Set stop bit of termios */
+ if (C_CSTOPB(tty))
+ stop_bits = MX_STOP_BITS_2;
+ else
+ stop_bits = MX_STOP_BITS_1;
+
+ buf[0] = data_bits;
+ buf[1] = parity;
+ buf[2] = stop_bits;
+ buf[3] = 0;
+
+ err = mxuport_send_ctrl_data_urb(serial, RQ_VENDOR_SET_LINE,
+ 0, port->port_number, buf, 4);
+ if (err)
+ goto out;
+
+ err = mxuport_set_termios_flow(tty, old_termios, port, serial);
+ if (err)
+ goto out;
+
+ baud = tty_get_baud_rate(tty);
+ if (!baud)
+ baud = 9600;
+
+ /* Note: Little Endian */
+ put_unaligned_le32(baud, buf);
+
+ err = mxuport_send_ctrl_data_urb(serial, RQ_VENDOR_SET_BAUD,
+ 0, port->port_number,
+ buf, 4);
+ if (err)
+ goto out;
+
+ dev_dbg(&port->dev, "baud_rate : %d\n", baud);
+ dev_dbg(&port->dev, "data_bits : %d\n", data_bits);
+ dev_dbg(&port->dev, "parity : %d\n", parity);
+ dev_dbg(&port->dev, "stop_bits : %d\n", stop_bits);
+
+out:
+ kfree(buf);
+}
+
+/*
+ * Determine how many ports this device has dynamically. It will be
+ * called after the probe() callback is called, but before attach().
+ */
+static int mxuport_calc_num_ports(struct usb_serial *serial)
+{
+ unsigned long features = (unsigned long)usb_get_serial_data(serial);
+
+ if (features & MX_UPORT_2_PORT)
+ return 2;
+ if (features & MX_UPORT_4_PORT)
+ return 4;
+ if (features & MX_UPORT_8_PORT)
+ return 8;
+ if (features & MX_UPORT_16_PORT)
+ return 16;
+
+ return 0;
+}
+
+/* Get the version of the firmware currently running. */
+static int mxuport_get_fw_version(struct usb_serial *serial, u32 *version)
+{
+ u8 *ver_buf;
+ int err;
+
+ ver_buf = kzalloc(4, GFP_KERNEL);
+ if (!ver_buf)
+ return -ENOMEM;
+
+ /* Get firmware version from SDRAM */
+ err = mxuport_recv_ctrl_urb(serial, RQ_VENDOR_GET_VERSION, 0, 0,
+ ver_buf, 4);
+ if (err != 4) {
+ err = -EIO;
+ goto out;
+ }
+
+ *version = (ver_buf[0] << 16) | (ver_buf[1] << 8) | ver_buf[2];
+ err = 0;
+out:
+ kfree(ver_buf);
+ return err;
+}
+
+/* Given a firmware blob, download it to the device. */
+static int mxuport_download_fw(struct usb_serial *serial,
+ const struct firmware *fw_p)
+{
+ u8 *fw_buf;
+ size_t txlen;
+ size_t fwidx;
+ int err;
+
+ fw_buf = kmalloc(DOWN_BLOCK_SIZE, GFP_KERNEL);
+ if (!fw_buf)
+ return -ENOMEM;
+
+ dev_dbg(&serial->interface->dev, "Starting firmware download...\n");
+ err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_START_FW_DOWN, 0, 0);
+ if (err)
+ goto out;
+
+ fwidx = 0;
+ do {
+ txlen = min_t(size_t, (fw_p->size - fwidx), DOWN_BLOCK_SIZE);
+
+ memcpy(fw_buf, &fw_p->data[fwidx], txlen);
+ err = mxuport_send_ctrl_data_urb(serial, RQ_VENDOR_FW_DATA,
+ 0, 0, fw_buf, txlen);
+ if (err) {
+ mxuport_send_ctrl_urb(serial, RQ_VENDOR_STOP_FW_DOWN,
+ 0, 0);
+ goto out;
+ }
+
+ fwidx += txlen;
+ usleep_range(1000, 2000);
+
+ } while (fwidx < fw_p->size);
+
+ msleep(1000);
+ err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_STOP_FW_DOWN, 0, 0);
+ if (err)
+ goto out;
+
+ msleep(1000);
+ err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_QUERY_FW_READY, 0, 0);
+
+out:
+ kfree(fw_buf);
+ return err;
+}
+
+static int mxuport_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
+{
+ u16 productid = le16_to_cpu(serial->dev->descriptor.idProduct);
+ const struct firmware *fw_p = NULL;
+ u32 version;
+ int local_ver;
+ char buf[32];
+ int err;
+
+ /* Load our firmware */
+ err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_QUERY_FW_CONFIG, 0, 0);
+ if (err) {
+ mxuport_send_ctrl_urb(serial, RQ_VENDOR_RESET_DEVICE, 0, 0);
+ return err;
+ }
+
+ err = mxuport_get_fw_version(serial, &version);
+ if (err < 0)
+ return err;
+
+ dev_dbg(&serial->interface->dev, "Device firmware version v%x.%x.%x\n",
+ (version & 0xff0000) >> 16,
+ (version & 0xff00) >> 8,
+ (version & 0xff));
+
+ snprintf(buf, sizeof(buf) - 1, "moxa/moxa-%04x.fw", productid);
+
+ err = request_firmware(&fw_p, buf, &serial->interface->dev);
+ if (err) {
+ dev_warn(&serial->interface->dev, "Firmware %s not found\n",
+ buf);
+
+ /* Use the firmware already in the device */
+ err = 0;
+ } else {
+ local_ver = ((fw_p->data[VER_ADDR_1] << 16) |
+ (fw_p->data[VER_ADDR_2] << 8) |
+ fw_p->data[VER_ADDR_3]);
+ dev_dbg(&serial->interface->dev,
+ "Available firmware version v%x.%x.%x\n",
+ fw_p->data[VER_ADDR_1], fw_p->data[VER_ADDR_2],
+ fw_p->data[VER_ADDR_3]);
+ if (local_ver > version) {
+ err = mxuport_download_fw(serial, fw_p);
+ if (err)
+ goto out;
+ err = mxuport_get_fw_version(serial, &version);
+ if (err < 0)
+ goto out;
+ }
+ }
+
+ dev_info(&serial->interface->dev,
+ "Using device firmware version v%x.%x.%x\n",
+ (version & 0xff0000) >> 16,
+ (version & 0xff00) >> 8,
+ (version & 0xff));
+
+ /*
+ * Contains the features of this hardware. Store away for
+ * later use, eg, number of ports.
+ */
+ usb_set_serial_data(serial, (void *)id->driver_info);
+out:
+ if (fw_p)
+ release_firmware(fw_p);
+ return err;
+}
+
+
+static int mxuport_port_probe(struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+ struct mxuport_port *mxport;
+ int err;
+
+ mxport = devm_kzalloc(&port->dev, sizeof(struct mxuport_port),
+ GFP_KERNEL);
+ if (!mxport)
+ return -ENOMEM;
+
+ mutex_init(&mxport->mutex);
+ spin_lock_init(&mxport->spinlock);
+
+ /* Set the port private data */
+ usb_set_serial_port_data(port, mxport);
+
+ /* Set FIFO (Enable) */
+ err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_FIFO_DISABLE,
+ 0, port->port_number);
+ if (err)
+ return err;
+
+ /* Set transmission mode (Hi-Performance) */
+ err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_HIGH_PERFOR,
+ 0, port->port_number);
+ if (err)
+ return err;
+
+ /* Set interface (RS-232) */
+ err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_INTERFACE,
+ MX_INT_RS232,
+ port->port_number);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int mxuport_alloc_write_urb(struct usb_serial *serial,
+ struct usb_serial_port *port,
+ struct usb_serial_port *port0,
+ int j)
+{
+ struct usb_device *dev = interface_to_usbdev(serial->interface);
+
+ set_bit(j, &port->write_urbs_free);
+ port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
+ if (!port->write_urbs[j])
+ return -ENOMEM;
+
+ port->bulk_out_buffers[j] = kmalloc(port0->bulk_out_size, GFP_KERNEL);
+ if (!port->bulk_out_buffers[j])
+ return -ENOMEM;
+
+ usb_fill_bulk_urb(port->write_urbs[j], dev,
+ usb_sndbulkpipe(dev, port->bulk_out_endpointAddress),
+ port->bulk_out_buffers[j],
+ port->bulk_out_size,
+ serial->type->write_bulk_callback,
+ port);
+ return 0;
+}
+
+
+static int mxuport_alloc_write_urbs(struct usb_serial *serial,
+ struct usb_serial_port *port,
+ struct usb_serial_port *port0)
+{
+ int j;
+ int ret;
+
+ for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
+ ret = mxuport_alloc_write_urb(serial, port, port0, j);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+
+static int mxuport_attach(struct usb_serial *serial)
+{
+ struct usb_serial_port *port0 = serial->port[0];
+ struct usb_serial_port *port1 = serial->port[1];
+ struct usb_serial_port *port;
+ int err;
+ int i;
+ int j;
+
+ /*
+ * Throw away all but the first allocated write URBs so we can
+ * set them up again to fit the multiplexing scheme.
+ */
+ for (i = 1; i < serial->num_bulk_out; ++i) {
+ port = serial->port[i];
+ for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
+ usb_free_urb(port->write_urbs[j]);
+ kfree(port->bulk_out_buffers[j]);
+ port->write_urbs[j] = NULL;
+ port->bulk_out_buffers[j] = NULL;
+ }
+ port->write_urbs_free = 0;
+ }
+
+ /*
+ * All write data is sent over the first bulk out endpoint,
+ * with an added header to indicate the port. Allocate URBs
+ * for each port to the first bulk out endpoint.
+ */
+ for (i = 1; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ port->bulk_out_size = port0->bulk_out_size;
+ port->bulk_out_endpointAddress =
+ port0->bulk_out_endpointAddress;
+
+ err = mxuport_alloc_write_urbs(serial, port, port0);
+ if (err)
+ return err;
+
+ port->write_urb = port->write_urbs[0];
+ port->bulk_out_buffer = port->bulk_out_buffers[0];
+
+ /*
+ * Ensure each port has a fifo. The framework only
+ * allocates a fifo to ports with a bulk out endpoint,
+ * where as we need one for every port.
+ */
+ if (!kfifo_initialized(&port->write_fifo)) {
+ err = kfifo_alloc(&port->write_fifo, PAGE_SIZE,
+ GFP_KERNEL);
+ if (err)
+ return err;
+ }
+ }
+
+ /*
+ * All data from the ports is received on the first bulk in
+ * endpoint, with a multiplex header. The second bulk in is
+ * used for events.
+ *
+ * Start to read from the device.
+ */
+ err = usb_serial_generic_submit_read_urbs(port0, GFP_KERNEL);
+ if (err)
+ return err;
+
+ err = usb_serial_generic_submit_read_urbs(port1, GFP_KERNEL);
+ if (err) {
+ usb_serial_generic_close(port0);
+ return err;
+ }
+
+ return 0;
+}
+
+static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port)
+{
+ struct mxuport_port *mxport = usb_get_serial_port_data(port);
+ struct usb_serial *serial = port->serial;
+ int err;
+
+ /* Set receive host (enable) */
+ err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_RX_HOST_EN,
+ 1, port->port_number);
+ if (err)
+ return err;
+
+ err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_OPEN,
+ 1, port->port_number);
+ if (err) {
+ mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_RX_HOST_EN,
+ 0, port->port_number);
+ return err;
+ }
+
+ /* Initial port termios */
+ mxuport_set_termios(tty, port, NULL);
+
+ /*
+ * TODO: use RQ_VENDOR_GET_MSR, once we know what it
+ * returns.
+ */
+ mxport->msr_state = 0;
+
+ return err;
+}
+
+static void mxuport_close(struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+
+ mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_OPEN, 0,
+ port->port_number);
+
+ mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_RX_HOST_EN, 0,
+ port->port_number);
+}
+
+/* Send a break to the port. */
+static void mxuport_break_ctl(struct tty_struct *tty, int break_state)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct usb_serial *serial = port->serial;
+ int enable;
+
+ if (break_state == -1) {
+ enable = 1;
+ dev_dbg(&port->dev, "%s - sending break\n", __func__);
+ } else {
+ enable = 0;
+ dev_dbg(&port->dev, "%s - clearing break\n", __func__);
+ }
+
+ mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_BREAK,
+ enable, port->port_number);
+}
+
+static int mxuport_resume(struct usb_serial *serial)
+{
+ struct usb_serial_port *port;
+ int c = 0;
+ int i;
+ int r;
+
+ for (i = 0; i < 2; i++) {
+ port = serial->port[i];
+
+ r = usb_serial_generic_submit_read_urbs(port, GFP_NOIO);
+ if (r < 0)
+ c++;
+ }
+
+ for (i = 0; i < serial->num_ports; i++) {
+ port = serial->port[i];
+ if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+ continue;
+
+ r = usb_serial_generic_write_start(port, GFP_NOIO);
+ if (r < 0)
+ c++;
+ }
+
+ return c ? -EIO : 0;
+}
+
+static struct usb_serial_driver mxuport_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "mxuport",
+ },
+ .description = "MOXA UPort",
+ .id_table = mxuport_idtable,
+ .num_ports = 0,
+ .probe = mxuport_probe,
+ .port_probe = mxuport_port_probe,
+ .attach = mxuport_attach,
+ .calc_num_ports = mxuport_calc_num_ports,
+ .open = mxuport_open,
+ .close = mxuport_close,
+ .set_termios = mxuport_set_termios,
+ .break_ctl = mxuport_break_ctl,
+ .tx_empty = mxuport_tx_empty,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
+ .throttle = mxuport_throttle,
+ .unthrottle = mxuport_unthrottle,
+ .tiocmget = mxuport_tiocmget,
+ .tiocmset = mxuport_tiocmset,
+ .dtr_rts = mxuport_dtr_rts,
+ .process_read_urb = mxuport_process_read_urb,
+ .prepare_write_buffer = mxuport_prepare_write_buffer,
+ .resume = mxuport_resume,
+};
+
+static struct usb_serial_driver *const serial_drivers[] = {
+ &mxuport_device, NULL
+};
+
+module_usb_serial_driver(serial_drivers, mxuport_idtable);
+
+MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
+MODULE_AUTHOR("<support@moxa.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 1f00f243c26..2a97cdc078d 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -14,15 +14,12 @@
#include <linux/gfp.h>
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-static int debug;
-
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x0a99, 0x0001) }, /* Talon Technology device */
{ USB_DEVICE(0x0df7, 0x0900) }, /* Mobile Action i-gotU */
@@ -30,19 +27,10 @@ static const struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver navman_driver = {
- .name = "navman",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
static void navman_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
- struct tty_struct *tty;
int status = urb->status;
int result;
@@ -54,24 +42,21 @@ static void navman_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
goto exit;
}
- usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, data);
+ usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
- tty = tty_port_tty_get(&port->port);
- if (tty && urb->actual_length) {
- tty_insert_flip_string(tty, data, urb->actual_length);
- tty_flip_buffer_push(tty);
+ if (urb->actual_length) {
+ tty_insert_flip_string(&port->port, data, urb->actual_length);
+ tty_flip_buffer_push(&port->port);
}
- tty_kref_put(tty);
exit:
result = usb_submit_urb(urb, GFP_ATOMIC);
@@ -85,10 +70,9 @@ static int navman_open(struct tty_struct *tty, struct usb_serial_port *port)
{
int result = 0;
- dbg("%s - port %d", __func__, port->number);
-
if (port->interrupt_in_urb) {
- dbg("%s - adding interrupt input for treo", __func__);
+ dev_dbg(&port->dev, "%s - adding interrupt input for treo\n",
+ __func__);
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result)
dev_err(&port->dev,
@@ -100,16 +84,12 @@ static int navman_open(struct tty_struct *tty, struct usb_serial_port *port)
static void navman_close(struct usb_serial_port *port)
{
- dbg("%s - port %d", __func__, port->number);
-
usb_kill_urb(port->interrupt_in_urb);
}
static int navman_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
- dbg("%s - port %d", __func__, port->number);
-
/*
* This device can't write any data, only read from the device
*/
@@ -122,7 +102,6 @@ static struct usb_serial_driver navman_device = {
.name = "navman",
},
.id_table = id_table,
- .usb_driver = &navman_driver,
.num_ports = 1,
.open = navman_open,
.close = navman_close,
@@ -130,28 +109,10 @@ static struct usb_serial_driver navman_device = {
.read_int_callback = navman_read_int_callback,
};
-static int __init navman_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&navman_device);
- if (retval)
- return retval;
- retval = usb_register(&navman_driver);
- if (retval)
- usb_serial_deregister(&navman_device);
- return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &navman_device, NULL
+};
-static void __exit navman_exit(void)
-{
- usb_deregister(&navman_driver);
- usb_serial_deregister(&navman_device);
-}
+module_usb_serial_driver(serial_drivers, id_table);
-module_init(navman_init);
-module_exit(navman_exit);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 60f38d5e64f..f6c6900bccf 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -9,52 +9,19 @@
* driver
*
* Please report both successes and troubles to the author at omninet@kroah.com
- *
- * (05/30/2001) gkh
- * switched from using spinlock to a semaphore, which fixes lots of
- * problems.
- *
- * (04/08/2001) gb
- * Identify version on module load.
- *
- * (11/01/2000) Adam J. Richter
- * usb_device_id table support
- *
- * (10/05/2000) gkh
- * Fixed bug with urb->dev not being set properly, now that the usb
- * core needs it.
- *
- * (08/28/2000) gkh
- * Added locks for SMP safeness.
- * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
- * than once.
- * Fixed potential race in omninet_write_bulk_callback
- *
- * (07/19/2000) gkh
- * Added module_init and module_exit functions to handle the fact that this
- * driver is a loadable module now.
- *
*/
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.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/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-static int debug;
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.1"
#define DRIVER_AUTHOR "Alessandro Zummo"
#define DRIVER_DESC "USB ZyXEL omni.net LCD PLUS Driver"
@@ -65,77 +32,67 @@ static int debug;
/* function prototypes */
static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port);
-static void omninet_close(struct usb_serial_port *port);
-static void omninet_read_bulk_callback(struct urb *urb);
+static void omninet_process_read_urb(struct urb *urb);
static void omninet_write_bulk_callback(struct urb *urb);
static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static int omninet_write_room(struct tty_struct *tty);
static void omninet_disconnect(struct usb_serial *serial);
-static void omninet_release(struct usb_serial *serial);
-static int omninet_attach(struct usb_serial *serial);
+static int omninet_port_probe(struct usb_serial_port *port);
+static int omninet_port_remove(struct usb_serial_port *port);
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
{ USB_DEVICE(ZYXEL_VENDOR_ID, BT_IGNITIONPRO_ID) },
{ } /* Terminating entry */
};
-
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver omninet_driver = {
- .name = "omninet",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
-
static struct usb_serial_driver zyxel_omninet_device = {
.driver = {
.owner = THIS_MODULE,
.name = "omninet",
},
.description = "ZyXEL - omni.net lcd plus usb",
- .usb_driver = &omninet_driver,
.id_table = id_table,
.num_ports = 1,
- .attach = omninet_attach,
+ .port_probe = omninet_port_probe,
+ .port_remove = omninet_port_remove,
.open = omninet_open,
- .close = omninet_close,
.write = omninet_write,
.write_room = omninet_write_room,
- .read_bulk_callback = omninet_read_bulk_callback,
.write_bulk_callback = omninet_write_bulk_callback,
+ .process_read_urb = omninet_process_read_urb,
.disconnect = omninet_disconnect,
- .release = omninet_release,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+ &zyxel_omninet_device, NULL
};
-/* The protocol.
+/*
+ * The protocol.
*
* The omni.net always exchange 64 bytes of data with the host. The first
- * four bytes are the control header, you can see it in the above structure.
+ * four bytes are the control header.
*
* oh_seq is a sequence number. Don't know if/how it's used.
* oh_len is the length of the data bytes in the packet.
* oh_xxx Bit-mapped, related to handshaking and status info.
- * I normally set it to 0x03 in trasmitted frames.
+ * I normally set it to 0x03 in transmitted frames.
* 7: Active when the TA is in a CONNECTed state.
* 6: unknown
* 5: handshaking, unknown
* 4: handshaking, unknown
* 3: unknown, usually 0
* 2: unknown, usually 0
- * 1: handshaking, unknown, usually set to 1 in trasmitted frames
- * 0: handshaking, unknown, usually set to 1 in trasmitted frames
+ * 1: handshaking, unknown, usually set to 1 in transmitted frames
+ * 0: handshaking, unknown, usually set to 1 in transmitted frames
* oh_pad Probably a pad byte.
*
* After the header you will find data bytes if oh_len was greater than zero.
- *
*/
-
struct omninet_header {
__u8 oh_seq;
__u8 oh_len;
@@ -147,18 +104,26 @@ struct omninet_data {
__u8 od_outseq; /* Sequence number for bulk_out URBs */
};
-static int omninet_attach(struct usb_serial *serial)
+static int omninet_port_probe(struct usb_serial_port *port)
{
struct omninet_data *od;
- struct usb_serial_port *port = serial->port[0];
- od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL);
- if (!od) {
- dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n",
- __func__, sizeof(struct omninet_data));
+ od = kzalloc(sizeof(*od), GFP_KERNEL);
+ if (!od)
return -ENOMEM;
- }
+
usb_set_serial_port_data(port, od);
+
+ return 0;
+}
+
+static int omninet_port_remove(struct usb_serial_port *port)
+{
+ struct omninet_data *od;
+
+ od = usb_get_serial_port_data(port);
+ kfree(od);
+
return 0;
}
@@ -166,86 +131,32 @@ static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct usb_serial_port *wport;
- int result = 0;
-
- dbg("%s - port %d", __func__, port->number);
wport = serial->port[1];
tty_port_tty_set(&wport->port, tty);
- /* Start reading from the device */
- usb_fill_bulk_urb(port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev,
- port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer,
- port->read_urb->transfer_buffer_length,
- omninet_read_bulk_callback, port);
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
- if (result)
- dev_err(&port->dev,
- "%s - failed submitting read urb, error %d\n",
- __func__, result);
- return result;
-}
-
-static void omninet_close(struct usb_serial_port *port)
-{
- dbg("%s - port %d", __func__, port->number);
- usb_kill_urb(port->read_urb);
+ return usb_serial_generic_open(tty, port);
}
+#define OMNINET_HEADERLEN 4
+#define OMNINET_BULKOUTSIZE 64
+#define OMNINET_PAYLOADSIZE (OMNINET_BULKOUTSIZE - OMNINET_HEADERLEN)
-#define OMNINET_DATAOFFSET 0x04
-#define OMNINET_HEADERLEN sizeof(struct omninet_header)
-#define OMNINET_BULKOUTSIZE (64 - OMNINET_HEADERLEN)
-
-static void omninet_read_bulk_callback(struct urb *urb)
+static void omninet_process_read_urb(struct urb *urb)
{
- struct usb_serial_port *port = urb->context;
- unsigned char *data = urb->transfer_buffer;
- struct omninet_header *header = (struct omninet_header *) &data[0];
- int status = urb->status;
- int result;
- int i;
+ struct usb_serial_port *port = urb->context;
+ const struct omninet_header *hdr = urb->transfer_buffer;
+ const unsigned char *data;
+ size_t data_len;
- dbg("%s - port %d", __func__, port->number);
-
- if (status) {
- dbg("%s - nonzero read bulk status received: %d",
- __func__, status);
+ if (urb->actual_length <= OMNINET_HEADERLEN || !hdr->oh_len)
return;
- }
-
- if (debug && header->oh_xxx != 0x30) {
- if (urb->actual_length) {
- printk(KERN_DEBUG "%s: omninet_read %d: ",
- __FILE__, header->oh_len);
- for (i = 0; i < (header->oh_len +
- OMNINET_HEADERLEN); i++)
- printk("%.2x ", data[i]);
- printk("\n");
- }
- }
-
- if (urb->actual_length && header->oh_len) {
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- tty_insert_flip_string(tty, data + OMNINET_DATAOFFSET,
- header->oh_len);
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
- }
- /* Continue trying to always read */
- usb_fill_bulk_urb(urb, port->serial->dev,
- usb_rcvbulkpipe(port->serial->dev,
- port->bulk_in_endpointAddress),
- urb->transfer_buffer, urb->transfer_buffer_length,
- omninet_read_bulk_callback, port);
- result = usb_submit_urb(urb, GFP_ATOMIC);
- if (result)
- dev_err(&port->dev,
- "%s - failed resubmitting read urb, error %d\n",
- __func__, result);
+ data = (char *)urb->transfer_buffer + OMNINET_HEADERLEN;
+ data_len = min_t(size_t, urb->actual_length - OMNINET_HEADERLEN,
+ hdr->oh_len);
+ tty_insert_flip_string(&port->port, data, data_len);
+ tty_flip_buffer_push(&port->port);
}
static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -260,29 +171,23 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
int result;
- dbg("%s - port %d", __func__, port->number);
-
if (count == 0) {
- dbg("%s - write request of 0 bytes", __func__);
+ dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__);
return 0;
}
- spin_lock_bh(&wport->lock);
- if (wport->write_urb_busy) {
- spin_unlock_bh(&wport->lock);
- dbg("%s - already writing", __func__);
+ if (!test_and_clear_bit(0, &port->write_urbs_free)) {
+ dev_dbg(&port->dev, "%s - already writing\n", __func__);
return 0;
}
- wport->write_urb_busy = 1;
- spin_unlock_bh(&wport->lock);
- count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;
+ count = (count > OMNINET_PAYLOADSIZE) ? OMNINET_PAYLOADSIZE : count;
- memcpy(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET,
+ memcpy(wport->write_urb->transfer_buffer + OMNINET_HEADERLEN,
buf, count);
- usb_serial_debug_data(debug, &port->dev, __func__, count,
- wport->write_urb->transfer_buffer);
+ usb_serial_debug_data(&port->dev, __func__, count,
+ wport->write_urb->transfer_buffer);
header->oh_seq = od->od_outseq++;
header->oh_len = count;
@@ -290,13 +195,12 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
header->oh_pad = 0x00;
/* send the data out the bulk port, always 64 bytes */
- wport->write_urb->transfer_buffer_length = 64;
+ wport->write_urb->transfer_buffer_length = OMNINET_BULKOUTSIZE;
- wport->write_urb->dev = serial->dev;
result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
if (result) {
- wport->write_urb_busy = 0;
- dev_err(&port->dev,
+ set_bit(0, &wport->write_urbs_free);
+ dev_err_console(port,
"%s - failed submitting write urb, error %d\n",
__func__, result);
} else
@@ -314,11 +218,10 @@ static int omninet_write_room(struct tty_struct *tty)
int room = 0; /* Default: no room */
- /* FIXME: no consistent locking for write_urb_busy */
- if (wport->write_urb_busy)
+ if (test_bit(0, &wport->write_urbs_free))
room = wport->bulk_out_size - OMNINET_HEADERLEN;
- dbg("%s - returns %d", __func__, room);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, room);
return room;
}
@@ -330,12 +233,10 @@ static void omninet_write_bulk_callback(struct urb *urb)
struct usb_serial_port *port = urb->context;
int status = urb->status;
- dbg("%s - port %0x", __func__, port->number);
-
- port->write_urb_busy = 0;
+ set_bit(0, &port->write_urbs_free);
if (status) {
- dbg("%s - nonzero write bulk status received: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - nonzero write bulk status received: %d\n",
+ __func__, status);
return;
}
@@ -347,54 +248,11 @@ static void omninet_disconnect(struct usb_serial *serial)
{
struct usb_serial_port *wport = serial->port[1];
- dbg("%s", __func__);
-
usb_kill_urb(wport->write_urb);
}
-
-static void omninet_release(struct usb_serial *serial)
-{
- struct usb_serial_port *port = serial->port[0];
-
- dbg("%s", __func__);
-
- kfree(usb_get_serial_port_data(port));
-}
-
-
-static int __init omninet_init(void)
-{
- int retval;
- retval = usb_serial_register(&zyxel_omninet_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&omninet_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&zyxel_omninet_device);
-failed_usb_serial_register:
- return retval;
-}
-
-
-static void __exit omninet_exit(void)
-{
- usb_deregister(&omninet_driver);
- usb_serial_deregister(&zyxel_omninet_device);
-}
-
-
-module_init(omninet_init);
-module_exit(omninet_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index eda1f9266c4..4856fb7e637 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -1,6 +1,8 @@
/*
* Opticon USB barcode to serial driver
*
+ * Copyright (C) 2011 - 2012 Johan Hovold <jhovold@gmail.com>
+ * Copyright (C) 2011 Martin Jansen <martin.jansen@opticon.com>
* Copyright (C) 2008 - 2009 Greg Kroah-Hartman <gregkh@suse.de>
* Copyright (C) 2008 - 2009 Novell Inc.
*
@@ -10,7 +12,6 @@
*/
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/slab.h>
@@ -21,7 +22,15 @@
#include <linux/usb/serial.h>
#include <linux/uaccess.h>
-static int debug;
+#define CONTROL_RTS 0x02
+#define RESEND_CTS_STATE 0x03
+
+/* max number of write urbs in flight */
+#define URB_UPPER_LIMIT 8
+
+/* This driver works for the Opticon 1D barcode reader
+ * an examples of 1D barcode types are EAN, UPC, Code39, IATA etc.. */
+#define DRIVER_DESC "Opticon USB barcode to serial driver (1D)"
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x065a, 0x0009) },
@@ -31,156 +40,122 @@ MODULE_DEVICE_TABLE(usb, id_table);
/* This structure holds all of the individual device information */
struct opticon_private {
- struct usb_device *udev;
- struct usb_serial *serial;
- struct usb_serial_port *port;
- unsigned char *bulk_in_buffer;
- struct urb *bulk_read_urb;
- int buffer_size;
- u8 bulk_address;
spinlock_t lock; /* protects the following flags */
- bool throttled;
- bool actually_throttled;
bool rts;
+ bool cts;
int outstanding_urbs;
};
-/* max number of write urbs in flight */
-#define URB_UPPER_LIMIT 4
-static void opticon_bulk_callback(struct urb *urb)
+static void opticon_process_data_packet(struct usb_serial_port *port,
+ const unsigned char *buf, size_t len)
{
- struct opticon_private *priv = urb->context;
- unsigned char *data = urb->transfer_buffer;
- struct usb_serial_port *port = priv->port;
- int status = urb->status;
- struct tty_struct *tty;
- int result;
- int data_length;
-
- dbg("%s - port %d", __func__, port->number);
-
- switch (status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ tty_insert_flip_string(&port->port, buf, len);
+ tty_flip_buffer_push(&port->port);
+}
+
+static void opticon_process_status_packet(struct usb_serial_port *port,
+ const unsigned char *buf, size_t len)
+{
+ struct opticon_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (buf[0] == 0x00)
+ priv->cts = false;
+ else
+ priv->cts = true;
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void opticon_process_read_urb(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+ const unsigned char *hdr = urb->transfer_buffer;
+ const unsigned char *data = hdr + 2;
+ size_t data_len = urb->actual_length - 2;
+
+ if (urb->actual_length <= 2) {
+ dev_dbg(&port->dev, "malformed packet received: %d bytes\n",
+ urb->actual_length);
return;
- default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
- goto exit;
}
-
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length,
- data);
-
- if (urb->actual_length > 2) {
- data_length = urb->actual_length - 2;
-
- /*
- * Data from the device comes with a 2 byte header:
- *
- * <0x00><0x00>data...
- * This is real data to be sent to the tty layer
- * <0x00><0x01)level
- * This is a RTS level change, the third byte is the RTS
- * value (0 for low, 1 for high).
- */
- if ((data[0] == 0x00) && (data[1] == 0x00)) {
- /* real data, send it to the tty layer */
- tty = tty_port_tty_get(&port->port);
- if (tty) {
- tty_insert_flip_string(tty, data + 2,
- data_length);
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
- }
- } else {
- if ((data[0] == 0x00) && (data[1] == 0x01)) {
- if (data[2] == 0x00)
- priv->rts = false;
- else
- priv->rts = true;
- } else {
- dev_dbg(&priv->udev->dev,
- "Unknown data packet received from the device:"
- " %2x %2x\n",
- data[0], data[1]);
- }
- }
+ /*
+ * Data from the device comes with a 2 byte header:
+ *
+ * <0x00><0x00>data...
+ * This is real data to be sent to the tty layer
+ * <0x00><0x01>level
+ * This is a CTS level change, the third byte is the CTS
+ * value (0 for low, 1 for high).
+ */
+ if ((hdr[0] == 0x00) && (hdr[1] == 0x00)) {
+ opticon_process_data_packet(port, data, data_len);
+ } else if ((hdr[0] == 0x00) && (hdr[1] == 0x01)) {
+ opticon_process_status_packet(port, data, data_len);
} else {
- dev_dbg(&priv->udev->dev,
- "Improper amount of data received from the device, "
- "%d bytes", urb->actual_length);
+ dev_dbg(&port->dev, "unknown packet received: %02x %02x\n",
+ hdr[0], hdr[1]);
}
+}
+
+static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
+ u8 val)
+{
+ struct usb_serial *serial = port->serial;
+ int retval;
+ u8 *buffer;
+
+ buffer = kzalloc(1, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
-exit:
- spin_lock(&priv->lock);
-
- /* Continue trying to always read if we should */
- if (!priv->throttled) {
- usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev,
- usb_rcvbulkpipe(priv->udev,
- priv->bulk_address),
- priv->bulk_in_buffer, priv->buffer_size,
- opticon_bulk_callback, priv);
- result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC);
- if (result)
- dev_err(&port->dev,
- "%s - failed resubmitting read urb, error %d\n",
- __func__, result);
- } else
- priv->actually_throttled = true;
- spin_unlock(&priv->lock);
+ buffer[0] = val;
+ /* Send the message to the vendor control endpoint
+ * of the connected device */
+ retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ requesttype,
+ USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
+ 0, 0, buffer, 1, 0);
+ kfree(buffer);
+
+ if (retval < 0)
+ return retval;
+
+ return 0;
}
static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port)
{
- struct opticon_private *priv = usb_get_serial_data(port->serial);
+ struct opticon_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- int result = 0;
-
- dbg("%s - port %d", __func__, port->number);
+ int res;
spin_lock_irqsave(&priv->lock, flags);
- priv->throttled = false;
- priv->actually_throttled = false;
- priv->port = port;
+ priv->rts = false;
spin_unlock_irqrestore(&priv->lock, flags);
- /* Start reading from the device */
- usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev,
- usb_rcvbulkpipe(priv->udev,
- priv->bulk_address),
- priv->bulk_in_buffer, priv->buffer_size,
- opticon_bulk_callback, priv);
- result = usb_submit_urb(priv->bulk_read_urb, GFP_KERNEL);
- if (result)
- dev_err(&port->dev,
- "%s - failed resubmitting read urb, error %d\n",
- __func__, result);
- return result;
-}
+ /* Clear RTS line */
+ send_control_msg(port, CONTROL_RTS, 0);
-static void opticon_close(struct usb_serial_port *port)
-{
- struct opticon_private *priv = usb_get_serial_data(port->serial);
+ /* clear the halt status of the endpoint */
+ usb_clear_halt(port->serial->dev, port->read_urb->pipe);
+
+ res = usb_serial_generic_open(tty, port);
+ if (!res)
+ return res;
- dbg("%s - port %d", __func__, port->number);
+ /* Request CTS line state, sometimes during opening the current
+ * CTS state can be missed. */
+ send_control_msg(port, RESEND_CTS_STATE, 1);
- /* shutdown our urbs */
- usb_kill_urb(priv->bulk_read_urb);
+ return res;
}
-static void opticon_write_bulk_callback(struct urb *urb)
+static void opticon_write_control_callback(struct urb *urb)
{
- struct opticon_private *priv = urb->context;
+ struct usb_serial_port *port = urb->context;
+ struct opticon_private *priv = usb_get_serial_port_data(port);
int status = urb->status;
unsigned long flags;
@@ -191,32 +166,32 @@ static void opticon_write_bulk_callback(struct urb *urb)
kfree(urb->setup_packet);
if (status)
- dbg("%s - nonzero write bulk status received: %d",
- __func__, status);
+ dev_dbg(&port->dev,
+ "%s - non-zero urb status received: %d\n",
+ __func__, status);
spin_lock_irqsave(&priv->lock, flags);
--priv->outstanding_urbs;
spin_unlock_irqrestore(&priv->lock, flags);
- usb_serial_port_softint(priv->port);
+ usb_serial_port_softint(port);
}
static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
- struct opticon_private *priv = usb_get_serial_data(port->serial);
+ struct opticon_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", __func__, port->number);
+ struct usb_ctrlrequest *dr;
spin_lock_irqsave(&priv->lock, flags);
if (priv->outstanding_urbs > URB_UPPER_LIMIT) {
spin_unlock_irqrestore(&priv->lock, flags);
- dbg("%s - write limit hit", __func__);
+ dev_dbg(&port->dev, "%s - write limit hit\n", __func__);
return 0;
}
priv->outstanding_urbs++;
@@ -224,51 +199,44 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
buffer = kmalloc(count, GFP_ATOMIC);
if (!buffer) {
- dev_err(&port->dev, "out of memory\n");
count = -ENOMEM;
goto error_no_buffer;
}
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
- dev_err(&port->dev, "no more free urbs\n");
count = -ENOMEM;
goto error_no_urb;
}
memcpy(buffer, buf, count);
- usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+ usb_serial_debug_data(&port->dev, __func__, count, buffer);
- if (port->bulk_out_endpointAddress) {
- usb_fill_bulk_urb(urb, serial->dev,
- usb_sndbulkpipe(serial->dev,
- port->bulk_out_endpointAddress),
- buffer, count, opticon_write_bulk_callback, priv);
- } else {
- struct usb_ctrlrequest *dr;
-
- dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
- if (!dr)
- return -ENOMEM;
-
- dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
- dr->bRequest = 0x01;
- dr->wValue = 0;
- dr->wIndex = 0;
- dr->wLength = cpu_to_le16(count);
-
- usb_fill_control_urb(urb, serial->dev,
- usb_sndctrlpipe(serial->dev, 0),
- (unsigned char *)dr, buffer, count,
- opticon_write_bulk_callback, priv);
+ /* The connected devices do not have a bulk write endpoint,
+ * to transmit data to de barcode device the control endpoint is used */
+ dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
+ if (!dr) {
+ count = -ENOMEM;
+ goto error_no_dr;
}
+ dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
+ dr->bRequest = 0x01;
+ dr->wValue = 0;
+ dr->wIndex = 0;
+ dr->wLength = cpu_to_le16(count);
+
+ usb_fill_control_urb(urb, serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ (unsigned char *)dr, buffer, count,
+ opticon_write_control_callback, port);
+
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
dev_err(&port->dev,
- "%s - usb_submit_urb(write bulk) failed with status = %d\n",
+ "%s - usb_submit_urb(write endpoint) failed status = %d\n",
__func__, status);
count = status;
goto error;
@@ -280,6 +248,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
return count;
error:
+ kfree(dr);
+error_no_dr:
usb_free_urb(urb);
error_no_urb:
kfree(buffer);
@@ -293,11 +263,9 @@ error_no_buffer:
static int opticon_write_room(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- struct opticon_private *priv = usb_get_serial_data(port->serial);
+ struct opticon_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
/*
* We really can take almost anything the user throws at us
* but let's pick a nice big number to tell the tty
@@ -306,7 +274,7 @@ static int opticon_write_room(struct tty_struct *tty)
spin_lock_irqsave(&priv->lock, flags);
if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) {
spin_unlock_irqrestore(&priv->lock, flags);
- dbg("%s - write limit hit", __func__);
+ dev_dbg(&port->dev, "%s - write limit hit\n", __func__);
return 0;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -314,63 +282,56 @@ static int opticon_write_room(struct tty_struct *tty)
return 2048;
}
-static void opticon_throttle(struct tty_struct *tty)
+static int opticon_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- struct opticon_private *priv = usb_get_serial_data(port->serial);
+ struct opticon_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
+ int result = 0;
- dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags);
- priv->throttled = true;
+ if (priv->rts)
+ result |= TIOCM_RTS;
+ if (priv->cts)
+ result |= TIOCM_CTS;
spin_unlock_irqrestore(&priv->lock, flags);
-}
+ dev_dbg(&port->dev, "%s - %x\n", __func__, result);
+ return result;
+}
-static void opticon_unthrottle(struct tty_struct *tty)
+static int opticon_tiocmset(struct tty_struct *tty,
+ unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
- struct opticon_private *priv = usb_get_serial_data(port->serial);
+ struct opticon_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- int result, was_throttled;
-
- dbg("%s - port %d", __func__, port->number);
+ bool rts;
+ bool changed = false;
+ int ret;
+ /* We only support RTS so we only handle that */
spin_lock_irqsave(&priv->lock, flags);
- priv->throttled = false;
- was_throttled = priv->actually_throttled;
- priv->actually_throttled = false;
- spin_unlock_irqrestore(&priv->lock, flags);
- priv->bulk_read_urb->dev = port->serial->dev;
- if (was_throttled) {
- result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC);
- if (result)
- dev_err(&port->dev,
- "%s - failed submitting read urb, error %d\n",
- __func__, result);
- }
-}
-
-static int opticon_tiocmget(struct tty_struct *tty, struct file *file)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct opticon_private *priv = usb_get_serial_data(port->serial);
- unsigned long flags;
- int result = 0;
+ rts = priv->rts;
+ if (set & TIOCM_RTS)
+ priv->rts = true;
+ if (clear & TIOCM_RTS)
+ priv->rts = false;
+ changed = rts ^ priv->rts;
+ spin_unlock_irqrestore(&priv->lock, flags);
- dbg("%s - port %d", __func__, port->number);
+ if (!changed)
+ return 0;
- spin_lock_irqsave(&priv->lock, flags);
- if (priv->rts)
- result = TIOCM_RTS;
- spin_unlock_irqrestore(&priv->lock, flags);
+ ret = send_control_msg(port, CONTROL_RTS, !rts);
+ if (ret)
+ return usb_translate_errors(ret);
- dbg("%s - %x", __func__, result);
- return result;
+ return 0;
}
-static int get_serial_info(struct opticon_private *priv,
+static int get_serial_info(struct usb_serial_port *port,
struct serial_struct __user *serial)
{
struct serial_struct tmp;
@@ -382,7 +343,7 @@ static int get_serial_info(struct opticon_private *priv,
/* fake emulate a 16550 uart to make userspace code happy */
tmp.type = PORT_16550A;
- tmp.line = priv->serial->minor;
+ tmp.line = port->minor;
tmp.port = 0;
tmp.irq = 0;
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
@@ -396,17 +357,14 @@ static int get_serial_info(struct opticon_private *priv,
return 0;
}
-static int opticon_ioctl(struct tty_struct *tty, struct file *file,
+static int opticon_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
- struct opticon_private *priv = usb_get_serial_data(port->serial);
-
- dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
switch (cmd) {
case TIOCGSERIAL:
- return get_serial_info(priv,
+ return get_serial_info(port,
(struct serial_struct __user *)arg);
}
@@ -415,173 +373,65 @@ static int opticon_ioctl(struct tty_struct *tty, struct file *file,
static int opticon_startup(struct usb_serial *serial)
{
- struct opticon_private *priv;
- struct usb_host_interface *intf;
- int i;
- int retval = -ENOMEM;
- bool bulk_in_found = false;
-
- /* create our private serial structure */
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (priv == NULL) {
- dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
- return -ENOMEM;
- }
- spin_lock_init(&priv->lock);
- priv->serial = serial;
- priv->port = serial->port[0];
- priv->udev = serial->dev;
-
- /* find our bulk endpoint */
- intf = serial->interface->altsetting;
- for (i = 0; i < intf->desc.bNumEndpoints; ++i) {
- struct usb_endpoint_descriptor *endpoint;
-
- endpoint = &intf->endpoint[i].desc;
- if (!usb_endpoint_is_bulk_in(endpoint))
- continue;
-
- priv->bulk_read_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!priv->bulk_read_urb) {
- dev_err(&priv->udev->dev, "out of memory\n");
- goto error;
- }
-
- priv->buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2;
- priv->bulk_in_buffer = kmalloc(priv->buffer_size, GFP_KERNEL);
- if (!priv->bulk_in_buffer) {
- dev_err(&priv->udev->dev, "out of memory\n");
- goto error;
- }
-
- priv->bulk_address = endpoint->bEndpointAddress;
-
- /* set up our bulk urb */
- usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev,
- usb_rcvbulkpipe(priv->udev,
- endpoint->bEndpointAddress),
- priv->bulk_in_buffer, priv->buffer_size,
- opticon_bulk_callback, priv);
-
- bulk_in_found = true;
- break;
- }
-
- if (!bulk_in_found) {
- dev_err(&priv->udev->dev,
- "Error - the proper endpoints were not found!\n");
- goto error;
+ if (!serial->num_bulk_in) {
+ dev_err(&serial->dev->dev, "no bulk in endpoint\n");
+ return -ENODEV;
}
- usb_set_serial_data(serial, priv);
return 0;
-
-error:
- usb_free_urb(priv->bulk_read_urb);
- kfree(priv->bulk_in_buffer);
- kfree(priv);
- return retval;
}
-static void opticon_disconnect(struct usb_serial *serial)
+static int opticon_port_probe(struct usb_serial_port *port)
{
- struct opticon_private *priv = usb_get_serial_data(serial);
-
- dbg("%s", __func__);
+ struct opticon_private *priv;
- usb_kill_urb(priv->bulk_read_urb);
- usb_free_urb(priv->bulk_read_urb);
-}
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
-static void opticon_release(struct usb_serial *serial)
-{
- struct opticon_private *priv = usb_get_serial_data(serial);
+ spin_lock_init(&priv->lock);
- dbg("%s", __func__);
+ usb_set_serial_port_data(port, priv);
- kfree(priv->bulk_in_buffer);
- kfree(priv);
+ return 0;
}
-static int opticon_suspend(struct usb_interface *intf, pm_message_t message)
+static int opticon_port_remove(struct usb_serial_port *port)
{
- struct usb_serial *serial = usb_get_intfdata(intf);
- struct opticon_private *priv = usb_get_serial_data(serial);
+ struct opticon_private *priv = usb_get_serial_port_data(port);
- usb_kill_urb(priv->bulk_read_urb);
- return 0;
-}
+ kfree(priv);
-static int opticon_resume(struct usb_interface *intf)
-{
- struct usb_serial *serial = usb_get_intfdata(intf);
- struct opticon_private *priv = usb_get_serial_data(serial);
- struct usb_serial_port *port = serial->port[0];
- int result;
-
- mutex_lock(&port->port.mutex);
- /* This is protected by the port mutex against close/open */
- if (test_bit(ASYNCB_INITIALIZED, &port->port.flags))
- result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO);
- else
- result = 0;
- mutex_unlock(&port->port.mutex);
- return result;
+ return 0;
}
-static struct usb_driver opticon_driver = {
- .name = "opticon",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .suspend = opticon_suspend,
- .resume = opticon_resume,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
static struct usb_serial_driver opticon_device = {
.driver = {
.owner = THIS_MODULE,
.name = "opticon",
},
.id_table = id_table,
- .usb_driver = &opticon_driver,
.num_ports = 1,
+ .bulk_in_size = 256,
.attach = opticon_startup,
+ .port_probe = opticon_port_probe,
+ .port_remove = opticon_port_remove,
.open = opticon_open,
- .close = opticon_close,
.write = opticon_write,
.write_room = opticon_write_room,
- .disconnect = opticon_disconnect,
- .release = opticon_release,
- .throttle = opticon_throttle,
- .unthrottle = opticon_unthrottle,
+ .throttle = usb_serial_generic_throttle,
+ .unthrottle = usb_serial_generic_unthrottle,
.ioctl = opticon_ioctl,
.tiocmget = opticon_tiocmget,
+ .tiocmset = opticon_tiocmset,
+ .process_read_urb = opticon_process_read_urb,
};
-static int __init opticon_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&opticon_device);
- if (retval)
- return retval;
- retval = usb_register(&opticon_driver);
- if (retval)
- usb_serial_deregister(&opticon_device);
- return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &opticon_device, NULL
+};
-static void __exit opticon_exit(void)
-{
- usb_deregister(&opticon_driver);
- usb_serial_deregister(&opticon_device);
-}
+module_usb_serial_driver(serial_drivers, id_table);
-module_init(opticon_init);
-module_exit(opticon_exit);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index ef2977d3a61..a9688940543 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -28,7 +28,6 @@
device features.
*/
-#define DRIVER_VERSION "v0.7.2"
#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
#define DRIVER_DESC "USB Driver for GSM modems"
@@ -47,6 +46,8 @@
/* Function prototypes */
static int option_probe(struct usb_serial *serial,
const struct usb_device_id *id);
+static int option_attach(struct usb_serial *serial);
+static void option_release(struct usb_serial *serial);
static int option_send_setup(struct usb_serial_port *port);
static void option_instat_callback(struct urb *urb);
@@ -79,76 +80,12 @@ static void option_instat_callback(struct urb *urb);
#define OPTION_PRODUCT_GTM380_MODEM 0x7201
#define HUAWEI_VENDOR_ID 0x12D1
-#define HUAWEI_PRODUCT_E600 0x1001
-#define HUAWEI_PRODUCT_E220 0x1003
-#define HUAWEI_PRODUCT_E220BIS 0x1004
-#define HUAWEI_PRODUCT_E1401 0x1401
-#define HUAWEI_PRODUCT_E1402 0x1402
-#define HUAWEI_PRODUCT_E1403 0x1403
-#define HUAWEI_PRODUCT_E1404 0x1404
-#define HUAWEI_PRODUCT_E1405 0x1405
-#define HUAWEI_PRODUCT_E1406 0x1406
-#define HUAWEI_PRODUCT_E1407 0x1407
-#define HUAWEI_PRODUCT_E1408 0x1408
-#define HUAWEI_PRODUCT_E1409 0x1409
-#define HUAWEI_PRODUCT_E140A 0x140A
-#define HUAWEI_PRODUCT_E140B 0x140B
-#define HUAWEI_PRODUCT_E140C 0x140C
-#define HUAWEI_PRODUCT_E140D 0x140D
-#define HUAWEI_PRODUCT_E140E 0x140E
-#define HUAWEI_PRODUCT_E140F 0x140F
-#define HUAWEI_PRODUCT_E1410 0x1410
-#define HUAWEI_PRODUCT_E1411 0x1411
-#define HUAWEI_PRODUCT_E1412 0x1412
-#define HUAWEI_PRODUCT_E1413 0x1413
-#define HUAWEI_PRODUCT_E1414 0x1414
-#define HUAWEI_PRODUCT_E1415 0x1415
-#define HUAWEI_PRODUCT_E1416 0x1416
-#define HUAWEI_PRODUCT_E1417 0x1417
-#define HUAWEI_PRODUCT_E1418 0x1418
-#define HUAWEI_PRODUCT_E1419 0x1419
-#define HUAWEI_PRODUCT_E141A 0x141A
-#define HUAWEI_PRODUCT_E141B 0x141B
-#define HUAWEI_PRODUCT_E141C 0x141C
-#define HUAWEI_PRODUCT_E141D 0x141D
-#define HUAWEI_PRODUCT_E141E 0x141E
-#define HUAWEI_PRODUCT_E141F 0x141F
-#define HUAWEI_PRODUCT_E1420 0x1420
-#define HUAWEI_PRODUCT_E1421 0x1421
-#define HUAWEI_PRODUCT_E1422 0x1422
-#define HUAWEI_PRODUCT_E1423 0x1423
-#define HUAWEI_PRODUCT_E1424 0x1424
-#define HUAWEI_PRODUCT_E1425 0x1425
-#define HUAWEI_PRODUCT_E1426 0x1426
-#define HUAWEI_PRODUCT_E1427 0x1427
-#define HUAWEI_PRODUCT_E1428 0x1428
-#define HUAWEI_PRODUCT_E1429 0x1429
-#define HUAWEI_PRODUCT_E142A 0x142A
-#define HUAWEI_PRODUCT_E142B 0x142B
-#define HUAWEI_PRODUCT_E142C 0x142C
-#define HUAWEI_PRODUCT_E142D 0x142D
-#define HUAWEI_PRODUCT_E142E 0x142E
-#define HUAWEI_PRODUCT_E142F 0x142F
-#define HUAWEI_PRODUCT_E1430 0x1430
-#define HUAWEI_PRODUCT_E1431 0x1431
-#define HUAWEI_PRODUCT_E1432 0x1432
-#define HUAWEI_PRODUCT_E1433 0x1433
-#define HUAWEI_PRODUCT_E1434 0x1434
-#define HUAWEI_PRODUCT_E1435 0x1435
-#define HUAWEI_PRODUCT_E1436 0x1436
-#define HUAWEI_PRODUCT_E1437 0x1437
-#define HUAWEI_PRODUCT_E1438 0x1438
-#define HUAWEI_PRODUCT_E1439 0x1439
-#define HUAWEI_PRODUCT_E143A 0x143A
-#define HUAWEI_PRODUCT_E143B 0x143B
-#define HUAWEI_PRODUCT_E143C 0x143C
-#define HUAWEI_PRODUCT_E143D 0x143D
-#define HUAWEI_PRODUCT_E143E 0x143E
-#define HUAWEI_PRODUCT_E143F 0x143F
+#define HUAWEI_PRODUCT_E173 0x140C
+#define HUAWEI_PRODUCT_E1750 0x1406
#define HUAWEI_PRODUCT_K4505 0x1464
#define HUAWEI_PRODUCT_K3765 0x1465
-#define HUAWEI_PRODUCT_E14AC 0x14AC
-#define HUAWEI_PRODUCT_ETS1220 0x1803
+#define HUAWEI_PRODUCT_K4605 0x14C6
+#define HUAWEI_PRODUCT_E173S6 0x1C07
#define QUANTA_VENDOR_ID 0x0408
#define QUANTA_PRODUCT_Q101 0xEA02
@@ -223,9 +160,10 @@ static void option_instat_callback(struct urb *urb);
#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0x8001
#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000
#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001
-#define NOVATELWIRELESS_PRODUCT_G1 0xA001
-#define NOVATELWIRELESS_PRODUCT_G1_M 0xA002
+#define NOVATELWIRELESS_PRODUCT_E362 0x9010
+#define NOVATELWIRELESS_PRODUCT_E371 0x9011
#define NOVATELWIRELESS_PRODUCT_G2 0xA010
+#define NOVATELWIRELESS_PRODUCT_MC551 0xB001
/* AMOI PRODUCTS */
#define AMOI_VENDOR_ID 0x1614
@@ -257,6 +195,10 @@ static void option_instat_callback(struct urb *urb);
#define DELL_PRODUCT_5730_MINICARD_TELUS 0x8181
#define DELL_PRODUCT_5730_MINICARD_VZW 0x8182
+#define DELL_PRODUCT_5800_MINICARD_VZW 0x8195 /* Novatel E362 */
+#define DELL_PRODUCT_5800_V2_MINICARD_VZW 0x8196 /* Novatel E362 */
+#define DELL_PRODUCT_5804_MINICARD_ATT 0x819b /* Novatel E371 */
+
#define KYOCERA_VENDOR_ID 0x0c88
#define KYOCERA_PRODUCT_KPC650 0x17da
#define KYOCERA_PRODUCT_KPC680 0x180a
@@ -293,26 +235,48 @@ static void option_instat_callback(struct urb *urb);
#define QUALCOMM_VENDOR_ID 0x05C6
#define CMOTECH_VENDOR_ID 0x16d8
-#define CMOTECH_PRODUCT_6008 0x6008
-#define CMOTECH_PRODUCT_6280 0x6280
+#define CMOTECH_PRODUCT_6001 0x6001
+#define CMOTECH_PRODUCT_CMU_300 0x6002
+#define CMOTECH_PRODUCT_6003 0x6003
+#define CMOTECH_PRODUCT_6004 0x6004
+#define CMOTECH_PRODUCT_6005 0x6005
+#define CMOTECH_PRODUCT_CGU_628A 0x6006
+#define CMOTECH_PRODUCT_CHE_628S 0x6007
+#define CMOTECH_PRODUCT_CMU_301 0x6008
+#define CMOTECH_PRODUCT_CHU_628 0x6280
+#define CMOTECH_PRODUCT_CHU_628S 0x6281
+#define CMOTECH_PRODUCT_CDU_680 0x6803
+#define CMOTECH_PRODUCT_CDU_685A 0x6804
+#define CMOTECH_PRODUCT_CHU_720S 0x7001
+#define CMOTECH_PRODUCT_7002 0x7002
+#define CMOTECH_PRODUCT_CHU_629K 0x7003
+#define CMOTECH_PRODUCT_7004 0x7004
+#define CMOTECH_PRODUCT_7005 0x7005
+#define CMOTECH_PRODUCT_CGU_629 0x7006
+#define CMOTECH_PRODUCT_CHU_629S 0x700a
+#define CMOTECH_PRODUCT_CHU_720I 0x7211
+#define CMOTECH_PRODUCT_7212 0x7212
+#define CMOTECH_PRODUCT_7213 0x7213
+#define CMOTECH_PRODUCT_7251 0x7251
+#define CMOTECH_PRODUCT_7252 0x7252
+#define CMOTECH_PRODUCT_7253 0x7253
#define TELIT_VENDOR_ID 0x1bc7
#define TELIT_PRODUCT_UC864E 0x1003
#define TELIT_PRODUCT_UC864G 0x1004
+#define TELIT_PRODUCT_CC864_DUAL 0x1005
+#define TELIT_PRODUCT_CC864_SINGLE 0x1006
+#define TELIT_PRODUCT_DE910_DUAL 0x1010
+#define TELIT_PRODUCT_UE910_V2 0x1012
+#define TELIT_PRODUCT_LE920 0x1200
/* ZTE PRODUCTS */
#define ZTE_VENDOR_ID 0x19d2
#define ZTE_PRODUCT_MF622 0x0001
#define ZTE_PRODUCT_MF628 0x0015
#define ZTE_PRODUCT_MF626 0x0031
-#define ZTE_PRODUCT_CDMA_TECH 0xfffe
-#define ZTE_PRODUCT_AC8710 0xfff1
-#define ZTE_PRODUCT_AC2726 0xfff5
-#define ZTE_PRODUCT_AC8710T 0xffff
-
-/* ZTE PRODUCTS -- alternate vendor ID */
-#define ZTE_VENDOR_ID2 0x1d6b
-#define ZTE_PRODUCT_MF_330 0x0002
+#define ZTE_PRODUCT_MC2718 0xffe8
+#define ZTE_PRODUCT_AC2726 0xfff1
#define BENQ_VENDOR_ID 0x04a5
#define BENQ_PRODUCT_H10 0x4068
@@ -339,11 +303,15 @@ static void option_instat_callback(struct urb *urb);
#define TOSHIBA_PRODUCT_G450 0x0d45
#define ALINK_VENDOR_ID 0x1e0e
+#define ALINK_PRODUCT_PH300 0x9100
#define ALINK_PRODUCT_3GU 0x9200
/* ALCATEL PRODUCTS */
#define ALCATEL_VENDOR_ID 0x1bbb
-#define ALCATEL_PRODUCT_X060S 0x0000
+#define ALCATEL_PRODUCT_X060S_X200 0x0000
+#define ALCATEL_PRODUCT_X220_X500D 0x0017
+#define ALCATEL_PRODUCT_L100V 0x011e
+#define ALCATEL_PRODUCT_L800MA 0x0203
#define PIRELLI_VENDOR_ID 0x1266
#define PIRELLI_PRODUCT_C100_1 0x1002
@@ -378,25 +346,153 @@ static void option_instat_callback(struct urb *urb);
* It seems to contain a Qualcomm QSC6240/6290 chipset */
#define FOUR_G_SYSTEMS_PRODUCT_W14 0x9603
+/* iBall 3.5G connect wireless modem */
+#define IBALL_3_5G_CONNECT 0x9605
+
+/* Zoom */
+#define ZOOM_PRODUCT_4597 0x9607
+
+/* SpeedUp SU9800 usb 3g modem */
+#define SPEEDUP_PRODUCT_SU9800 0x9800
+
/* Haier products */
#define HAIER_VENDOR_ID 0x201e
#define HAIER_PRODUCT_CE100 0x2009
-#define CINTERION_VENDOR_ID 0x0681
+/* Cinterion (formerly Siemens) products */
+#define SIEMENS_VENDOR_ID 0x0681
+#define CINTERION_VENDOR_ID 0x1e2d
+#define CINTERION_PRODUCT_HC25_MDM 0x0047
+#define CINTERION_PRODUCT_HC25_MDMNET 0x0040
+#define CINTERION_PRODUCT_HC28_MDM 0x004C
+#define CINTERION_PRODUCT_HC28_MDMNET 0x004A /* same for HC28J */
+#define CINTERION_PRODUCT_EU3_E 0x0051
+#define CINTERION_PRODUCT_EU3_P 0x0052
+#define CINTERION_PRODUCT_PH8 0x0053
+#define CINTERION_PRODUCT_AHXX 0x0055
+#define CINTERION_PRODUCT_PLXX 0x0060
/* Olivetti products */
#define OLIVETTI_VENDOR_ID 0x0b3c
#define OLIVETTI_PRODUCT_OLICARD100 0xc000
+#define OLIVETTI_PRODUCT_OLICARD120 0xc001
+#define OLIVETTI_PRODUCT_OLICARD140 0xc002
+#define OLIVETTI_PRODUCT_OLICARD145 0xc003
+#define OLIVETTI_PRODUCT_OLICARD155 0xc004
+#define OLIVETTI_PRODUCT_OLICARD200 0xc005
+#define OLIVETTI_PRODUCT_OLICARD160 0xc00a
+#define OLIVETTI_PRODUCT_OLICARD500 0xc00b
/* Celot products */
#define CELOT_VENDOR_ID 0x211f
#define CELOT_PRODUCT_CT680M 0x6801
-/* ONDA Communication vendor id */
-#define ONDA_VENDOR_ID 0x1ee8
-
-/* ONDA MT825UP HSDPA 14.2 modem */
-#define ONDA_MT825UP 0x000b
+/* Samsung products */
+#define SAMSUNG_VENDOR_ID 0x04e8
+#define SAMSUNG_PRODUCT_GT_B3730 0x6889
+
+/* YUGA products www.yuga-info.com gavin.kx@qq.com */
+#define YUGA_VENDOR_ID 0x257A
+#define YUGA_PRODUCT_CEM600 0x1601
+#define YUGA_PRODUCT_CEM610 0x1602
+#define YUGA_PRODUCT_CEM500 0x1603
+#define YUGA_PRODUCT_CEM510 0x1604
+#define YUGA_PRODUCT_CEM800 0x1605
+#define YUGA_PRODUCT_CEM900 0x1606
+
+#define YUGA_PRODUCT_CEU818 0x1607
+#define YUGA_PRODUCT_CEU816 0x1608
+#define YUGA_PRODUCT_CEU828 0x1609
+#define YUGA_PRODUCT_CEU826 0x160A
+#define YUGA_PRODUCT_CEU518 0x160B
+#define YUGA_PRODUCT_CEU516 0x160C
+#define YUGA_PRODUCT_CEU528 0x160D
+#define YUGA_PRODUCT_CEU526 0x160F
+#define YUGA_PRODUCT_CEU881 0x161F
+#define YUGA_PRODUCT_CEU882 0x162F
+
+#define YUGA_PRODUCT_CWM600 0x2601
+#define YUGA_PRODUCT_CWM610 0x2602
+#define YUGA_PRODUCT_CWM500 0x2603
+#define YUGA_PRODUCT_CWM510 0x2604
+#define YUGA_PRODUCT_CWM800 0x2605
+#define YUGA_PRODUCT_CWM900 0x2606
+
+#define YUGA_PRODUCT_CWU718 0x2607
+#define YUGA_PRODUCT_CWU716 0x2608
+#define YUGA_PRODUCT_CWU728 0x2609
+#define YUGA_PRODUCT_CWU726 0x260A
+#define YUGA_PRODUCT_CWU518 0x260B
+#define YUGA_PRODUCT_CWU516 0x260C
+#define YUGA_PRODUCT_CWU528 0x260D
+#define YUGA_PRODUCT_CWU581 0x260E
+#define YUGA_PRODUCT_CWU526 0x260F
+#define YUGA_PRODUCT_CWU582 0x261F
+#define YUGA_PRODUCT_CWU583 0x262F
+
+#define YUGA_PRODUCT_CLM600 0x3601
+#define YUGA_PRODUCT_CLM610 0x3602
+#define YUGA_PRODUCT_CLM500 0x3603
+#define YUGA_PRODUCT_CLM510 0x3604
+#define YUGA_PRODUCT_CLM800 0x3605
+#define YUGA_PRODUCT_CLM900 0x3606
+
+#define YUGA_PRODUCT_CLU718 0x3607
+#define YUGA_PRODUCT_CLU716 0x3608
+#define YUGA_PRODUCT_CLU728 0x3609
+#define YUGA_PRODUCT_CLU726 0x360A
+#define YUGA_PRODUCT_CLU518 0x360B
+#define YUGA_PRODUCT_CLU516 0x360C
+#define YUGA_PRODUCT_CLU528 0x360D
+#define YUGA_PRODUCT_CLU526 0x360F
+
+/* Viettel products */
+#define VIETTEL_VENDOR_ID 0x2262
+#define VIETTEL_PRODUCT_VT1000 0x0002
+
+/* ZD Incorporated */
+#define ZD_VENDOR_ID 0x0685
+#define ZD_PRODUCT_7000 0x7000
+
+/* LG products */
+#define LG_VENDOR_ID 0x1004
+#define LG_PRODUCT_L02C 0x618f
+
+/* MediaTek products */
+#define MEDIATEK_VENDOR_ID 0x0e8d
+#define MEDIATEK_PRODUCT_DC_1COM 0x00a0
+#define MEDIATEK_PRODUCT_DC_4COM 0x00a5
+#define MEDIATEK_PRODUCT_DC_4COM2 0x00a7
+#define MEDIATEK_PRODUCT_DC_5COM 0x00a4
+#define MEDIATEK_PRODUCT_7208_1COM 0x7101
+#define MEDIATEK_PRODUCT_7208_2COM 0x7102
+#define MEDIATEK_PRODUCT_7103_2COM 0x7103
+#define MEDIATEK_PRODUCT_7106_2COM 0x7106
+#define MEDIATEK_PRODUCT_FP_1COM 0x0003
+#define MEDIATEK_PRODUCT_FP_2COM 0x0023
+#define MEDIATEK_PRODUCT_FPDC_1COM 0x0043
+#define MEDIATEK_PRODUCT_FPDC_2COM 0x0033
+
+/* Cellient products */
+#define CELLIENT_VENDOR_ID 0x2692
+#define CELLIENT_PRODUCT_MEN200 0x9005
+
+/* Hyundai Petatel Inc. products */
+#define PETATEL_VENDOR_ID 0x1ff4
+#define PETATEL_PRODUCT_NP10T_600A 0x600a
+#define PETATEL_PRODUCT_NP10T_600E 0x600e
+
+/* TP-LINK Incorporated products */
+#define TPLINK_VENDOR_ID 0x2357
+#define TPLINK_PRODUCT_MA180 0x0201
+
+/* Changhong products */
+#define CHANGHONG_VENDOR_ID 0x2077
+#define CHANGHONG_PRODUCT_CH690 0x7001
+
+/* Inovia */
+#define INOVIA_VENDOR_ID 0x20a6
+#define INOVIA_SEW858 0x1105
/* some devices interfaces need special handling due to a number of reasons */
enum option_blacklist_reason {
@@ -405,17 +501,80 @@ enum option_blacklist_reason {
OPTION_BLACKLIST_RESERVED_IF = 2
};
+#define MAX_BL_NUM 8
struct option_blacklist_info {
- const u32 infolen; /* number of interface numbers on blacklist */
- const u8 *ifaceinfo; /* pointer to the array holding the numbers */
- enum option_blacklist_reason reason;
+ /* bitfield of interface numbers for OPTION_BLACKLIST_SENDSETUP */
+ const unsigned long sendsetup;
+ /* bitfield of interface numbers for OPTION_BLACKLIST_RESERVED_IF */
+ const unsigned long reserved;
};
-static const u8 four_g_w14_no_sendsetup[] = { 0, 1 };
static const struct option_blacklist_info four_g_w14_blacklist = {
- .infolen = ARRAY_SIZE(four_g_w14_no_sendsetup),
- .ifaceinfo = four_g_w14_no_sendsetup,
- .reason = OPTION_BLACKLIST_SENDSETUP
+ .sendsetup = BIT(0) | BIT(1),
+};
+
+static const struct option_blacklist_info alcatel_x200_blacklist = {
+ .sendsetup = BIT(0) | BIT(1),
+ .reserved = BIT(4),
+};
+
+static const struct option_blacklist_info zte_0037_blacklist = {
+ .sendsetup = BIT(0) | BIT(1),
+};
+
+static const struct option_blacklist_info zte_k3765_z_blacklist = {
+ .sendsetup = BIT(0) | BIT(1) | BIT(2),
+ .reserved = BIT(4),
+};
+
+static const struct option_blacklist_info zte_mc2718_z_blacklist = {
+ .sendsetup = BIT(1) | BIT(2) | BIT(3) | BIT(4),
+};
+
+static const struct option_blacklist_info huawei_cdc12_blacklist = {
+ .reserved = BIT(1) | BIT(2),
+};
+
+static const struct option_blacklist_info net_intf0_blacklist = {
+ .reserved = BIT(0),
+};
+
+static const struct option_blacklist_info net_intf1_blacklist = {
+ .reserved = BIT(1),
+};
+
+static const struct option_blacklist_info net_intf2_blacklist = {
+ .reserved = BIT(2),
+};
+
+static const struct option_blacklist_info net_intf3_blacklist = {
+ .reserved = BIT(3),
+};
+
+static const struct option_blacklist_info net_intf4_blacklist = {
+ .reserved = BIT(4),
+};
+
+static const struct option_blacklist_info net_intf5_blacklist = {
+ .reserved = BIT(5),
+};
+
+static const struct option_blacklist_info net_intf6_blacklist = {
+ .reserved = BIT(6),
+};
+
+static const struct option_blacklist_info zte_mf626_blacklist = {
+ .sendsetup = BIT(0) | BIT(1),
+ .reserved = BIT(4),
+};
+
+static const struct option_blacklist_info zte_1255_blacklist = {
+ .reserved = BIT(3) | BIT(4),
+};
+
+static const struct option_blacklist_info telit_le920_blacklist = {
+ .sendsetup = BIT(0),
+ .reserved = BIT(1) | BIT(5),
};
static const struct usb_device_id option_ids[] = {
@@ -449,76 +608,378 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) },
{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) },
{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1404, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1407, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140A, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140B, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140C, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140D, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140E, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140F, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141A, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141B, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141C, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141D, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141E, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141F, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1420, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1421, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1422, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1423, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1424, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1425, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1426, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1427, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1428, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1429, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1431, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1432, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1433, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1434, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1435, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1436, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1437, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1438, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1439, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143A, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143B, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) },
+ { USB_DEVICE(QUANTA_VENDOR_ID, 0xea42),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c05, USB_CLASS_COMM, 0x02, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c1f, USB_CLASS_COMM, 0x02, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t) &net_intf1_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S6, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t) &net_intf1_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1750, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t) &net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1441, USB_CLASS_COMM, 0x02, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1442, USB_CLASS_COMM, 0x02, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x14ac, 0xff, 0xff, 0xff), /* Huawei E1820 */
+ .driver_info = (kernel_ulong_t) &net_intf1_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0xff, 0xff) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x01) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x02) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x03) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x04) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x05) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x06) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x10) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x12) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x13) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x14) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x15) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x17) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x18) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x19) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x31) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x32) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x33) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x34) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x35) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x36) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x48) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x49) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x61) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x62) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x63) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x64) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x65) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x66) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x72) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x73) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x74) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x75) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x01) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x02) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x03) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x04) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x05) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x06) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x10) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x12) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x13) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x14) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x15) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x17) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x18) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x19) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x31) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x32) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x33) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x34) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x35) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x36) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x48) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x49) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x61) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x62) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x63) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x64) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x65) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x66) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x72) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x73) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x74) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x75) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x01) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x02) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x03) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x04) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x05) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x06) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x10) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x12) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x13) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x14) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x15) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x17) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x18) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x19) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x31) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x32) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x33) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x34) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x35) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x36) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x48) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x49) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x61) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x62) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x63) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x64) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x65) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x66) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x72) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x73) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x74) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x75) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x78) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x79) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x01) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x02) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x03) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x04) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x05) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x06) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x10) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x12) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x13) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x14) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x15) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x17) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x18) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x19) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x31) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x32) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x33) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x34) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x35) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x36) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x48) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x49) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x61) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x62) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x63) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x64) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x65) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x66) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x72) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x73) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x74) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x75) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x78) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x79) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x01) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x02) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x03) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x04) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x05) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x06) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x10) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x12) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x13) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x14) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x15) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x17) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x18) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x19) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x31) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x32) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x33) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x34) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x35) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x36) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x48) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x49) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x61) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x62) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x63) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x64) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x65) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x66) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x72) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x73) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x74) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x75) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x78) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x79) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x01) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x02) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x03) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x04) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x05) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x06) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x10) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x12) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x13) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x14) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x15) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x17) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x18) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x19) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x31) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x32) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x33) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x34) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x35) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x36) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x48) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x49) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x61) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x62) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x63) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x64) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x65) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x66) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x72) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x73) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x74) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x75) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x78) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x79) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7C) },
+
+
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) },
@@ -544,6 +1005,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) },
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED3) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED4) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED5) },
@@ -554,9 +1016,11 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC547) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED) },
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1) },
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1_M) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) },
+ /* Novatel Ovation MC551 a.k.a. Verizon USB551L */
+ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E371, 0xff, 0xff, 0xff) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
@@ -579,43 +1043,92 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
+ { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5804_MINICARD_ATT, 0xff, 0xff, 0xff) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
{ USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
{ USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012, 0xff) },
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
- { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
- { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */
- { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },
+ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
+ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6004) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6005) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CGU_628A) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHE_628S),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_301),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_628),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_628S) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDU_680) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDU_685A) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_720S),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7002),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_629K),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7004),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7005) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CGU_629),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_629S),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_720I),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7212),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7213),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7251),
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7252),
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7253),
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
+ .driver_info = (kernel_ulong_t)&telit_le920_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0003, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0004, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0005, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0006, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0007, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0008, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0009, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000a, 0xff, 0xff, 0xff) },
@@ -626,56 +1139,64 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000f, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0010, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0011, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0018, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0019, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0019, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0020, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0021, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0021, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0022, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0023, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff) },
- /* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) }, */
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff,
+ 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_mf626_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0034, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0037, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0037, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&zte_0037_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0038, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0039, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0040, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0042, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0042, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0043, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0044, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0048, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0049, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0049, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0050, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff) },
- /* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0053, 0xff, 0xff, 0xff) }, */
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0056, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0064, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0065, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0067, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0077, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) },
@@ -684,44 +1205,96 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0083, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0087, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0088, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0089, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0090, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0091, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0092, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0093, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0095, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0096, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0097, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0105, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0106, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0108, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf6_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0135, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0136, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0137, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0139, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0145, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0146, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0148, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0149, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0150, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0151, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0154, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0160, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0164, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0189, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0196, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0197, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0200, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0201, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff), /* ONDA MT8205 */
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff), /* ZTE MF880 */
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0330, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0395, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0412, 0xff, 0xff, 0xff), /* Telewell TW-LTE 4G */
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0414, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0417, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) },
@@ -837,18 +1410,24 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1169, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1170, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1244, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1246, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1248, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1249, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1250, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1251, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1253, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&zte_1255_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1257, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1258, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1259, 0xff, 0xff, 0xff) },
@@ -862,7 +1441,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1267, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1268, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1269, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1270, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1270, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1271, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1272, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1273, 0xff, 0xff, 0xff) },
@@ -893,21 +1473,85 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1301, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1302, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1303, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1333, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff), /* ZTE MF91 */
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1428, 0xff, 0xff, 0xff), /* Telewell TW-LTE 4G v2 */
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1533, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1534, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1535, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1545, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1546, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1547, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1565, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1566, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1567, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1589, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1590, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1591, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1592, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1594, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1596, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1598, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1600, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
+ 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
+
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffe9, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff8b, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff8c, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff8d, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff8e, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff8f, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff90, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff91, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff92, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff93, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff94, 0xff, 0xff, 0xff) },
+
+ /* NOTE: most ZTE CDMA devices should be driven by zte_ev, not option */
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2718, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&zte_mc2718_z_blacklist },
+ { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
+ { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
+ { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) },
- { USB_DEVICE(ZTE_VENDOR_ID2, ZTE_PRODUCT_MF_330) },
+
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
{ USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */
@@ -920,52 +1564,170 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) },
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
{ USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
+ { USB_DEVICE(ALINK_VENDOR_ID, ALINK_PRODUCT_PH300) },
{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
- { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
+ .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
+ },
+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D),
+ .driver_info = (kernel_ulong_t)&net_intf6_blacklist },
+ { USB_DEVICE(ALCATEL_VENDOR_ID, 0x0052),
+ .driver_info = (kernel_ulong_t)&net_intf6_blacklist },
+ { USB_DEVICE(ALCATEL_VENDOR_ID, 0x00b6),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE(ALCATEL_VENDOR_ID, 0x00b7),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L800MA),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
{ USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
.driver_info = (kernel_ulong_t)&four_g_w14_blacklist
},
+ { USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, SPEEDUP_PRODUCT_SU9800, 0xff) },
+ { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
+ { USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) },
{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
/* Pirelli */
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B) },
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C) },
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D) },
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E) },
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) },
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)},
- { USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) },
- { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012, 0xff) },
+ /* Cinterion */
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
+ { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) },
+ { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDMNET) },
+ { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, /* HC28 enumerates with Siemens or Cinterion VID depending on FW revision */
+ { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD120),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD140),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) },
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD155),
+ .driver_info = (kernel_ulong_t)&net_intf6_blacklist },
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200),
+ .driver_info = (kernel_ulong_t)&net_intf6_blacklist },
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD160),
+ .driver_info = (kernel_ulong_t)&net_intf6_blacklist },
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD500),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
- { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
+ { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM610) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM500) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM510) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM800) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM900) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU818) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU816) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU828) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU826) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU518) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU516) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU528) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU526) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM600) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM610) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM500) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM510) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM800) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM900) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU718) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU716) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU728) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU726) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU518) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU516) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU528) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU526) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM600) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM610) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM500) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM510) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM800) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM900) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU718) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU716) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU728) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU726) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU518) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU516) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU881) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU882) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU581) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU582) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU583) },
+ { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) },
+ { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) }, /* MediaTek MT6276M modem & app port */
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_1COM, 0x0a, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_5COM, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_5COM, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7208_1COM, 0x02, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7208_2COM, 0x02, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_1COM, 0x0a, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7103_2COM, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7106_2COM, 0x02, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) },
+ { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
+ { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600A) },
+ { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600E) },
+ { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(TPLINK_VENDOR_ID, 0x9000), /* TP-Link MA260 */
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x02, 0x01) }, /* D-Link DWM-156 (variant) */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x00, 0x00) }, /* D-Link DWM-156 (variant) */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */
+ { USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
-static struct usb_driver option_driver = {
- .name = "option",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
-#ifdef CONFIG_PM
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .supports_autosuspend = 1,
-#endif
- .id_table = option_ids,
- .no_dynamic_id = 1,
-};
-
/* The card has three separate interfaces, which the serial driver
* recognizes separately, thus num_port=1.
*/
@@ -976,7 +1738,6 @@ static struct usb_serial_driver option_1port_device = {
.name = "option1",
},
.description = "GSM modem (1-port)",
- .usb_driver = &option_driver,
.id_table = option_ids,
.num_ports = 1,
.probe = option_probe,
@@ -986,12 +1747,13 @@ static struct usb_serial_driver option_1port_device = {
.write = usb_wwan_write,
.write_room = usb_wwan_write_room,
.chars_in_buffer = usb_wwan_chars_in_buffer,
- .set_termios = usb_wwan_set_termios,
.tiocmget = usb_wwan_tiocmget,
.tiocmset = usb_wwan_tiocmset,
- .attach = usb_wwan_startup,
- .disconnect = usb_wwan_disconnect,
- .release = usb_wwan_release,
+ .ioctl = usb_wwan_ioctl,
+ .attach = option_attach,
+ .release = option_release,
+ .port_probe = usb_wwan_port_probe,
+ .port_remove = usb_wwan_port_remove,
.read_int_callback = option_instat_callback,
#ifdef CONFIG_PM
.suspend = usb_wwan_suspend,
@@ -999,134 +1761,138 @@ static struct usb_serial_driver option_1port_device = {
#endif
};
-static int debug;
-
-/* per port private data */
-
-#define N_IN_URB 4
-#define N_OUT_URB 4
-#define IN_BUFLEN 4096
-#define OUT_BUFLEN 4096
-
-struct option_port_private {
- /* Input endpoints and buffer for this port */
- struct urb *in_urbs[N_IN_URB];
- u8 *in_buffer[N_IN_URB];
- /* Output endpoints and buffer for this port */
- struct urb *out_urbs[N_OUT_URB];
- u8 *out_buffer[N_OUT_URB];
- unsigned long out_busy; /* Bit vector of URBs in use */
- int opened;
- struct usb_anchor delayed;
-
- /* Settings for the port */
- int rts_state; /* Handshaking pins (outputs) */
- int dtr_state;
- int cts_state; /* Handshaking pins (inputs) */
- int dsr_state;
- int dcd_state;
- int ri_state;
-
- unsigned long tx_start_time[N_OUT_URB];
+static struct usb_serial_driver * const serial_drivers[] = {
+ &option_1port_device, NULL
};
-/* Functions used by new usb-serial code. */
-static int __init option_init(void)
-{
- int retval;
- retval = usb_serial_register(&option_1port_device);
- if (retval)
- goto failed_1port_device_register;
- retval = usb_register(&option_driver);
- if (retval)
- goto failed_driver_register;
+struct option_private {
+ u8 bInterfaceNumber;
+};
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
+module_usb_serial_driver(serial_drivers, option_ids);
- return 0;
+static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason,
+ const struct option_blacklist_info *blacklist)
+{
+ unsigned long num;
+ const unsigned long *intf_list;
-failed_driver_register:
- usb_serial_deregister(&option_1port_device);
-failed_1port_device_register:
- return retval;
-}
+ if (blacklist) {
+ if (reason == OPTION_BLACKLIST_SENDSETUP)
+ intf_list = &blacklist->sendsetup;
+ else if (reason == OPTION_BLACKLIST_RESERVED_IF)
+ intf_list = &blacklist->reserved;
+ else {
+ BUG_ON(reason);
+ return false;
+ }
-static void __exit option_exit(void)
-{
- usb_deregister(&option_driver);
- usb_serial_deregister(&option_1port_device);
+ for_each_set_bit(num, intf_list, MAX_BL_NUM + 1) {
+ if (num == ifnum)
+ return true;
+ }
+ }
+ return false;
}
-module_init(option_init);
-module_exit(option_exit);
-
static int option_probe(struct usb_serial *serial,
const struct usb_device_id *id)
{
- struct usb_wwan_intf_private *data;
- /* D-Link DWM 652 still exposes CD-Rom emulation interface in modem mode */
- if (serial->dev->descriptor.idVendor == DLINK_VENDOR_ID &&
- serial->dev->descriptor.idProduct == DLINK_PRODUCT_DWM_652 &&
- serial->interface->cur_altsetting->desc.bInterfaceClass == 0x8)
- return -ENODEV;
+ struct usb_interface_descriptor *iface_desc =
+ &serial->interface->cur_altsetting->desc;
+ struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
- /* Bandrich modem and AT command interface is 0xff */
- if ((serial->dev->descriptor.idVendor == BANDRICH_VENDOR_ID ||
- serial->dev->descriptor.idVendor == PIRELLI_VENDOR_ID) &&
- serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff)
+ /* Never bind to the CD-Rom emulation interface */
+ if (iface_desc->bInterfaceClass == 0x08)
return -ENODEV;
- /* Don't bind network interfaces on Huawei K3765 & K4505 */
- if (serial->dev->descriptor.idVendor == HUAWEI_VENDOR_ID &&
- (serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K3765 ||
- serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505) &&
- serial->interface->cur_altsetting->desc.bInterfaceNumber == 1)
+ /*
+ * Don't bind reserved interfaces (like network ones) which often have
+ * the same class/subclass/protocol as the serial interfaces. Look at
+ * the Windows driver .INF files for reserved interface numbers.
+ */
+ if (is_blacklisted(
+ iface_desc->bInterfaceNumber,
+ OPTION_BLACKLIST_RESERVED_IF,
+ (const struct option_blacklist_info *) id->driver_info))
+ return -ENODEV;
+ /*
+ * Don't bind network interface on Samsung GT-B3730, it is handled by
+ * a separate module.
+ */
+ if (dev_desc->idVendor == cpu_to_le16(SAMSUNG_VENDOR_ID) &&
+ dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) &&
+ iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
return -ENODEV;
- data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
+ /* Store device id so we can use it during attach. */
+ usb_set_serial_data(serial, (void *)id);
+
+ return 0;
+}
+
+static int option_attach(struct usb_serial *serial)
+{
+ struct usb_interface_descriptor *iface_desc;
+ const struct usb_device_id *id;
+ struct usb_wwan_intf_private *data;
+ struct option_private *priv;
+ data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
if (!data)
return -ENOMEM;
- data->send_setup = option_send_setup;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ kfree(data);
+ return -ENOMEM;
+ }
+
+ /* Retrieve device id stored at probe. */
+ id = usb_get_serial_data(serial);
+ iface_desc = &serial->interface->cur_altsetting->desc;
+
+ priv->bInterfaceNumber = iface_desc->bInterfaceNumber;
+ data->private = priv;
+
+ if (!is_blacklisted(iface_desc->bInterfaceNumber,
+ OPTION_BLACKLIST_SENDSETUP,
+ (struct option_blacklist_info *)id->driver_info)) {
+ data->send_setup = option_send_setup;
+ }
spin_lock_init(&data->susp_lock);
- data->private = (void *)id->driver_info;
+
+ usb_set_serial_data(serial, data);
+
return 0;
}
-static enum option_blacklist_reason is_blacklisted(const u8 ifnum,
- const struct option_blacklist_info *blacklist)
+static void option_release(struct usb_serial *serial)
{
- const u8 *info;
- int i;
-
- if (blacklist) {
- info = blacklist->ifaceinfo;
+ struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
+ struct option_private *priv = intfdata->private;
- for (i = 0; i < blacklist->infolen; i++) {
- if (info[i] == ifnum)
- return blacklist->reason;
- }
- }
- return OPTION_BLACKLIST_NONE;
+ kfree(priv);
+ kfree(intfdata);
}
static void option_instat_callback(struct urb *urb)
{
int err;
int status = urb->status;
- struct usb_serial_port *port = urb->context;
- struct option_port_private *portdata = usb_get_serial_port_data(port);
+ struct usb_serial_port *port = urb->context;
+ struct device *dev = &port->dev;
+ struct usb_wwan_port_private *portdata =
+ usb_get_serial_port_data(port);
- dbg("%s", __func__);
- dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata);
+ dev_dbg(dev, "%s: urb %p port %p has data %p\n", __func__, urb, port, portdata);
if (status == 0) {
struct usb_ctrlrequest *req_pkt =
(struct usb_ctrlrequest *)urb->transfer_buffer;
if (!req_pkt) {
- dbg("%s: NULL req_pkt", __func__);
+ dev_dbg(dev, "%s: NULL req_pkt\n", __func__);
return;
}
if ((req_pkt->bRequestType == 0xA1) &&
@@ -1136,7 +1902,7 @@ static void option_instat_callback(struct urb *urb)
urb->transfer_buffer +
sizeof(struct usb_ctrlrequest));
- dbg("%s: signal x%x", __func__, signals);
+ dev_dbg(dev, "%s: signal x%x\n", __func__, signals);
old_dcd_state = portdata->dcd_state;
portdata->cts_state = 1;
@@ -1144,25 +1910,21 @@ static void option_instat_callback(struct urb *urb)
portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
portdata->ri_state = ((signals & 0x08) ? 1 : 0);
- if (old_dcd_state && !portdata->dcd_state) {
- struct tty_struct *tty =
- tty_port_tty_get(&port->port);
- if (tty && !C_CLOCAL(tty))
- tty_hangup(tty);
- tty_kref_put(tty);
- }
+ if (old_dcd_state && !portdata->dcd_state)
+ tty_port_tty_hangup(&port->port, true);
} else {
- dbg("%s: type %x req %x", __func__,
+ dev_dbg(dev, "%s: type %x req %x\n", __func__,
req_pkt->bRequestType, req_pkt->bRequest);
}
} else
- err("%s: error %d", __func__, status);
+ dev_err(dev, "%s: error %d\n", __func__, status);
/* Resubmit urb so we continue receiving IRQ data */
if (status != -ESHUTDOWN && status != -ENOENT) {
+ usb_mark_last_busy(port->serial->dev);
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
- dbg("%s: resubmit intr urb failed. (%d)",
+ dev_dbg(dev, "%s: resubmit intr urb failed. (%d)\n",
__func__, err);
}
}
@@ -1175,19 +1937,11 @@ static void option_instat_callback(struct urb *urb)
static int option_send_setup(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
- struct usb_wwan_intf_private *intfdata =
- (struct usb_wwan_intf_private *) serial->private;
- struct option_port_private *portdata;
- int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+ struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
+ struct option_private *priv = intfdata->private;
+ struct usb_wwan_port_private *portdata;
int val = 0;
- dbg("%s", __func__);
-
- if (is_blacklisted(ifNum,
- (struct option_blacklist_info *) intfdata->private)
- == OPTION_BLACKLIST_SENDSETUP) {
- dbg("No send_setup on blacklisted interface #%d\n", ifNum);
- return -EIO;
- }
+ int res;
portdata = usb_get_serial_port_data(port);
@@ -1196,15 +1950,19 @@ static int option_send_setup(struct usb_serial_port *port)
if (portdata->rts_state)
val |= 0x02;
- return usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ res = usb_autopm_get_interface(serial->interface);
+ if (res)
+ return res;
+
+ res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ 0x22, 0x21, val, priv->bInterfaceNumber, NULL,
+ 0, USB_CTRL_SET_TIMEOUT);
+
+ usb_autopm_put_interface(serial->interface);
+
+ return res;
}
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug messages");
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index e199b0f4f99..a4b88bc038b 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -39,7 +39,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -57,7 +56,6 @@
#define OTI6858_DESCRIPTION \
"Ours Technology Inc. OTi-6858 USB to serial adapter driver"
#define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>"
-#define OTI6858_VERSION "0.2"
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) },
@@ -66,16 +64,6 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver oti6858_driver = {
- .name = "oti6858",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
-static int debug;
-
/* requests */
#define OTI6858_REQ_GET_STATUS (USB_DIR_IN | USB_TYPE_VENDOR | 0x00)
#define OTI6858_REQ_T_GET_STATUS 0x01
@@ -114,6 +102,7 @@ struct oti6858_control_pkt {
#define TX_BUFFER_EMPTIED 0x09
u8 pin_state;
#define PIN_MASK 0x3f
+#define PIN_MSR_MASK 0x1b
#define PIN_RTS 0x20 /* output pin */
#define PIN_CTS 0x10 /* input pin, active low */
#define PIN_DSR 0x08 /* input pin, active low */
@@ -135,8 +124,6 @@ static void oti6858_close(struct usb_serial_port *port);
static void oti6858_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
static void oti6858_init_termios(struct tty_struct *tty);
-static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg);
static void oti6858_read_int_callback(struct urb *urb);
static void oti6858_read_bulk_callback(struct urb *urb);
static void oti6858_write_bulk_callback(struct urb *urb);
@@ -144,11 +131,11 @@ static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static int oti6858_write_room(struct tty_struct *tty);
static int oti6858_chars_in_buffer(struct tty_struct *tty);
-static int oti6858_tiocmget(struct tty_struct *tty, struct file *file);
-static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
+static int oti6858_tiocmget(struct tty_struct *tty);
+static int oti6858_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
-static int oti6858_startup(struct usb_serial *serial);
-static void oti6858_release(struct usb_serial *serial);
+static int oti6858_port_probe(struct usb_serial_port *port);
+static int oti6858_port_remove(struct usb_serial_port *port);
/* device info */
static struct usb_serial_driver oti6858_device = {
@@ -161,18 +148,22 @@ static struct usb_serial_driver oti6858_device = {
.open = oti6858_open,
.close = oti6858_close,
.write = oti6858_write,
- .ioctl = oti6858_ioctl,
.set_termios = oti6858_set_termios,
.init_termios = oti6858_init_termios,
.tiocmget = oti6858_tiocmget,
.tiocmset = oti6858_tiocmset,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
.read_bulk_callback = oti6858_read_bulk_callback,
.read_int_callback = oti6858_read_int_callback,
.write_bulk_callback = oti6858_write_bulk_callback,
.write_room = oti6858_write_room,
.chars_in_buffer = oti6858_chars_in_buffer,
- .attach = oti6858_startup,
- .release = oti6858_release,
+ .port_probe = oti6858_port_probe,
+ .port_remove = oti6858_port_remove,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+ &oti6858_device, NULL
};
struct oti6858_private {
@@ -195,7 +186,6 @@ struct oti6858_private {
u8 setup_done;
struct delayed_work delayed_setup_work;
- wait_queue_head_t intr_wait;
struct usb_serial_port *port; /* USB port with which associated */
};
@@ -208,11 +198,8 @@ static void setup_line(struct work_struct *work)
unsigned long flags;
int result;
- dbg("%s(port = %d)", __func__, port->number);
-
new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL);
- if (new_setup == NULL) {
- dev_err(&port->dev, "%s(): out of memory!\n", __func__);
+ if (!new_setup) {
/* we will try again */
schedule_delayed_work(&priv->delayed_setup_work,
msecs_to_jiffies(2));
@@ -262,12 +249,11 @@ static void setup_line(struct work_struct *work)
priv->setup_done = 1;
spin_unlock_irqrestore(&priv->lock, flags);
- dbg("%s(): submitting interrupt urb", __func__);
- port->interrupt_in_urb->dev = port->serial->dev;
+ dev_dbg(&port->dev, "%s(): submitting interrupt urb\n", __func__);
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result != 0) {
- dev_err(&port->dev, "%s(): usb_submit_urb() failed"
- " with error %d\n", __func__, result);
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed with error %d\n",
+ __func__, result);
}
}
@@ -280,8 +266,6 @@ static void send_data(struct work_struct *work)
unsigned long flags;
u8 *allow;
- dbg("%s(port = %d)", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
if (priv->flags.write_urb_in_use) {
spin_unlock_irqrestore(&priv->lock, flags);
@@ -301,11 +285,9 @@ static void send_data(struct work_struct *work)
if (count != 0) {
allow = kmalloc(1, GFP_KERNEL);
- if (!allow) {
- dev_err(&port->dev, "%s(): kmalloc failed\n",
- __func__);
+ if (!allow)
return;
- }
+
result = usb_control_msg(port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0),
OTI6858_REQ_T_CHECK_TXBUFF,
@@ -319,12 +301,11 @@ static void send_data(struct work_struct *work)
if (count == 0) {
priv->flags.write_urb_in_use = 0;
- dbg("%s(): submitting interrupt urb", __func__);
- port->interrupt_in_urb->dev = port->serial->dev;
+ dev_dbg(&port->dev, "%s(): submitting interrupt urb\n", __func__);
result = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
if (result != 0) {
- dev_err(&port->dev, "%s(): usb_submit_urb() failed"
- " with error %d\n", __func__, result);
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed with error %d\n",
+ __func__, result);
}
return;
}
@@ -333,54 +314,49 @@ static void send_data(struct work_struct *work)
port->write_urb->transfer_buffer,
count, &port->lock);
port->write_urb->transfer_buffer_length = count;
- port->write_urb->dev = port->serial->dev;
result = usb_submit_urb(port->write_urb, GFP_NOIO);
if (result != 0) {
- dev_err(&port->dev, "%s(): usb_submit_urb() failed"
- " with error %d\n", __func__, result);
+ dev_err_console(port, "%s(): usb_submit_urb() failed with error %d\n",
+ __func__, result);
priv->flags.write_urb_in_use = 0;
}
usb_serial_port_softint(port);
}
-static int oti6858_startup(struct usb_serial *serial)
+static int oti6858_port_probe(struct usb_serial_port *port)
{
- struct usb_serial_port *port = serial->port[0];
struct oti6858_private *priv;
- int i;
-
- for (i = 0; i < serial->num_ports; ++i) {
- priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL);
- if (!priv)
- break;
-
- spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->intr_wait);
-/* INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */
-/* INIT_WORK(&priv->write_work, send_data, serial->port[i]); */
- priv->port = port;
- INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
- INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
-
- usb_set_serial_port_data(serial->port[i], priv);
- }
- if (i == serial->num_ports)
- return 0;
- for (--i; i >= 0; --i) {
- priv = usb_get_serial_port_data(serial->port[i]);
- kfree(priv);
- usb_set_serial_port_data(serial->port[i], NULL);
- }
- return -ENOMEM;
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ spin_lock_init(&priv->lock);
+ priv->port = port;
+ INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
+ INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
+
+ usb_set_serial_port_data(port, priv);
+
+ port->port.drain_delay = 256; /* FIXME: check the FIFO length */
+
+ return 0;
+}
+
+static int oti6858_port_remove(struct usb_serial_port *port)
+{
+ struct oti6858_private *priv;
+
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
}
static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
- dbg("%s(port = %d, count = %d)", __func__, port->number, count);
-
if (!count)
return count;
@@ -395,8 +371,6 @@ static int oti6858_write_room(struct tty_struct *tty)
int room = 0;
unsigned long flags;
- dbg("%s(port = %d)", __func__, port->number);
-
spin_lock_irqsave(&port->lock, flags);
room = kfifo_avail(&port->write_fifo);
spin_unlock_irqrestore(&port->lock, flags);
@@ -410,8 +384,6 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty)
int chars = 0;
unsigned long flags;
- dbg("%s(port = %d)", __func__, port->number);
-
spin_lock_irqsave(&port->lock, flags);
chars = kfifo_len(&port->write_fifo);
spin_unlock_irqrestore(&port->lock, flags);
@@ -421,10 +393,10 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty)
static void oti6858_init_termios(struct tty_struct *tty)
{
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
- tty->termios->c_ispeed = 38400;
- tty->termios->c_ospeed = 38400;
+ tty->termios = tty_std_termios;
+ tty->termios.c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios.c_ispeed = 38400;
+ tty->termios.c_ospeed = 38400;
}
static void oti6858_set_termios(struct tty_struct *tty,
@@ -437,14 +409,7 @@ static void oti6858_set_termios(struct tty_struct *tty,
__le16 divisor;
int br;
- dbg("%s(port = %d)", __func__, port->number);
-
- if (!tty) {
- dbg("%s(): no tty structures", __func__);
- return;
- }
-
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
spin_lock_irqsave(&priv->lock, flags);
divisor = priv->pending_setup.divisor;
@@ -539,22 +504,17 @@ static void oti6858_set_termios(struct tty_struct *tty,
static int oti6858_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct oti6858_private *priv = usb_get_serial_port_data(port);
- struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
struct oti6858_control_pkt *buf;
unsigned long flags;
int result;
- dbg("%s(port = %d)", __func__, port->number);
-
usb_clear_halt(serial->dev, port->write_urb->pipe);
usb_clear_halt(serial->dev, port->read_urb->pipe);
buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL);
- if (buf == NULL) {
- dev_err(&port->dev, "%s(): out of memory!\n", __func__);
+ if (!buf)
return -ENOMEM;
- }
result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
OTI6858_REQ_T_GET_STATUS,
@@ -581,20 +541,19 @@ static int oti6858_open(struct tty_struct *tty, struct usb_serial_port *port)
spin_unlock_irqrestore(&priv->lock, flags);
kfree(buf);
- dbg("%s(): submitting interrupt urb", __func__);
- port->interrupt_in_urb->dev = serial->dev;
+ dev_dbg(&port->dev, "%s(): submitting interrupt urb\n", __func__);
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result != 0) {
- dev_err(&port->dev, "%s(): usb_submit_urb() failed"
- " with error %d\n", __func__, result);
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed with error %d\n",
+ __func__, result);
oti6858_close(port);
- return -EPROTO;
+ return result;
}
/* setup termios */
if (tty)
- oti6858_set_termios(tty, port, &tmp_termios);
- port->port.drain_delay = 256; /* FIXME: check the FIFO length */
+ oti6858_set_termios(tty, port, NULL);
+
return 0;
}
@@ -603,28 +562,25 @@ static void oti6858_close(struct usb_serial_port *port)
struct oti6858_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- dbg("%s(port = %d)", __func__, port->number);
-
spin_lock_irqsave(&port->lock, flags);
/* clear out any remaining data in the buffer */
kfifo_reset_out(&port->write_fifo);
spin_unlock_irqrestore(&port->lock, flags);
- dbg("%s(): after buf_clear()", __func__);
+ dev_dbg(&port->dev, "%s(): after buf_clear()\n", __func__);
/* cancel scheduled setup */
- cancel_delayed_work(&priv->delayed_setup_work);
- cancel_delayed_work(&priv->delayed_write_work);
- flush_scheduled_work();
+ cancel_delayed_work_sync(&priv->delayed_setup_work);
+ cancel_delayed_work_sync(&priv->delayed_write_work);
/* shutdown our urbs */
- dbg("%s(): shutting down urbs", __func__);
+ dev_dbg(&port->dev, "%s(): shutting down urbs\n", __func__);
usb_kill_urb(port->write_urb);
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);
}
-static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
+static int oti6858_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
@@ -632,11 +588,8 @@ static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
unsigned long flags;
u8 control;
- dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)",
- __func__, port->number, set, clear);
-
- if (!usb_get_intfdata(port->serial->interface))
- return -ENODEV;
+ dev_dbg(&port->dev, "%s(set = 0x%08x, clear = 0x%08x)\n",
+ __func__, set, clear);
/* FIXME: check if this is correct (active high/low) */
spin_lock_irqsave(&priv->lock, flags);
@@ -657,7 +610,7 @@ static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
return 0;
}
-static int oti6858_tiocmget(struct tty_struct *tty, struct file *file)
+static int oti6858_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct oti6858_private *priv = usb_get_serial_port_data(port);
@@ -665,11 +618,6 @@ static int oti6858_tiocmget(struct tty_struct *tty, struct file *file)
unsigned pin_state;
unsigned result = 0;
- dbg("%s(port = %d)", __func__, port->number);
-
- if (!usb_get_intfdata(port->serial->interface))
- return -ENODEV;
-
spin_lock_irqsave(&priv->lock, flags);
pin_state = priv->status.pin_state & PIN_MASK;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -688,76 +636,11 @@ static int oti6858_tiocmget(struct tty_struct *tty, struct file *file)
if ((pin_state & PIN_DCD) != 0)
result |= TIOCM_CD;
- dbg("%s() = 0x%08x", __func__, result);
+ dev_dbg(&port->dev, "%s() = 0x%08x\n", __func__, result);
return result;
}
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
-{
- struct oti6858_private *priv = usb_get_serial_port_data(port);
- unsigned long flags;
- unsigned int prev, status;
- unsigned int changed;
-
- spin_lock_irqsave(&priv->lock, flags);
- prev = priv->status.pin_state;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- while (1) {
- wait_event_interruptible(priv->intr_wait,
- priv->status.pin_state != prev);
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- spin_lock_irqsave(&priv->lock, flags);
- status = priv->status.pin_state & PIN_MASK;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- changed = prev ^ status;
- /* FIXME: check if this is correct (active high/low) */
- if (((arg & TIOCM_RNG) && (changed & PIN_RI)) ||
- ((arg & TIOCM_DSR) && (changed & PIN_DSR)) ||
- ((arg & TIOCM_CD) && (changed & PIN_DCD)) ||
- ((arg & TIOCM_CTS) && (changed & PIN_CTS)))
- return 0;
- prev = status;
- }
-
- /* NOTREACHED */
- return 0;
-}
-
-static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct usb_serial_port *port = tty->driver_data;
-
- dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)",
- __func__, port->number, cmd, arg);
-
- switch (cmd) {
- case TIOCMIWAIT:
- dbg("%s(): TIOCMIWAIT", __func__);
- return wait_modem_info(port, arg);
- default:
- dbg("%s(): 0x%04x not supported", __func__, cmd);
- break;
- }
- return -ENOIOCTLCMD;
-}
-
-
-static void oti6858_release(struct usb_serial *serial)
-{
- int i;
-
- dbg("%s()", __func__);
-
- for (i = 0; i < serial->num_ports; ++i)
- kfree(usb_get_serial_port_data(serial->port[i]));
-}
-
static void oti6858_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
@@ -765,9 +648,6 @@ static void oti6858_read_int_callback(struct urb *urb)
int transient = 0, can_recv = 0, resubmit = 1;
int status = urb->status;
- dbg("%s(port = %d, status = %d)",
- __func__, port->number, status);
-
switch (status) {
case 0:
/* success */
@@ -776,12 +656,12 @@ static void oti6858_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s(): urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&urb->dev->dev, "%s(): urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s(): nonzero urb status received: %d",
- __func__, status);
+ dev_dbg(&urb->dev->dev, "%s(): nonzero urb status received: %d\n",
+ __func__, status);
break;
}
@@ -797,8 +677,7 @@ static void oti6858_read_int_callback(struct urb *urb)
priv->transient = 4;
priv->setup_done = 0;
resubmit = 0;
- dbg("%s(): scheduling setup_line()",
- __func__);
+ dev_dbg(&port->dev, "%s(): scheduling setup_line()\n", __func__);
schedule_delayed_work(&priv->delayed_setup_work, 0);
}
}
@@ -812,16 +691,28 @@ static void oti6858_read_int_callback(struct urb *urb)
priv->transient = 4;
priv->setup_done = 0;
resubmit = 0;
- dbg("%s(): scheduling setup_line()",
- __func__);
+ dev_dbg(&port->dev, "%s(): scheduling setup_line()\n", __func__);
schedule_delayed_work(&priv->delayed_setup_work, 0);
}
}
}
if (!priv->transient) {
- if (xs->pin_state != priv->status.pin_state)
- wake_up_interruptible(&priv->intr_wait);
+ u8 delta = xs->pin_state ^ priv->status.pin_state;
+
+ if (delta & PIN_MSR_MASK) {
+ if (delta & PIN_CTS)
+ port->icount.cts++;
+ if (delta & PIN_DSR)
+ port->icount.dsr++;
+ if (delta & PIN_RI)
+ port->icount.rng++;
+ if (delta & PIN_DCD)
+ port->icount.dcd++;
+
+ wake_up_interruptible(&port->port.delta_msr_wait);
+ }
+
memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);
}
@@ -837,7 +728,6 @@ static void oti6858_read_int_callback(struct urb *urb)
if (can_recv) {
int result;
- port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result != 0) {
priv->flags.read_urb_in_use = 0;
@@ -865,8 +755,7 @@ static void oti6858_read_int_callback(struct urb *urb)
if (resubmit) {
int result;
-/* dbg("%s(): submitting interrupt urb", __func__); */
- urb->dev = port->serial->dev;
+/* dev_dbg(&urb->dev->dev, "%s(): submitting interrupt urb\n", __func__); */
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result != 0) {
dev_err(&urb->dev->dev,
@@ -880,45 +769,26 @@ static void oti6858_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct oti6858_private *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
unsigned long flags;
int status = urb->status;
int result;
- dbg("%s(port = %d, status = %d)",
- __func__, port->number, status);
-
spin_lock_irqsave(&priv->lock, flags);
priv->flags.read_urb_in_use = 0;
spin_unlock_irqrestore(&priv->lock, flags);
if (status != 0) {
- /*
- if (status == -EPROTO) {
- * PL2303 mysteriously fails with -EPROTO reschedule
- the read *
- dbg("%s - caught -EPROTO, resubmitting the urb",
- __func__);
- result = usb_submit_urb(urb, GFP_ATOMIC);
- if (result)
- dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
- return;
- }
- */
- dbg("%s(): unable to handle the error, exiting", __func__);
+ dev_dbg(&urb->dev->dev, "%s(): unable to handle the error, exiting\n", __func__);
return;
}
- tty = tty_port_tty_get(&port->port);
- if (tty != NULL && urb->actual_length > 0) {
- tty_insert_flip_string(tty, data, urb->actual_length);
- tty_flip_buffer_push(tty);
+ if (urb->actual_length > 0) {
+ tty_insert_flip_string(&port->port, data, urb->actual_length);
+ tty_flip_buffer_push(&port->port);
}
- tty_kref_put(tty);
/* schedule the interrupt urb */
- port->interrupt_in_urb->dev = port->serial->dev;
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result != 0 && result != -EPERM) {
dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
@@ -933,9 +803,6 @@ static void oti6858_write_bulk_callback(struct urb *urb)
int status = urb->status;
int result;
- dbg("%s(port = %d, status = %d)",
- __func__, port->number, status);
-
switch (status) {
case 0:
/* success */
@@ -944,21 +811,18 @@ static void oti6858_write_bulk_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s(): urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&urb->dev->dev, "%s(): urb shutting down with status: %d\n", __func__, status);
priv->flags.write_urb_in_use = 0;
return;
default:
/* error in the urb, so we have to resubmit it */
- dbg("%s(): nonzero write bulk status received: %d",
- __func__, status);
- dbg("%s(): overflow in write", __func__);
+ dev_dbg(&urb->dev->dev, "%s(): nonzero write bulk status received: %d\n", __func__, status);
+ dev_dbg(&urb->dev->dev, "%s(): overflow in write\n", __func__);
port->write_urb->transfer_buffer_length = 1;
- port->write_urb->dev = port->serial->dev;
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+ dev_err_console(port, "%s(): usb_submit_urb() failed,"
" error %d\n", __func__, result);
} else {
return;
@@ -968,8 +832,7 @@ static void oti6858_write_bulk_callback(struct urb *urb)
priv->flags.write_urb_in_use = 0;
/* schedule the interrupt urb if we are still open */
- port->interrupt_in_urb->dev = port->serial->dev;
- dbg("%s(): submitting interrupt urb", __func__);
+ dev_dbg(&port->dev, "%s(): submitting interrupt urb\n", __func__);
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result != 0) {
dev_err(&port->dev, "%s(): failed submitting int urb,"
@@ -977,35 +840,8 @@ static void oti6858_write_bulk_callback(struct urb *urb)
}
}
-/* module description and (de)initialization */
-
-static int __init oti6858_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&oti6858_device);
- if (retval == 0) {
- retval = usb_register(&oti6858_driver);
- if (retval)
- usb_serial_deregister(&oti6858_device);
- }
- return retval;
-}
-
-static void __exit oti6858_exit(void)
-{
- usb_deregister(&oti6858_driver);
- usb_serial_deregister(&oti6858_device);
-}
-
-module_init(oti6858_init);
-module_exit(oti6858_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(OTI6858_DESCRIPTION);
MODULE_AUTHOR(OTI6858_AUTHOR);
-MODULE_VERSION(OTI6858_VERSION);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "enable debug output");
-
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 8ae4c6cbc38..b3d5a35c0d4 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -12,12 +12,10 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this
* driver
- *
*/
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -29,16 +27,12 @@
#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
+#include <asm/unaligned.h>
#include "pl2303.h"
-/*
- * Version Information
- */
-#define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver"
-
-static int debug;
-#define PL2303_CLOSING_WAIT (30*HZ)
+#define PL2303_QUIRK_UART_STATE_IDX0 BIT(0)
+#define PL2303_QUIRK_LEGACY BIT(1)
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) },
@@ -50,6 +44,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) },
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
@@ -66,9 +61,12 @@ static const 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(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) },
- { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
- { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) },
+ { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1),
+ .driver_info = PL2303_QUIRK_UART_STATE_IDX0 },
+ { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65),
+ .driver_info = PL2303_QUIRK_UART_STATE_IDX0 },
+ { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75),
+ .driver_info = PL2303_QUIRK_UART_STATE_IDX0 },
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) },
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_ID_S81) }, /* Benq/Siemens S81 */
{ USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
@@ -85,27 +83,20 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
{ USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_LD960_PRODUCT_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) },
{ USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
{ USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
{ USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
{ USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) },
+ { USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver pl2303_driver = {
- .name = "pl2303",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .no_dynamic_id = 1,
- .supports_autosuspend = 1,
-};
-
#define SET_LINE_REQUEST_TYPE 0x21
#define SET_LINE_REQUEST 0x20
@@ -128,7 +119,8 @@ static struct usb_driver pl2303_driver = {
#define VENDOR_READ_REQUEST_TYPE 0xc0
#define VENDOR_READ_REQUEST 0x01
-#define UART_STATE 0x08
+#define UART_STATE_INDEX 8
+#define UART_STATE_MSR_MASK 0x8b
#define UART_STATE_TRANSIENT_MASK 0x74
#define UART_DCD 0x01
#define UART_DSR 0x02
@@ -141,300 +133,462 @@ static struct usb_driver pl2303_driver = {
enum pl2303_type {
- type_0, /* don't know the difference between type 0 and */
- type_1, /* type 1, until someone from prolific tells us... */
- HX, /* HX version of the pl2303 chip */
+ TYPE_01, /* Type 0 and 1 (difference unknown) */
+ TYPE_HX, /* HX version of the pl2303 chip */
+ TYPE_COUNT
+};
+
+struct pl2303_type_data {
+ speed_t max_baud_rate;
+ unsigned long quirks;
+};
+
+struct pl2303_serial_private {
+ const struct pl2303_type_data *type;
+ unsigned long quirks;
};
struct pl2303_private {
spinlock_t lock;
- wait_queue_head_t delta_msr_wait;
u8 line_control;
u8 line_status;
- enum pl2303_type type;
+
+ u8 line_settings[7];
};
-static int pl2303_vendor_read(__u16 value, __u16 index,
- struct usb_serial *serial, unsigned char *buf)
+static const struct pl2303_type_data pl2303_type_data[TYPE_COUNT] = {
+ [TYPE_01] = {
+ .max_baud_rate = 1228800,
+ .quirks = PL2303_QUIRK_LEGACY,
+ },
+};
+
+static int pl2303_vendor_read(struct usb_serial *serial, u16 value,
+ unsigned char buf[1])
{
- int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ struct device *dev = &serial->interface->dev;
+ int res;
+
+ res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE,
- value, index, buf, 1, 100);
- dbg("0x%x:0x%x:0x%x:0x%x %d - %x", VENDOR_READ_REQUEST_TYPE,
- VENDOR_READ_REQUEST, value, index, res, buf[0]);
- return res;
+ value, 0, buf, 1, 100);
+ if (res != 1) {
+ dev_err(dev, "%s - failed to read [%04x]: %d\n", __func__,
+ value, res);
+ if (res >= 0)
+ res = -EIO;
+
+ return res;
+ }
+
+ dev_dbg(dev, "%s - [%04x] = %02x\n", __func__, value, buf[0]);
+
+ return 0;
}
-static int pl2303_vendor_write(__u16 value, __u16 index,
- struct usb_serial *serial)
+static int pl2303_vendor_write(struct usb_serial *serial, u16 value, u16 index)
{
- int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ struct device *dev = &serial->interface->dev;
+ int res;
+
+ dev_dbg(dev, "%s - [%04x] = %02x\n", __func__, value, index);
+
+ res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE,
value, index, NULL, 0, 100);
- dbg("0x%x:0x%x:0x%x:0x%x %d", VENDOR_WRITE_REQUEST_TYPE,
- VENDOR_WRITE_REQUEST, value, index, res);
- return res;
+ if (res) {
+ dev_err(dev, "%s - failed to write [%04x]: %d\n", __func__,
+ value, res);
+ return res;
+ }
+
+ return 0;
+}
+
+static int pl2303_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
+{
+ usb_set_serial_data(serial, (void *)id->driver_info);
+
+ return 0;
}
static int pl2303_startup(struct usb_serial *serial)
{
- struct pl2303_private *priv;
- enum pl2303_type type = type_0;
+ struct pl2303_serial_private *spriv;
+ enum pl2303_type type = TYPE_01;
unsigned char *buf;
- int i;
- buf = kmalloc(10, GFP_KERNEL);
- if (buf == NULL)
+ spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
+ if (!spriv)
+ return -ENOMEM;
+
+ buf = kmalloc(1, GFP_KERNEL);
+ if (!buf) {
+ kfree(spriv);
return -ENOMEM;
+ }
if (serial->dev->descriptor.bDeviceClass == 0x02)
- type = type_0;
+ type = TYPE_01; /* type 0 */
else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
- type = HX;
+ type = TYPE_HX;
else if (serial->dev->descriptor.bDeviceClass == 0x00)
- type = type_1;
+ type = TYPE_01; /* type 1 */
else if (serial->dev->descriptor.bDeviceClass == 0xFF)
- type = type_1;
- dbg("device type: %d", type);
-
- for (i = 0; i < serial->num_ports; ++i) {
- priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL);
- if (!priv)
- goto cleanup;
- spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
- priv->type = type;
- usb_set_serial_port_data(serial->port[i], priv);
- }
-
- pl2303_vendor_read(0x8484, 0, serial, buf);
- pl2303_vendor_write(0x0404, 0, serial);
- pl2303_vendor_read(0x8484, 0, serial, buf);
- pl2303_vendor_read(0x8383, 0, serial, buf);
- pl2303_vendor_read(0x8484, 0, serial, buf);
- pl2303_vendor_write(0x0404, 1, serial);
- pl2303_vendor_read(0x8484, 0, serial, buf);
- pl2303_vendor_read(0x8383, 0, serial, buf);
- pl2303_vendor_write(0, 1, serial);
- pl2303_vendor_write(1, 0, serial);
- if (type == HX)
- pl2303_vendor_write(2, 0x44, serial);
+ type = TYPE_01; /* type 1 */
+ dev_dbg(&serial->interface->dev, "device type: %d\n", type);
+
+ spriv->type = &pl2303_type_data[type];
+ spriv->quirks = (unsigned long)usb_get_serial_data(serial);
+ spriv->quirks |= spriv->type->quirks;
+
+ usb_set_serial_data(serial, spriv);
+
+ pl2303_vendor_read(serial, 0x8484, buf);
+ pl2303_vendor_write(serial, 0x0404, 0);
+ pl2303_vendor_read(serial, 0x8484, buf);
+ pl2303_vendor_read(serial, 0x8383, buf);
+ pl2303_vendor_read(serial, 0x8484, buf);
+ pl2303_vendor_write(serial, 0x0404, 1);
+ pl2303_vendor_read(serial, 0x8484, buf);
+ pl2303_vendor_read(serial, 0x8383, buf);
+ pl2303_vendor_write(serial, 0, 1);
+ pl2303_vendor_write(serial, 1, 0);
+ if (spriv->quirks & PL2303_QUIRK_LEGACY)
+ pl2303_vendor_write(serial, 2, 0x24);
else
- pl2303_vendor_write(2, 0x24, serial);
+ pl2303_vendor_write(serial, 2, 0x44);
kfree(buf);
+
return 0;
+}
-cleanup:
- kfree(buf);
- for (--i; i >= 0; --i) {
- priv = usb_get_serial_port_data(serial->port[i]);
- kfree(priv);
- usb_set_serial_port_data(serial->port[i], NULL);
- }
- return -ENOMEM;
+static void pl2303_release(struct usb_serial *serial)
+{
+ struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
+
+ kfree(spriv);
}
-static int set_control_lines(struct usb_device *dev, u8 value)
+static int pl2303_port_probe(struct usb_serial_port *port)
{
+ struct pl2303_private *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ spin_lock_init(&priv->lock);
+
+ usb_set_serial_port_data(port, priv);
+
+ port->port.drain_delay = 256;
+
+ return 0;
+}
+
+static int pl2303_port_remove(struct usb_serial_port *port)
+{
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+
+ kfree(priv);
+
+ return 0;
+}
+
+static int pl2303_set_control_lines(struct usb_serial_port *port, u8 value)
+{
+ struct usb_device *dev = port->serial->dev;
int retval;
+ dev_dbg(&port->dev, "%s - %02x\n", __func__, value);
+
retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
value, 0, NULL, 0, 100);
- dbg("%s - value = %d, retval = %d", __func__, value, retval);
+ if (retval)
+ dev_err(&port->dev, "%s - failed: %d\n", __func__, retval);
+
return retval;
}
+/*
+ * Returns the nearest supported baud rate that can be set directly without
+ * using divisors.
+ */
+static speed_t pl2303_get_supported_baud_rate(speed_t baud)
+{
+ static const speed_t baud_sup[] = {
+ 75, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600,
+ 14400, 19200, 28800, 38400, 57600, 115200, 230400, 460800,
+ 614400, 921600, 1228800, 2457600, 3000000, 6000000
+ };
+
+ unsigned i;
+
+ for (i = 0; i < ARRAY_SIZE(baud_sup); ++i) {
+ if (baud_sup[i] > baud)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(baud_sup))
+ baud = baud_sup[i - 1];
+ else if (i > 0 && (baud_sup[i] - baud) > (baud - baud_sup[i - 1]))
+ baud = baud_sup[i - 1];
+ else
+ baud = baud_sup[i];
+
+ return baud;
+}
+
+/*
+ * NOTE: If unsupported baud rates are set directly, the PL2303 seems to
+ * use 9600 baud.
+ */
+static speed_t pl2303_encode_baud_rate_direct(unsigned char buf[4],
+ speed_t baud)
+{
+ put_unaligned_le32(baud, buf);
+
+ return baud;
+}
+
+static speed_t pl2303_encode_baud_rate_divisor(unsigned char buf[4],
+ speed_t baud)
+{
+ unsigned int tmp;
+
+ /*
+ * Apparently the formula is:
+ * baudrate = 12M * 32 / (2^buf[1]) / buf[0]
+ */
+ tmp = 12000000 * 32 / baud;
+ buf[3] = 0x80;
+ buf[2] = 0;
+ buf[1] = (tmp >= 256);
+ while (tmp >= 256) {
+ tmp >>= 2;
+ buf[1] <<= 1;
+ }
+ buf[0] = tmp;
+
+ return baud;
+}
+
+static void pl2303_encode_baud_rate(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ u8 buf[4])
+{
+ struct usb_serial *serial = port->serial;
+ struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
+ speed_t baud_sup;
+ speed_t baud;
+
+ baud = tty_get_baud_rate(tty);
+ dev_dbg(&port->dev, "baud requested = %u\n", baud);
+ if (!baud)
+ return;
+
+ if (spriv->type->max_baud_rate)
+ baud = min_t(speed_t, baud, spriv->type->max_baud_rate);
+ /*
+ * Set baud rate to nearest supported value.
+ *
+ * NOTE: Baud rate 500k can only be set using divisors.
+ */
+ baud_sup = pl2303_get_supported_baud_rate(baud);
+
+ if (baud == 500000)
+ baud = pl2303_encode_baud_rate_divisor(buf, baud);
+ else
+ baud = pl2303_encode_baud_rate_direct(buf, baud_sup);
+
+ /* Save resulting baud rate */
+ tty_encode_baud_rate(tty, baud, baud);
+ dev_dbg(&port->dev, "baud set = %u\n", baud);
+}
+
+static int pl2303_get_line_request(struct usb_serial_port *port,
+ unsigned char buf[7])
+{
+ struct usb_device *udev = port->serial->dev;
+ int ret;
+
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
+ 0, 0, buf, 7, 100);
+ if (ret != 7) {
+ dev_err(&port->dev, "%s - failed: %d\n", __func__, ret);
+
+ if (ret > 0)
+ ret = -EIO;
+
+ return ret;
+ }
+
+ dev_dbg(&port->dev, "%s - %7ph\n", __func__, buf);
+
+ return 0;
+}
+
+static int pl2303_set_line_request(struct usb_serial_port *port,
+ unsigned char buf[7])
+{
+ struct usb_device *udev = port->serial->dev;
+ int ret;
+
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE,
+ 0, 0, buf, 7, 100);
+ if (ret != 7) {
+ dev_err(&port->dev, "%s - failed: %d\n", __func__, ret);
+
+ if (ret > 0)
+ ret = -EIO;
+
+ return ret;
+ }
+
+ dev_dbg(&port->dev, "%s - %7ph\n", __func__, buf);
+
+ return 0;
+}
+
static void pl2303_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
+ struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- unsigned int cflag;
unsigned char *buf;
- int baud;
- int i;
+ int ret;
u8 control;
- const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600,
- 4800, 7200, 9600, 14400, 19200, 28800, 38400,
- 57600, 115200, 230400, 460800, 614400,
- 921600, 1228800, 2457600, 3000000, 6000000 };
- int baud_floor, baud_ceil;
- int k;
-
- dbg("%s - port %d", __func__, port->number);
-
- /* The PL2303 is reported to lose bytes if you change
- serial settings even to the same values as before. Thus
- we actually need to filter in this specific case */
- if (!tty_termios_hw_change(tty->termios, old_termios))
+ if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios))
return;
- cflag = tty->termios->c_cflag;
-
buf = kzalloc(7, GFP_KERNEL);
if (!buf) {
- dev_err(&port->dev, "%s - out of memory.\n", __func__);
/* Report back no change occurred */
- *tty->termios = *old_termios;
+ if (old_termios)
+ tty->termios = *old_termios;
return;
}
- i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
- GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
- 0, 0, buf, 7, 100);
- dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i,
- buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+ pl2303_get_line_request(port, buf);
- if (cflag & CSIZE) {
- switch (cflag & CSIZE) {
- case CS5:
- buf[6] = 5;
- break;
- case CS6:
- buf[6] = 6;
- break;
- case CS7:
- buf[6] = 7;
- break;
- default:
- case CS8:
- buf[6] = 8;
- break;
- }
- dbg("%s - data bits = %d", __func__, buf[6]);
+ switch (C_CSIZE(tty)) {
+ case CS5:
+ buf[6] = 5;
+ break;
+ case CS6:
+ buf[6] = 6;
+ break;
+ case CS7:
+ buf[6] = 7;
+ break;
+ default:
+ case CS8:
+ buf[6] = 8;
}
+ dev_dbg(&port->dev, "data bits = %d\n", buf[6]);
/* For reference buf[0]:buf[3] baud rate value */
- /* NOTE: Only the values defined in baud_sup are supported !
- * => if unsupported values are set, the PL2303 seems to use
- * 9600 baud (at least my PL2303X always does)
- */
- baud = tty_get_baud_rate(tty);
- dbg("%s - baud requested = %d", __func__, baud);
- if (baud) {
- /* Set baudrate to nearest supported value */
- for (k=0; k<ARRAY_SIZE(baud_sup); k++) {
- if (baud_sup[k] / baud) {
- baud_ceil = baud_sup[k];
- if (k==0) {
- baud = baud_ceil;
- } else {
- baud_floor = baud_sup[k-1];
- if ((baud_ceil % baud)
- > (baud % baud_floor))
- baud = baud_floor;
- else
- baud = baud_ceil;
- }
- break;
- }
- }
- if (baud > 1228800) {
- /* type_0, type_1 only support up to 1228800 baud */
- if (priv->type != HX)
- baud = 1228800;
- else if (baud > 6000000)
- baud = 6000000;
- }
- dbg("%s - baud set = %d", __func__, baud);
- buf[0] = baud & 0xff;
- buf[1] = (baud >> 8) & 0xff;
- buf[2] = (baud >> 16) & 0xff;
- buf[3] = (baud >> 24) & 0xff;
- }
+ pl2303_encode_baud_rate(tty, port, &buf[0]);
/* For reference buf[4]=0 is 1 stop bits */
/* For reference buf[4]=1 is 1.5 stop bits */
/* For reference buf[4]=2 is 2 stop bits */
- if (cflag & CSTOPB) {
- /* NOTE: Comply with "real" UARTs / RS232:
+ if (C_CSTOPB(tty)) {
+ /*
+ * NOTE: Comply with "real" UARTs / RS232:
* use 1.5 instead of 2 stop bits with 5 data bits
*/
- if ((cflag & CSIZE) == CS5) {
+ if (C_CSIZE(tty) == CS5) {
buf[4] = 1;
- dbg("%s - stop bits = 1.5", __func__);
+ dev_dbg(&port->dev, "stop bits = 1.5\n");
} else {
buf[4] = 2;
- dbg("%s - stop bits = 2", __func__);
+ dev_dbg(&port->dev, "stop bits = 2\n");
}
} else {
buf[4] = 0;
- dbg("%s - stop bits = 1", __func__);
+ dev_dbg(&port->dev, "stop bits = 1\n");
}
- if (cflag & PARENB) {
+ if (C_PARENB(tty)) {
/* For reference buf[5]=0 is none parity */
/* For reference buf[5]=1 is odd parity */
/* For reference buf[5]=2 is even parity */
/* For reference buf[5]=3 is mark parity */
/* For reference buf[5]=4 is space parity */
- if (cflag & PARODD) {
- if (cflag & CMSPAR) {
+ if (C_PARODD(tty)) {
+ if (C_CMSPAR(tty)) {
buf[5] = 3;
- dbg("%s - parity = mark", __func__);
+ dev_dbg(&port->dev, "parity = mark\n");
} else {
buf[5] = 1;
- dbg("%s - parity = odd", __func__);
+ dev_dbg(&port->dev, "parity = odd\n");
}
} else {
- if (cflag & CMSPAR) {
+ if (C_CMSPAR(tty)) {
buf[5] = 4;
- dbg("%s - parity = space", __func__);
+ dev_dbg(&port->dev, "parity = space\n");
} else {
buf[5] = 2;
- dbg("%s - parity = even", __func__);
+ dev_dbg(&port->dev, "parity = even\n");
}
}
} else {
buf[5] = 0;
- dbg("%s - parity = none", __func__);
+ dev_dbg(&port->dev, "parity = none\n");
}
- i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE,
- 0, 0, buf, 7, 100);
- dbg("0x21:0x20:0:0 %d", i);
+ /*
+ * Some PL2303 are known to lose bytes if you change serial settings
+ * even to the same values as before. Thus we actually need to filter
+ * in this specific case.
+ *
+ * Note that the tty_termios_hw_change check above is not sufficient
+ * as a previously requested baud rate may differ from the one
+ * actually used (and stored in old_termios).
+ *
+ * NOTE: No additional locking needed for line_settings as it is
+ * only used in set_termios, which is serialised against itself.
+ */
+ if (!old_termios || memcmp(buf, priv->line_settings, 7)) {
+ ret = pl2303_set_line_request(port, buf);
+ if (!ret)
+ memcpy(priv->line_settings, buf, 7);
+ }
/* change control lines if we are switching to or from B0 */
spin_lock_irqsave(&priv->lock, flags);
control = priv->line_control;
- if ((cflag & CBAUD) == B0)
+ if (C_BAUD(tty) == B0)
priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
- else
+ else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
if (control != priv->line_control) {
control = priv->line_control;
spin_unlock_irqrestore(&priv->lock, flags);
- set_control_lines(serial->dev, control);
+ pl2303_set_control_lines(port, control);
} else {
spin_unlock_irqrestore(&priv->lock, flags);
}
- buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
-
- i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
- GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
- 0, 0, buf, 7, 100);
- dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i,
- buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
-
- if (cflag & CRTSCTS) {
- if (priv->type == HX)
- pl2303_vendor_write(0x0, 0x61, serial);
+ if (C_CRTSCTS(tty)) {
+ if (spriv->quirks & PL2303_QUIRK_LEGACY)
+ pl2303_vendor_write(serial, 0x0, 0x41);
else
- pl2303_vendor_write(0x0, 0x41, serial);
+ pl2303_vendor_write(serial, 0x0, 0x61);
} else {
- pl2303_vendor_write(0x0, 0x0, serial);
+ pl2303_vendor_write(serial, 0x0, 0x0);
}
- /* Save resulting baud rate */
- if (baud)
- tty_encode_baud_rate(tty, baud, baud);
-
kfree(buf);
}
@@ -445,75 +599,65 @@ static void pl2303_dtr_rts(struct usb_serial_port *port, int on)
u8 control;
spin_lock_irqsave(&priv->lock, flags);
- /* Change DTR and RTS */
if (on)
priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
else
priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
control = priv->line_control;
spin_unlock_irqrestore(&priv->lock, flags);
- set_control_lines(port->serial->dev, control);
+
+ pl2303_set_control_lines(port, control);
}
static void pl2303_close(struct usb_serial_port *port)
{
- dbg("%s - port %d", __func__, port->number);
-
usb_serial_generic_close(port);
usb_kill_urb(port->interrupt_in_urb);
}
static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
{
- struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
- struct pl2303_private *priv = usb_get_serial_port_data(port);
+ struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
int result;
- dbg("%s - port %d", __func__, port->number);
-
- if (priv->type != HX) {
+ if (spriv->quirks & PL2303_QUIRK_LEGACY) {
usb_clear_halt(serial->dev, port->write_urb->pipe);
usb_clear_halt(serial->dev, port->read_urb->pipe);
} else {
/* reset upstream data pipes */
- pl2303_vendor_write(8, 0, serial);
- pl2303_vendor_write(9, 0, serial);
+ pl2303_vendor_write(serial, 8, 0);
+ pl2303_vendor_write(serial, 9, 0);
}
/* Setup termios */
if (tty)
- pl2303_set_termios(tty, port, &tmp_termios);
+ pl2303_set_termios(tty, port, NULL);
- dbg("%s - submitting read urb", __func__);
- result = usb_serial_generic_submit_read_urb(port, GFP_KERNEL);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result) {
- pl2303_close(port);
- return -EPROTO;
+ dev_err(&port->dev, "failed to submit interrupt urb: %d\n",
+ result);
+ return result;
}
- dbg("%s - submitting interrupt urb", __func__);
- result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ result = usb_serial_generic_open(tty, port);
if (result) {
- dev_err(&port->dev, "%s - failed submitting interrupt urb,"
- " error %d\n", __func__, result);
- pl2303_close(port);
- return -EPROTO;
+ usb_kill_urb(port->interrupt_in_urb);
+ return result;
}
- port->port.drain_delay = 256;
+
return 0;
}
-static int pl2303_tiocmset(struct tty_struct *tty, struct file *file,
+static int pl2303_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 control;
-
- if (!usb_get_intfdata(port->serial->interface))
- return -ENODEV;
+ int ret;
spin_lock_irqsave(&priv->lock, flags);
if (set & TIOCM_RTS)
@@ -527,10 +671,14 @@ static int pl2303_tiocmset(struct tty_struct *tty, struct file *file,
control = priv->line_control;
spin_unlock_irqrestore(&priv->lock, flags);
- return set_control_lines(port->serial->dev, control);
+ ret = pl2303_set_control_lines(port, control);
+ if (ret)
+ return usb_translate_errors(ret);
+
+ return 0;
}
-static int pl2303_tiocmget(struct tty_struct *tty, struct file *file)
+static int pl2303_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -539,11 +687,6 @@ static int pl2303_tiocmget(struct tty_struct *tty, struct file *file)
unsigned int status;
unsigned int result;
- dbg("%s (%d)", __func__, port->number);
-
- if (!usb_get_intfdata(port->serial->interface))
- return -ENODEV;
-
spin_lock_irqsave(&priv->lock, flags);
mcr = priv->line_control;
status = priv->line_status;
@@ -556,7 +699,7 @@ static int pl2303_tiocmget(struct tty_struct *tty, struct file *file)
| ((status & UART_RING) ? TIOCM_RI : 0)
| ((status & UART_DCD) ? TIOCM_CD : 0);
- dbg("%s - result = %x", __func__, result);
+ dev_dbg(&port->dev, "%s - result = %x\n", __func__, result);
return result;
}
@@ -564,74 +707,35 @@ static int pl2303_tiocmget(struct tty_struct *tty, struct file *file)
static int pl2303_carrier_raised(struct usb_serial_port *port)
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
+
if (priv->line_status & UART_DCD)
return 1;
- return 0;
-}
-
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
-{
- struct pl2303_private *priv = usb_get_serial_port_data(port);
- unsigned long flags;
- unsigned int prevstatus;
- unsigned int status;
- unsigned int changed;
-
- spin_lock_irqsave(&priv->lock, flags);
- prevstatus = priv->line_status;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- while (1) {
- interruptible_sleep_on(&priv->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- spin_lock_irqsave(&priv->lock, flags);
- status = priv->line_status;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- changed = prevstatus ^ status;
- if (((arg & TIOCM_RNG) && (changed & UART_RING)) ||
- ((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
- ((arg & TIOCM_CD) && (changed & UART_DCD)) ||
- ((arg & TIOCM_CTS) && (changed & UART_CTS))) {
- return 0;
- }
- prevstatus = status;
- }
- /* NOTREACHED */
return 0;
}
-static int pl2303_ioctl(struct tty_struct *tty, struct file *file,
+static int pl2303_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct serial_struct ser;
struct usb_serial_port *port = tty->driver_data;
- dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
switch (cmd) {
case TIOCGSERIAL:
memset(&ser, 0, sizeof ser);
ser.type = PORT_16654;
- ser.line = port->serial->minor;
- ser.port = port->number;
+ ser.line = port->minor;
+ ser.port = port->port_number;
ser.baud_base = 460800;
if (copy_to_user((void __user *)arg, &ser, sizeof ser))
return -EFAULT;
return 0;
-
- case TIOCMIWAIT:
- dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
- return wait_modem_info(port, arg);
default:
- dbg("%s not supported = 0x%04x", __func__, cmd);
break;
}
+
return -ENOIOCTLCMD;
}
@@ -642,70 +746,70 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
u16 state;
int result;
- dbg("%s - port %d", __func__, port->number);
-
if (break_state == 0)
state = BREAK_OFF;
else
state = BREAK_ON;
- dbg("%s - turning break %s", __func__,
+
+ dev_dbg(&port->dev, "%s - turning break %s\n", __func__,
state == BREAK_OFF ? "off" : "on");
result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
0, NULL, 0, 100);
if (result)
- dbg("%s - error sending break = %d", __func__, result);
-}
-
-static void pl2303_release(struct usb_serial *serial)
-{
- int i;
- struct pl2303_private *priv;
-
- dbg("%s", __func__);
-
- for (i = 0; i < serial->num_ports; ++i) {
- priv = usb_get_serial_port_data(serial->port[i]);
- kfree(priv);
- }
+ dev_err(&port->dev, "error sending break = %d\n", result);
}
static void pl2303_update_line_status(struct usb_serial_port *port,
unsigned char *data,
unsigned int actual_length)
{
-
+ struct usb_serial *serial = port->serial;
+ struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
struct pl2303_private *priv = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
unsigned long flags;
- u8 status_idx = UART_STATE;
- u8 length = UART_STATE + 1;
- u16 idv, idp;
-
- idv = le16_to_cpu(port->serial->dev->descriptor.idVendor);
- idp = le16_to_cpu(port->serial->dev->descriptor.idProduct);
-
+ unsigned int status_idx = UART_STATE_INDEX;
+ u8 status;
+ u8 delta;
- if (idv == SIEMENS_VENDOR_ID) {
- if (idp == SIEMENS_PRODUCT_ID_X65 ||
- idp == SIEMENS_PRODUCT_ID_SX1 ||
- idp == SIEMENS_PRODUCT_ID_X75) {
-
- length = 1;
- status_idx = 0;
- }
- }
+ if (spriv->quirks & PL2303_QUIRK_UART_STATE_IDX0)
+ status_idx = 0;
- if (actual_length < length)
+ if (actual_length < status_idx + 1)
return;
+ status = data[status_idx];
+
/* Save off the uart status for others to look at */
spin_lock_irqsave(&priv->lock, flags);
- priv->line_status = data[status_idx];
+ delta = priv->line_status ^ status;
+ priv->line_status = status;
spin_unlock_irqrestore(&priv->lock, flags);
- if (priv->line_status & UART_BREAK_ERROR)
+
+ if (status & UART_BREAK_ERROR)
usb_serial_handle_break(port);
- wake_up_interruptible(&priv->delta_msr_wait);
+
+ if (delta & UART_STATE_MSR_MASK) {
+ if (delta & UART_CTS)
+ port->icount.cts++;
+ if (delta & UART_DSR)
+ port->icount.dsr++;
+ if (delta & UART_RING)
+ port->icount.rng++;
+ if (delta & UART_DCD) {
+ port->icount.dcd++;
+ tty = tty_port_tty_get(&port->port);
+ if (tty) {
+ usb_serial_handle_dcd_change(port, tty,
+ status & UART_DCD);
+ tty_kref_put(tty);
+ }
+ }
+
+ wake_up_interruptible(&port->port.delta_msr_wait);
+ }
}
static void pl2303_read_int_callback(struct urb *urb)
@@ -716,8 +820,6 @@ static void pl2303_read_int_callback(struct urb *urb)
int status = urb->status;
int retval;
- dbg("%s (%d)", __func__, port->number);
-
switch (status) {
case 0:
/* success */
@@ -726,33 +828,33 @@ static void pl2303_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__,
- status);
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __func__,
- status);
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
goto exit;
}
- usb_serial_debug_data(debug, &port->dev, __func__,
+ usb_serial_debug_data(&port->dev, __func__,
urb->actual_length, urb->transfer_buffer);
pl2303_update_line_status(port, data, actual_length);
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
- if (retval)
- dev_err(&urb->dev->dev,
+ if (retval) {
+ dev_err(&port->dev,
"%s - usb_submit_urb failed with result %d\n",
__func__, retval);
+ }
}
static void pl2303_process_read_urb(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct pl2303_private *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
char tty_flag = TTY_NORMAL;
unsigned long flags;
@@ -764,98 +866,74 @@ static void pl2303_process_read_urb(struct urb *urb)
line_status = priv->line_status;
priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
spin_unlock_irqrestore(&priv->lock, flags);
- wake_up_interruptible(&priv->delta_msr_wait);
if (!urb->actual_length)
return;
- tty = tty_port_tty_get(&port->port);
- if (!tty)
- return;
-
- /* break takes precedence over parity, */
- /* which takes precedence over framing errors */
+ /*
+ * Break takes precedence over parity, which takes precedence over
+ * framing errors.
+ */
if (line_status & UART_BREAK_ERROR)
tty_flag = TTY_BREAK;
else if (line_status & UART_PARITY_ERROR)
tty_flag = TTY_PARITY;
else if (line_status & UART_FRAME_ERROR)
tty_flag = TTY_FRAME;
- dbg("%s - tty_flag = %d", __func__, tty_flag);
+ if (tty_flag != TTY_NORMAL)
+ dev_dbg(&port->dev, "%s - tty_flag = %d\n", __func__,
+ tty_flag);
/* overrun is special, not associated with a char */
if (line_status & UART_OVERRUN_ERROR)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
if (port->port.console && port->sysrq) {
for (i = 0; i < urb->actual_length; ++i)
if (!usb_serial_handle_sysrq_char(port, data[i]))
- tty_insert_flip_char(tty, data[i], tty_flag);
+ tty_insert_flip_char(&port->port, data[i],
+ tty_flag);
} else {
- tty_insert_flip_string_fixed_flag(tty, data, tty_flag,
+ tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag,
urb->actual_length);
}
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
+ tty_flip_buffer_push(&port->port);
}
-/* All of the device info needed for the PL2303 SIO serial converter */
static struct usb_serial_driver pl2303_device = {
.driver = {
.owner = THIS_MODULE,
.name = "pl2303",
},
.id_table = id_table,
- .usb_driver = &pl2303_driver,
.num_ports = 1,
.bulk_in_size = 256,
.bulk_out_size = 256,
.open = pl2303_open,
.close = pl2303_close,
- .dtr_rts = pl2303_dtr_rts,
+ .dtr_rts = pl2303_dtr_rts,
.carrier_raised = pl2303_carrier_raised,
.ioctl = pl2303_ioctl,
.break_ctl = pl2303_break_ctl,
.set_termios = pl2303_set_termios,
.tiocmget = pl2303_tiocmget,
.tiocmset = pl2303_tiocmset,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
.process_read_urb = pl2303_process_read_urb,
.read_int_callback = pl2303_read_int_callback,
+ .probe = pl2303_probe,
.attach = pl2303_startup,
.release = pl2303_release,
+ .port_probe = pl2303_port_probe,
+ .port_remove = pl2303_port_remove,
};
-static int __init pl2303_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&pl2303_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&pl2303_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&pl2303_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit pl2303_exit(void)
-{
- usb_deregister(&pl2303_driver);
- usb_serial_deregister(&pl2303_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &pl2303_device, NULL
+};
-module_init(pl2303_init);
-module_exit(pl2303_exit);
+module_usb_serial_driver(serial_drivers, id_table);
-MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_DESCRIPTION("Prolific PL2303 USB to serial adaptor driver");
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 43eb9bdad42..42bc082896a 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -21,6 +21,7 @@
#define PL2303_PRODUCT_ID_MMX 0x0612
#define PL2303_PRODUCT_ID_GPRS 0x0609
#define PL2303_PRODUCT_ID_HCR331 0x331a
+#define PL2303_PRODUCT_ID_MOTOROLA 0x0307
#define ATEN_VENDOR_ID 0x0557
#define ATEN_VENDOR_ID2 0x0547
@@ -120,8 +121,11 @@
#define SUPERIAL_VENDOR_ID 0x5372
#define SUPERIAL_PRODUCT_ID 0x2303
-/* Hewlett-Packard LD220-HP POS Pole Display */
+/* Hewlett-Packard POS Pole Displays */
#define HP_VENDOR_ID 0x03f0
+#define HP_LD960_PRODUCT_ID 0x0b39
+#define HP_LCM220_PRODUCT_ID 0x3139
+#define HP_LCM960_PRODUCT_ID 0x3239
#define HP_LD220_PRODUCT_ID 0x3524
/* Cressi Edy (diving computer) PC interface */
@@ -143,3 +147,8 @@
/* ADLINK ND-6530 RS232,RS485 and RS422 adapter */
#define ADLINK_VENDOR_ID 0x0b63
#define ADLINK_ND6530_PRODUCT_ID 0x6530
+
+/* SMART USB Serial Adapter */
+#define SMART_VENDOR_ID 0x0b8c
+#define SMART_PRODUCT_ID 0x2303
+
diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c
index 214a3e50429..6e9f8af9695 100644
--- a/drivers/usb/serial/qcaux.c
+++ b/drivers/usb/serial/qcaux.c
@@ -16,7 +16,6 @@
*/
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/usb.h>
@@ -54,7 +53,7 @@
#define SAMSUNG_VENDOR_ID 0x04e8
#define SAMSUNG_PRODUCT_U520 0x6640 /* SCH-U520 */
-static struct usb_device_id id_table[] = {
+static const struct usb_device_id id_table[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_PC5740, 0xff, 0x00, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_PC5750, 0xff, 0x00, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_UM150, 0xff, 0x00, 0x00) },
@@ -66,18 +65,14 @@ static struct usb_device_id id_table[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) },
+ { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) }, /* NMEA */
+ { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) }, /* WMC */
+ { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) }, /* DIAG */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1fac, 0x0151, 0xff, 0xff, 0xff) },
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver qcaux_driver = {
- .name = "qcaux",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
static struct usb_serial_driver qcaux_device = {
.driver = {
.owner = THIS_MODULE,
@@ -87,25 +82,9 @@ static struct usb_serial_driver qcaux_device = {
.num_ports = 1,
};
-static int __init qcaux_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&qcaux_device);
- if (retval)
- return retval;
- retval = usb_register(&qcaux_driver);
- if (retval)
- usb_serial_deregister(&qcaux_device);
- return retval;
-}
-
-static void __exit qcaux_exit(void)
-{
- usb_deregister(&qcaux_driver);
- usb_serial_deregister(&qcaux_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &qcaux_device, NULL
+};
-module_init(qcaux_init);
-module_exit(qcaux_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index 8858201eb1d..b2aa003bf41 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -13,6 +13,7 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
+#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include <linux/slab.h>
@@ -21,34 +22,60 @@
#define DRIVER_AUTHOR "Qualcomm Inc"
#define DRIVER_DESC "Qualcomm USB Serial driver"
-static int debug;
+/* standard device layouts supported by this driver */
+enum qcserial_layouts {
+ QCSERIAL_G2K = 0, /* Gobi 2000 */
+ QCSERIAL_G1K = 1, /* Gobi 1000 */
+ QCSERIAL_SWI = 2, /* Sierra Wireless */
+};
+
+#define DEVICE_G1K(v, p) \
+ USB_DEVICE(v, p), .driver_info = QCSERIAL_G1K
+#define DEVICE_SWI(v, p) \
+ USB_DEVICE(v, p), .driver_info = QCSERIAL_SWI
static const struct usb_device_id id_table[] = {
- {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
- {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
- {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */
- {USB_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */
- {USB_DEVICE(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */
- {USB_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */
- {USB_DEVICE(0x413c, 0x8171)}, /* Dell Gobi QDL device */
- {USB_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */
- {USB_DEVICE(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
- {USB_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
- {USB_DEVICE(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
- {USB_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
- {USB_DEVICE(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */
- {USB_DEVICE(0x1557, 0x0a80)}, /* OQO Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9008)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9201)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
+ /* Gobi 1000 devices */
+ {DEVICE_G1K(0x05c6, 0x9211)}, /* Acer Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
+ {DEVICE_G1K(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
+ {DEVICE_G1K(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */
+ {DEVICE_G1K(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */
+ {DEVICE_G1K(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */
+ {DEVICE_G1K(0x413c, 0x8172)}, /* Dell Gobi Modem device */
+ {DEVICE_G1K(0x413c, 0x8171)}, /* Dell Gobi QDL device */
+ {DEVICE_G1K(0x1410, 0xa001)}, /* Novatel/Verizon USB-1000 */
+ {DEVICE_G1K(0x1410, 0xa002)}, /* Novatel Gobi Modem device */
+ {DEVICE_G1K(0x1410, 0xa003)}, /* Novatel Gobi Modem device */
+ {DEVICE_G1K(0x1410, 0xa004)}, /* Novatel Gobi Modem device */
+ {DEVICE_G1K(0x1410, 0xa005)}, /* Novatel Gobi Modem device */
+ {DEVICE_G1K(0x1410, 0xa006)}, /* Novatel Gobi Modem device */
+ {DEVICE_G1K(0x1410, 0xa007)}, /* Novatel Gobi Modem device */
+ {DEVICE_G1K(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
+ {DEVICE_G1K(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
+ {DEVICE_G1K(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
+ {DEVICE_G1K(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
+ {DEVICE_G1K(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */
+ {DEVICE_G1K(0x1557, 0x0a80)}, /* OQO Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9001)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9002)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9202)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9203)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9008)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9009)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9201)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
+ {DEVICE_G1K(0x1bc7, 0x900e)}, /* Telit Gobi QDL device */
+
+ /* Gobi 2000 devices */
+ {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi 2000 QDL device */
{USB_DEVICE(0x413c, 0x8185)}, /* Dell Gobi 2000 QDL device (N0218, VU936) */
{USB_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */
{USB_DEVICE(0x05c6, 0x9208)}, /* Generic Gobi 2000 QDL device */
@@ -78,133 +105,231 @@ static const struct usb_device_id id_table[] = {
{USB_DEVICE(0x1199, 0x9008)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
{USB_DEVICE(0x1199, 0x9009)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
{USB_DEVICE(0x1199, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
+ {USB_DEVICE(0x1199, 0x9011)}, /* Sierra Wireless Gobi 2000 Modem device (MC8305) */
{USB_DEVICE(0x16d8, 0x8001)}, /* CMDTech Gobi 2000 QDL device (VU922) */
{USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */
{USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */
{USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */
+
+ /* Gobi 3000 devices */
+ {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Gobi 3000 QDL */
+ {USB_DEVICE(0x05c6, 0x920c)}, /* Gobi 3000 QDL */
+ {USB_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */
+ {USB_DEVICE(0x1410, 0xa020)}, /* Novatel Gobi 3000 QDL */
+ {USB_DEVICE(0x1410, 0xa021)}, /* Novatel Gobi 3000 Composite */
+ {USB_DEVICE(0x413c, 0x8193)}, /* Dell Gobi 3000 QDL */
+ {USB_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */
+ {USB_DEVICE(0x1199, 0x68a4)}, /* Sierra Wireless QDL */
+ {USB_DEVICE(0x1199, 0x68a5)}, /* Sierra Wireless Modem */
+ {USB_DEVICE(0x1199, 0x68a8)}, /* Sierra Wireless QDL */
+ {USB_DEVICE(0x1199, 0x68a9)}, /* Sierra Wireless Modem */
+ {USB_DEVICE(0x1199, 0x9010)}, /* Sierra Wireless Gobi 3000 QDL */
+ {USB_DEVICE(0x1199, 0x9012)}, /* Sierra Wireless Gobi 3000 QDL */
+ {USB_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */
+ {USB_DEVICE(0x1199, 0x9014)}, /* Sierra Wireless Gobi 3000 QDL */
+ {USB_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */
+ {USB_DEVICE(0x1199, 0x9018)}, /* Sierra Wireless Gobi 3000 QDL */
+ {USB_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */
+ {USB_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */
+ {USB_DEVICE(0x12D1, 0x14F0)}, /* Sony Gobi 3000 QDL */
+ {USB_DEVICE(0x12D1, 0x14F1)}, /* Sony Gobi 3000 Composite */
+ {USB_DEVICE(0x0AF0, 0x8120)}, /* Option GTM681W */
+
+ /* non-Gobi Sierra Wireless devices */
+ {DEVICE_SWI(0x0f3d, 0x68a2)}, /* Sierra Wireless MC7700 */
+ {DEVICE_SWI(0x114f, 0x68a2)}, /* Sierra Wireless MC7750 */
+ {DEVICE_SWI(0x1199, 0x68a2)}, /* Sierra Wireless MC7710 */
+ {DEVICE_SWI(0x1199, 0x68c0)}, /* Sierra Wireless MC73xx */
+ {DEVICE_SWI(0x1199, 0x901c)}, /* Sierra Wireless EM7700 */
+ {DEVICE_SWI(0x1199, 0x901f)}, /* Sierra Wireless EM7355 */
+ {DEVICE_SWI(0x1199, 0x9040)}, /* Sierra Wireless Modem */
+ {DEVICE_SWI(0x1199, 0x9041)}, /* Sierra Wireless MC7305/MC7355 */
+ {DEVICE_SWI(0x1199, 0x9051)}, /* Netgear AirCard 340U */
+ {DEVICE_SWI(0x1199, 0x9053)}, /* Sierra Wireless Modem */
+ {DEVICE_SWI(0x1199, 0x9054)}, /* Sierra Wireless Modem */
+ {DEVICE_SWI(0x1199, 0x9055)}, /* Netgear AirCard 341U */
+ {DEVICE_SWI(0x1199, 0x9056)}, /* Sierra Wireless Modem */
+ {DEVICE_SWI(0x1199, 0x9060)}, /* Sierra Wireless Modem */
+ {DEVICE_SWI(0x1199, 0x9061)}, /* Sierra Wireless Modem */
+ {DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */
+ {DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */
+ {DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
+ {DEVICE_SWI(0x413c, 0x81a8)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
+ {DEVICE_SWI(0x413c, 0x81a9)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
+
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver qcdriver = {
- .name = "qcserial",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .supports_autosuspend = true,
-};
-
static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
{
- struct usb_wwan_intf_private *data;
struct usb_host_interface *intf = serial->interface->cur_altsetting;
+ struct device *dev = &serial->dev->dev;
int retval = -ENODEV;
__u8 nintf;
__u8 ifnum;
-
- dbg("%s", __func__);
+ int altsetting = -1;
nintf = serial->dev->actconfig->desc.bNumInterfaces;
- dbg("Num Interfaces = %d", nintf);
+ dev_dbg(dev, "Num Interfaces = %d\n", nintf);
ifnum = intf->desc.bInterfaceNumber;
- dbg("This Interface = %d", ifnum);
+ dev_dbg(dev, "This Interface = %d\n", ifnum);
- data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- spin_lock_init(&data->susp_lock);
-
- usb_enable_autosuspend(serial->dev);
-
- switch (nintf) {
- case 1:
+ if (nintf == 1) {
/* QDL mode */
/* Gobi 2000 has a single altsetting, older ones have two */
if (serial->interface->num_altsetting == 2)
intf = &serial->interface->altsetting[1];
else if (serial->interface->num_altsetting > 2)
- break;
+ goto done;
if (intf->desc.bNumEndpoints == 2 &&
usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) &&
usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
- dbg("QDL port found");
+ dev_dbg(dev, "QDL port found\n");
if (serial->interface->num_altsetting == 1)
- return 0;
-
- retval = usb_set_interface(serial->dev, ifnum, 1);
- if (retval < 0) {
- dev_err(&serial->dev->dev,
- "Could not set interface, error %d\n",
- retval);
- retval = -ENODEV;
- kfree(data);
- }
- return retval;
+ retval = 0; /* Success */
+ else
+ altsetting = 1;
}
+ goto done;
+
+ }
+
+ /* default to enabling interface */
+ altsetting = 0;
+
+ /*
+ * Composite mode; don't bind to the QMI/net interface as that
+ * gets handled by other drivers.
+ */
+
+ switch (id->driver_info) {
+ case QCSERIAL_G1K:
+ /*
+ * Gobi 1K USB layout:
+ * 0: DM/DIAG (use libqcdm from ModemManager for communication)
+ * 1: serial port (doesn't respond)
+ * 2: AT-capable modem port
+ * 3: QMI/net
+ */
+ if (nintf < 3 || nintf > 4) {
+ dev_err(dev, "unknown number of interfaces: %d\n", nintf);
+ altsetting = -1;
+ goto done;
+ }
+
+ if (ifnum == 0) {
+ dev_dbg(dev, "Gobi 1K DM/DIAG interface found\n");
+ altsetting = 1;
+ } else if (ifnum == 2)
+ dev_dbg(dev, "Modem port found\n");
+ else
+ altsetting = -1;
break;
+ case QCSERIAL_G2K:
+ /*
+ * Gobi 2K+ USB layout:
+ * 0: QMI/net
+ * 1: DM/DIAG (use libqcdm from ModemManager for communication)
+ * 2: AT-capable modem port
+ * 3: NMEA
+ */
+ if (nintf < 3 || nintf > 4) {
+ dev_err(dev, "unknown number of interfaces: %d\n", nintf);
+ altsetting = -1;
+ goto done;
+ }
- case 3:
- case 4:
- /* Composite mode */
- /* ifnum == 0 is a broadband network adapter */
- if (ifnum == 1) {
- /*
- * Diagnostics Monitor (serial line 9600 8N1)
- * Qualcomm DM protocol
- * use "libqcdm" (ModemManager) for communication
- */
- dbg("Diagnostics Monitor found");
- retval = usb_set_interface(serial->dev, ifnum, 0);
- if (retval < 0) {
- dev_err(&serial->dev->dev,
- "Could not set interface, error %d\n",
- retval);
- retval = -ENODEV;
- }
- } else if (ifnum == 2) {
- dbg("Modem port found");
- retval = usb_set_interface(serial->dev, ifnum, 0);
- if (retval < 0) {
- dev_err(&serial->dev->dev,
- "Could not set interface, error %d\n",
- retval);
- retval = -ENODEV;
- kfree(data);
- }
- return retval;
- } else if (ifnum==3) {
+ switch (ifnum) {
+ case 0:
+ /* Don't claim the QMI/net interface */
+ altsetting = -1;
+ break;
+ case 1:
+ dev_dbg(dev, "Gobi 2K+ DM/DIAG interface found\n");
+ break;
+ case 2:
+ dev_dbg(dev, "Modem port found\n");
+ break;
+ case 3:
/*
* NMEA (serial line 9600 8N1)
* # echo "\$GPS_START" > /dev/ttyUSBx
* # echo "\$GPS_STOP" > /dev/ttyUSBx
*/
- dbg("NMEA GPS interface found");
- retval = usb_set_interface(serial->dev, ifnum, 0);
- if (retval < 0) {
- dev_err(&serial->dev->dev,
- "Could not set interface, error %d\n",
- retval);
- retval = -ENODEV;
- }
+ dev_dbg(dev, "Gobi 2K+ NMEA GPS interface found\n");
+ break;
+ }
+ break;
+ case QCSERIAL_SWI:
+ /*
+ * Sierra Wireless layout:
+ * 0: DM/DIAG (use libqcdm from ModemManager for communication)
+ * 2: NMEA
+ * 3: AT-capable modem port
+ * 8: QMI/net
+ */
+ switch (ifnum) {
+ case 0:
+ dev_dbg(dev, "DM/DIAG interface found\n");
+ break;
+ case 2:
+ dev_dbg(dev, "NMEA GPS interface found\n");
+ break;
+ case 3:
+ dev_dbg(dev, "Modem port found\n");
+ break;
+ default:
+ /* don't claim any unsupported interface */
+ altsetting = -1;
+ break;
}
break;
-
default:
- dev_err(&serial->dev->dev,
- "unknown number of interfaces: %d\n", nintf);
- kfree(data);
- return -ENODEV;
+ dev_err(dev, "unsupported device layout type: %lu\n",
+ id->driver_info);
+ break;
+ }
+
+done:
+ if (altsetting >= 0) {
+ retval = usb_set_interface(serial->dev, ifnum, altsetting);
+ if (retval < 0) {
+ dev_err(dev,
+ "Could not set interface, error %d\n",
+ retval);
+ retval = -ENODEV;
+ }
}
return retval;
}
+static int qc_attach(struct usb_serial *serial)
+{
+ struct usb_wwan_intf_private *data;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ spin_lock_init(&data->susp_lock);
+
+ usb_set_serial_data(serial, data);
+
+ return 0;
+}
+
+static void qc_release(struct usb_serial *serial)
+{
+ struct usb_wwan_intf_private *priv = usb_get_serial_data(serial);
+
+ usb_set_serial_data(serial, NULL);
+ kfree(priv);
+}
+
static struct usb_serial_driver qcdevice = {
.driver = {
.owner = THIS_MODULE,
@@ -212,7 +337,6 @@ static struct usb_serial_driver qcdevice = {
},
.description = "Qualcomm USB modem",
.id_table = id_table,
- .usb_driver = &qcdriver,
.num_ports = 1,
.probe = qcprobe,
.open = usb_wwan_open,
@@ -220,44 +344,22 @@ static struct usb_serial_driver qcdevice = {
.write = usb_wwan_write,
.write_room = usb_wwan_write_room,
.chars_in_buffer = usb_wwan_chars_in_buffer,
- .attach = usb_wwan_startup,
- .disconnect = usb_wwan_disconnect,
- .release = usb_wwan_release,
+ .attach = qc_attach,
+ .release = qc_release,
+ .port_probe = usb_wwan_port_probe,
+ .port_remove = usb_wwan_port_remove,
#ifdef CONFIG_PM
.suspend = usb_wwan_suspend,
.resume = usb_wwan_resume,
#endif
};
-static int __init qcinit(void)
-{
- int retval;
-
- retval = usb_serial_register(&qcdevice);
- if (retval)
- return retval;
-
- retval = usb_register(&qcdriver);
- if (retval) {
- usb_serial_deregister(&qcdevice);
- return retval;
- }
-
- return 0;
-}
-
-static void __exit qcexit(void)
-{
- usb_deregister(&qcdriver);
- usb_serial_deregister(&qcdevice);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &qcdevice, NULL
+};
-module_init(qcinit);
-module_exit(qcexit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL v2");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
new file mode 100644
index 00000000000..504f5bff79c
--- /dev/null
+++ b/drivers/usb/serial/quatech2.c
@@ -0,0 +1,1036 @@
+/*
+ * usb-serial driver for Quatech USB 2 devices
+ *
+ * Copyright (C) 2012 Bill Pemberton (wfp5p@virginia.edu)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ *
+ * These devices all have only 1 bulk in and 1 bulk out that is shared
+ * for all serial ports.
+ *
+ */
+
+#include <asm/unaligned.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/uaccess.h>
+
+/* default urb timeout for usb operations */
+#define QT2_USB_TIMEOUT USB_CTRL_SET_TIMEOUT
+
+#define QT_OPEN_CLOSE_CHANNEL 0xca
+#define QT_SET_GET_DEVICE 0xc2
+#define QT_SET_GET_REGISTER 0xc0
+#define QT_GET_SET_PREBUF_TRIG_LVL 0xcc
+#define QT_SET_ATF 0xcd
+#define QT_TRANSFER_IN 0xc0
+#define QT_HW_FLOW_CONTROL_MASK 0xc5
+#define QT_SW_FLOW_CONTROL_MASK 0xc6
+#define QT2_BREAK_CONTROL 0xc8
+#define QT2_GET_SET_UART 0xc1
+#define QT2_FLUSH_DEVICE 0xc4
+#define QT2_GET_SET_QMCR 0xe1
+#define QT2_QMCR_RS232 0x40
+#define QT2_QMCR_RS422 0x10
+
+#define SERIAL_CRTSCTS ((UART_MCR_RTS << 8) | UART_MSR_CTS)
+
+#define SERIAL_EVEN_PARITY (UART_LCR_PARITY | UART_LCR_EPAR)
+
+/* status bytes for the device */
+#define QT2_CONTROL_BYTE 0x1b
+#define QT2_LINE_STATUS 0x00 /* following 1 byte is line status */
+#define QT2_MODEM_STATUS 0x01 /* following 1 byte is modem status */
+#define QT2_XMIT_HOLD 0x02 /* following 2 bytes are ?? */
+#define QT2_CHANGE_PORT 0x03 /* following 1 byte is port to change to */
+#define QT2_REC_FLUSH 0x04 /* no following info */
+#define QT2_XMIT_FLUSH 0x05 /* no following info */
+#define QT2_CONTROL_ESCAPE 0xff /* pass through previous 2 control bytes */
+
+#define MAX_BAUD_RATE 921600
+#define DEFAULT_BAUD_RATE 9600
+
+#define QT2_READ_BUFFER_SIZE 512 /* size of read buffer */
+#define QT2_WRITE_BUFFER_SIZE 512 /* size of write buffer */
+#define QT2_WRITE_CONTROL_SIZE 5 /* control bytes used for a write */
+
+#define DRIVER_DESC "Quatech 2nd gen USB to Serial Driver"
+
+#define USB_VENDOR_ID_QUATECH 0x061d
+#define QUATECH_SSU2_100 0xC120 /* RS232 single port */
+#define QUATECH_DSU2_100 0xC140 /* RS232 dual port */
+#define QUATECH_DSU2_400 0xC150 /* RS232/422/485 dual port */
+#define QUATECH_QSU2_100 0xC160 /* RS232 four port */
+#define QUATECH_QSU2_400 0xC170 /* RS232/422/485 four port */
+#define QUATECH_ESU2_100 0xC1A0 /* RS232 eight port */
+#define QUATECH_ESU2_400 0xC180 /* RS232/422/485 eight port */
+
+struct qt2_device_detail {
+ int product_id;
+ int num_ports;
+};
+
+#define QT_DETAILS(prod, ports) \
+ .product_id = (prod), \
+ .num_ports = (ports)
+
+static const struct qt2_device_detail qt2_device_details[] = {
+ {QT_DETAILS(QUATECH_SSU2_100, 1)},
+ {QT_DETAILS(QUATECH_DSU2_400, 2)},
+ {QT_DETAILS(QUATECH_DSU2_100, 2)},
+ {QT_DETAILS(QUATECH_QSU2_400, 4)},
+ {QT_DETAILS(QUATECH_QSU2_100, 4)},
+ {QT_DETAILS(QUATECH_ESU2_400, 8)},
+ {QT_DETAILS(QUATECH_ESU2_100, 8)},
+ {QT_DETAILS(0, 0)} /* Terminating entry */
+};
+
+static const struct usb_device_id id_table[] = {
+ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU2_100)},
+ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU2_100)},
+ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU2_400)},
+ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU2_100)},
+ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU2_400)},
+ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU2_100)},
+ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU2_400)},
+ {} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+struct qt2_serial_private {
+ unsigned char current_port; /* current port for incoming data */
+
+ struct urb *read_urb; /* shared among all ports */
+ char *read_buffer;
+};
+
+struct qt2_port_private {
+ u8 device_port;
+
+ spinlock_t urb_lock;
+ bool urb_in_use;
+ struct urb *write_urb;
+ char *write_buffer;
+
+ spinlock_t lock;
+ u8 shadowLSR;
+ u8 shadowMSR;
+
+ struct usb_serial_port *port;
+};
+
+static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch);
+static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch);
+static void qt2_write_bulk_callback(struct urb *urb);
+static void qt2_read_bulk_callback(struct urb *urb);
+
+static void qt2_release(struct usb_serial *serial)
+{
+ struct qt2_serial_private *serial_priv;
+
+ serial_priv = usb_get_serial_data(serial);
+
+ usb_free_urb(serial_priv->read_urb);
+ kfree(serial_priv->read_buffer);
+ kfree(serial_priv);
+}
+
+static inline int calc_baud_divisor(int baudrate)
+{
+ int divisor, rem;
+
+ divisor = MAX_BAUD_RATE / baudrate;
+ rem = MAX_BAUD_RATE % baudrate;
+ /* Round to nearest divisor */
+ if (((rem * 2) >= baudrate) && (baudrate != 110))
+ divisor++;
+
+ return divisor;
+}
+
+static inline int qt2_set_port_config(struct usb_device *dev,
+ unsigned char port_number,
+ u16 baudrate, u16 lcr)
+{
+ int divisor = calc_baud_divisor(baudrate);
+ u16 index = ((u16) (lcr << 8) | (u16) (port_number));
+
+ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ QT2_GET_SET_UART, 0x40,
+ divisor, index, NULL, 0, QT2_USB_TIMEOUT);
+}
+
+static inline int qt2_control_msg(struct usb_device *dev,
+ u8 request, u16 data, u16 index)
+{
+ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ request, 0x40, data, index,
+ NULL, 0, QT2_USB_TIMEOUT);
+}
+
+static inline int qt2_setdevice(struct usb_device *dev, u8 *data)
+{
+ u16 x = ((u16) (data[1] << 8) | (u16) (data[0]));
+
+ return qt2_control_msg(dev, QT_SET_GET_DEVICE, x, 0);
+}
+
+
+static inline int qt2_getdevice(struct usb_device *dev, u8 *data)
+{
+ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ QT_SET_GET_DEVICE, 0xc0, 0, 0,
+ data, 3, QT2_USB_TIMEOUT);
+}
+
+static inline int qt2_getregister(struct usb_device *dev,
+ u8 uart,
+ u8 reg,
+ u8 *data)
+{
+ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ QT_SET_GET_REGISTER, 0xc0, reg,
+ uart, data, sizeof(*data), QT2_USB_TIMEOUT);
+
+}
+
+static inline int qt2_setregister(struct usb_device *dev,
+ u8 uart, u8 reg, u16 data)
+{
+ u16 value = (data << 8) | reg;
+
+ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ QT_SET_GET_REGISTER, 0x40, value, uart,
+ NULL, 0, QT2_USB_TIMEOUT);
+}
+
+static inline int update_mctrl(struct qt2_port_private *port_priv,
+ unsigned int set, unsigned int clear)
+{
+ struct usb_serial_port *port = port_priv->port;
+ struct usb_device *dev = port->serial->dev;
+ unsigned urb_value;
+ int status;
+
+ if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
+ dev_dbg(&port->dev,
+ "update_mctrl - DTR|RTS not being set|cleared\n");
+ return 0; /* no change */
+ }
+
+ clear &= ~set; /* 'set' takes precedence over 'clear' */
+ urb_value = 0;
+ if (set & TIOCM_DTR)
+ urb_value |= UART_MCR_DTR;
+ if (set & TIOCM_RTS)
+ urb_value |= UART_MCR_RTS;
+
+ status = qt2_setregister(dev, port_priv->device_port, UART_MCR,
+ urb_value);
+ if (status < 0)
+ dev_err(&port->dev,
+ "update_mctrl - Error from MODEM_CTRL urb: %i\n",
+ status);
+ return status;
+}
+
+static int qt2_calc_num_ports(struct usb_serial *serial)
+{
+ struct qt2_device_detail d;
+ int i;
+
+ for (i = 0; d = qt2_device_details[i], d.product_id != 0; i++) {
+ if (d.product_id == le16_to_cpu(serial->dev->descriptor.idProduct))
+ return d.num_ports;
+ }
+
+ /* we didn't recognize the device */
+ dev_err(&serial->dev->dev,
+ "don't know the number of ports, assuming 1\n");
+
+ return 1;
+}
+
+static void qt2_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ struct ktermios *old_termios)
+{
+ struct usb_device *dev = port->serial->dev;
+ struct qt2_port_private *port_priv;
+ struct ktermios *termios = &tty->termios;
+ u16 baud;
+ unsigned int cflag = termios->c_cflag;
+ u16 new_lcr = 0;
+ int status;
+
+ port_priv = usb_get_serial_port_data(port);
+
+ if (cflag & PARENB) {
+ if (cflag & PARODD)
+ new_lcr |= UART_LCR_PARITY;
+ else
+ new_lcr |= SERIAL_EVEN_PARITY;
+ }
+
+ switch (cflag & CSIZE) {
+ case CS5:
+ new_lcr |= UART_LCR_WLEN5;
+ break;
+ case CS6:
+ new_lcr |= UART_LCR_WLEN6;
+ break;
+ case CS7:
+ new_lcr |= UART_LCR_WLEN7;
+ break;
+ default:
+ case CS8:
+ new_lcr |= UART_LCR_WLEN8;
+ break;
+ }
+
+ baud = tty_get_baud_rate(tty);
+ if (!baud)
+ baud = 9600;
+
+ status = qt2_set_port_config(dev, port_priv->device_port, baud,
+ new_lcr);
+ if (status < 0)
+ dev_err(&port->dev, "%s - qt2_set_port_config failed: %i\n",
+ __func__, status);
+
+ if (cflag & CRTSCTS)
+ status = qt2_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
+ SERIAL_CRTSCTS,
+ port_priv->device_port);
+ else
+ status = qt2_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
+ 0, port_priv->device_port);
+ if (status < 0)
+ dev_err(&port->dev, "%s - set HW flow control failed: %i\n",
+ __func__, status);
+
+ if (I_IXOFF(tty) || I_IXON(tty)) {
+ u16 x = ((u16) (START_CHAR(tty) << 8) | (u16) (STOP_CHAR(tty)));
+
+ status = qt2_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
+ x, port_priv->device_port);
+ } else
+ status = qt2_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
+ 0, port_priv->device_port);
+
+ if (status < 0)
+ dev_err(&port->dev, "%s - set SW flow control failed: %i\n",
+ __func__, status);
+
+}
+
+static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port)
+{
+ struct usb_serial *serial;
+ struct qt2_port_private *port_priv;
+ u8 *data;
+ u16 device_port;
+ int status;
+ unsigned long flags;
+
+ device_port = port->port_number;
+
+ serial = port->serial;
+
+ port_priv = usb_get_serial_port_data(port);
+
+ /* set the port to RS232 mode */
+ status = qt2_control_msg(serial->dev, QT2_GET_SET_QMCR,
+ QT2_QMCR_RS232, device_port);
+ if (status < 0) {
+ dev_err(&port->dev,
+ "%s failed to set RS232 mode for port %i error %i\n",
+ __func__, device_port, status);
+ return status;
+ }
+
+ data = kzalloc(2, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ /* open the port */
+ status = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ QT_OPEN_CLOSE_CHANNEL,
+ 0xc0, 0,
+ device_port, data, 2, QT2_USB_TIMEOUT);
+
+ if (status < 0) {
+ dev_err(&port->dev, "%s - open port failed %i\n", __func__,
+ status);
+ kfree(data);
+ return status;
+ }
+
+ spin_lock_irqsave(&port_priv->lock, flags);
+ port_priv->shadowLSR = data[0];
+ port_priv->shadowMSR = data[1];
+ spin_unlock_irqrestore(&port_priv->lock, flags);
+
+ kfree(data);
+
+ /* set to default speed and 8bit word size */
+ status = qt2_set_port_config(serial->dev, device_port,
+ DEFAULT_BAUD_RATE, UART_LCR_WLEN8);
+ if (status < 0) {
+ dev_err(&port->dev, "%s - initial setup failed (%i)\n",
+ __func__, device_port);
+ return status;
+ }
+
+ port_priv->device_port = (u8) device_port;
+
+ if (tty)
+ qt2_set_termios(tty, port, &tty->termios);
+
+ return 0;
+
+}
+
+static void qt2_close(struct usb_serial_port *port)
+{
+ struct usb_serial *serial;
+ struct qt2_port_private *port_priv;
+ unsigned long flags;
+ int i;
+
+ serial = port->serial;
+ port_priv = usb_get_serial_port_data(port);
+
+ spin_lock_irqsave(&port_priv->urb_lock, flags);
+ usb_kill_urb(port_priv->write_urb);
+ port_priv->urb_in_use = false;
+ spin_unlock_irqrestore(&port_priv->urb_lock, flags);
+
+ /* flush the port transmit buffer */
+ i = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ QT2_FLUSH_DEVICE, 0x40, 1,
+ port_priv->device_port, NULL, 0, QT2_USB_TIMEOUT);
+
+ if (i < 0)
+ dev_err(&port->dev, "%s - transmit buffer flush failed: %i\n",
+ __func__, i);
+
+ /* flush the port receive buffer */
+ i = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ QT2_FLUSH_DEVICE, 0x40, 0,
+ port_priv->device_port, NULL, 0, QT2_USB_TIMEOUT);
+
+ if (i < 0)
+ dev_err(&port->dev, "%s - receive buffer flush failed: %i\n",
+ __func__, i);
+
+ /* close the port */
+ i = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ QT_OPEN_CLOSE_CHANNEL,
+ 0x40, 0,
+ port_priv->device_port, NULL, 0, QT2_USB_TIMEOUT);
+
+ if (i < 0)
+ dev_err(&port->dev, "%s - close port failed %i\n",
+ __func__, i);
+}
+
+static void qt2_disconnect(struct usb_serial *serial)
+{
+ struct qt2_serial_private *serial_priv = usb_get_serial_data(serial);
+
+ usb_kill_urb(serial_priv->read_urb);
+}
+
+static int get_serial_info(struct usb_serial_port *port,
+ struct serial_struct __user *retinfo)
+{
+ struct serial_struct tmp;
+
+ if (!retinfo)
+ return -EFAULT;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.line = port->minor;
+ tmp.port = 0;
+ tmp.irq = 0;
+ tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+ tmp.xmit_fifo_size = port->bulk_out_size;
+ tmp.baud_base = 9600;
+ tmp.close_delay = 5*HZ;
+ tmp.closing_wait = 30*HZ;
+
+ if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+ return -EFAULT;
+ return 0;
+}
+
+static int qt2_ioctl(struct tty_struct *tty,
+ unsigned int cmd, unsigned long arg)
+{
+ struct usb_serial_port *port = tty->driver_data;
+
+ switch (cmd) {
+ case TIOCGSERIAL:
+ return get_serial_info(port,
+ (struct serial_struct __user *)arg);
+ default:
+ break;
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+static void qt2_process_status(struct usb_serial_port *port, unsigned char *ch)
+{
+ switch (*ch) {
+ case QT2_LINE_STATUS:
+ qt2_update_lsr(port, ch + 1);
+ break;
+ case QT2_MODEM_STATUS:
+ qt2_update_msr(port, ch + 1);
+ break;
+ }
+}
+
+/* not needed, kept to document functionality */
+static void qt2_process_xmit_empty(struct usb_serial_port *port,
+ unsigned char *ch)
+{
+ int bytes_written;
+
+ bytes_written = (int)(*ch) + (int)(*(ch + 1) << 4);
+}
+
+/* not needed, kept to document functionality */
+static void qt2_process_flush(struct usb_serial_port *port, unsigned char *ch)
+{
+ return;
+}
+
+static void qt2_process_read_urb(struct urb *urb)
+{
+ struct usb_serial *serial;
+ struct qt2_serial_private *serial_priv;
+ struct usb_serial_port *port;
+ struct qt2_port_private *port_priv;
+ bool escapeflag;
+ unsigned char *ch;
+ int i;
+ unsigned char newport;
+ int len = urb->actual_length;
+
+ if (!len)
+ return;
+
+ ch = urb->transfer_buffer;
+ serial = urb->context;
+ serial_priv = usb_get_serial_data(serial);
+ port = serial->port[serial_priv->current_port];
+ port_priv = usb_get_serial_port_data(port);
+
+ for (i = 0; i < urb->actual_length; i++) {
+ ch = (unsigned char *)urb->transfer_buffer + i;
+ if ((i <= (len - 3)) &&
+ (*ch == QT2_CONTROL_BYTE) &&
+ (*(ch + 1) == QT2_CONTROL_BYTE)) {
+ escapeflag = false;
+ switch (*(ch + 2)) {
+ case QT2_LINE_STATUS:
+ case QT2_MODEM_STATUS:
+ if (i > (len - 4)) {
+ dev_warn(&port->dev,
+ "%s - status message too short\n",
+ __func__);
+ break;
+ }
+ qt2_process_status(port, ch + 2);
+ i += 3;
+ escapeflag = true;
+ break;
+ case QT2_XMIT_HOLD:
+ if (i > (len - 5)) {
+ dev_warn(&port->dev,
+ "%s - xmit_empty message too short\n",
+ __func__);
+ break;
+ }
+ qt2_process_xmit_empty(port, ch + 3);
+ i += 4;
+ escapeflag = true;
+ break;
+ case QT2_CHANGE_PORT:
+ if (i > (len - 4)) {
+ dev_warn(&port->dev,
+ "%s - change_port message too short\n",
+ __func__);
+ break;
+ }
+ tty_flip_buffer_push(&port->port);
+
+ newport = *(ch + 3);
+
+ if (newport > serial->num_ports) {
+ dev_err(&port->dev,
+ "%s - port change to invalid port: %i\n",
+ __func__, newport);
+ break;
+ }
+
+ serial_priv->current_port = newport;
+ port = serial->port[serial_priv->current_port];
+ port_priv = usb_get_serial_port_data(port);
+ i += 3;
+ escapeflag = true;
+ break;
+ case QT2_REC_FLUSH:
+ case QT2_XMIT_FLUSH:
+ qt2_process_flush(port, ch + 2);
+ i += 2;
+ escapeflag = true;
+ break;
+ case QT2_CONTROL_ESCAPE:
+ tty_buffer_request_room(&port->port, 2);
+ tty_insert_flip_string(&port->port, ch, 2);
+ i += 2;
+ escapeflag = true;
+ break;
+ default:
+ dev_warn(&port->dev,
+ "%s - unsupported command %i\n",
+ __func__, *(ch + 2));
+ break;
+ }
+ if (escapeflag)
+ continue;
+ }
+
+ tty_buffer_request_room(&port->port, 1);
+ tty_insert_flip_string(&port->port, ch, 1);
+ }
+
+ tty_flip_buffer_push(&port->port);
+}
+
+static void qt2_write_bulk_callback(struct urb *urb)
+{
+ struct usb_serial_port *port;
+ struct qt2_port_private *port_priv;
+
+ port = urb->context;
+ port_priv = usb_get_serial_port_data(port);
+
+ spin_lock(&port_priv->urb_lock);
+
+ port_priv->urb_in_use = false;
+ usb_serial_port_softint(port);
+
+ spin_unlock(&port_priv->urb_lock);
+
+}
+
+static void qt2_read_bulk_callback(struct urb *urb)
+{
+ struct usb_serial *serial = urb->context;
+ int status;
+
+ if (urb->status) {
+ dev_warn(&serial->dev->dev,
+ "%s - non-zero urb status: %i\n", __func__,
+ urb->status);
+ return;
+ }
+
+ qt2_process_read_urb(urb);
+
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status != 0)
+ dev_err(&serial->dev->dev,
+ "%s - resubmit read urb failed: %i\n",
+ __func__, status);
+}
+
+static int qt2_setup_urbs(struct usb_serial *serial)
+{
+ struct usb_serial_port *port0;
+ struct qt2_serial_private *serial_priv;
+ int status;
+
+ port0 = serial->port[0];
+
+ serial_priv = usb_get_serial_data(serial);
+ serial_priv->read_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!serial_priv->read_urb)
+ return -ENOMEM;
+
+ usb_fill_bulk_urb(serial_priv->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port0->bulk_in_endpointAddress),
+ serial_priv->read_buffer,
+ QT2_READ_BUFFER_SIZE,
+ qt2_read_bulk_callback, serial);
+
+ status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL);
+ if (status != 0) {
+ dev_err(&serial->dev->dev,
+ "%s - submit read urb failed %i\n", __func__, status);
+ usb_free_urb(serial_priv->read_urb);
+ return status;
+ }
+
+ return 0;
+}
+
+static int qt2_attach(struct usb_serial *serial)
+{
+ struct qt2_serial_private *serial_priv;
+ int status;
+
+ /* power on unit */
+ status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ 0xc2, 0x40, 0x8000, 0, NULL, 0,
+ QT2_USB_TIMEOUT);
+ if (status < 0) {
+ dev_err(&serial->dev->dev,
+ "%s - failed to power on unit: %i\n", __func__, status);
+ return status;
+ }
+
+ serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
+ if (!serial_priv)
+ return -ENOMEM;
+
+ serial_priv->read_buffer = kmalloc(QT2_READ_BUFFER_SIZE, GFP_KERNEL);
+ if (!serial_priv->read_buffer) {
+ status = -ENOMEM;
+ goto err_buf;
+ }
+
+ usb_set_serial_data(serial, serial_priv);
+
+ status = qt2_setup_urbs(serial);
+ if (status != 0)
+ goto attach_failed;
+
+ return 0;
+
+attach_failed:
+ kfree(serial_priv->read_buffer);
+err_buf:
+ kfree(serial_priv);
+ return status;
+}
+
+static int qt2_port_probe(struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+ struct qt2_port_private *port_priv;
+ u8 bEndpointAddress;
+
+ port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
+ if (!port_priv)
+ return -ENOMEM;
+
+ spin_lock_init(&port_priv->lock);
+ spin_lock_init(&port_priv->urb_lock);
+ port_priv->port = port;
+
+ port_priv->write_buffer = kmalloc(QT2_WRITE_BUFFER_SIZE, GFP_KERNEL);
+ if (!port_priv->write_buffer)
+ goto err_buf;
+
+ port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!port_priv->write_urb)
+ goto err_urb;
+
+ bEndpointAddress = serial->port[0]->bulk_out_endpointAddress;
+ usb_fill_bulk_urb(port_priv->write_urb, serial->dev,
+ usb_sndbulkpipe(serial->dev, bEndpointAddress),
+ port_priv->write_buffer,
+ QT2_WRITE_BUFFER_SIZE,
+ qt2_write_bulk_callback, port);
+
+ usb_set_serial_port_data(port, port_priv);
+
+ return 0;
+err_urb:
+ kfree(port_priv->write_buffer);
+err_buf:
+ kfree(port_priv);
+ return -ENOMEM;
+}
+
+static int qt2_port_remove(struct usb_serial_port *port)
+{
+ struct qt2_port_private *port_priv;
+
+ port_priv = usb_get_serial_port_data(port);
+ usb_free_urb(port_priv->write_urb);
+ kfree(port_priv->write_buffer);
+ kfree(port_priv);
+
+ return 0;
+}
+
+static int qt2_tiocmget(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct usb_device *dev = port->serial->dev;
+ struct qt2_port_private *port_priv = usb_get_serial_port_data(port);
+ u8 *d;
+ int r;
+
+ d = kzalloc(2, GFP_KERNEL);
+ if (!d)
+ return -ENOMEM;
+
+ r = qt2_getregister(dev, port_priv->device_port, UART_MCR, d);
+ if (r < 0)
+ goto mget_out;
+
+ r = qt2_getregister(dev, port_priv->device_port, UART_MSR, d + 1);
+ if (r < 0)
+ goto mget_out;
+
+ r = (d[0] & UART_MCR_DTR ? TIOCM_DTR : 0) |
+ (d[0] & UART_MCR_RTS ? TIOCM_RTS : 0) |
+ (d[1] & UART_MSR_CTS ? TIOCM_CTS : 0) |
+ (d[1] & UART_MSR_DCD ? TIOCM_CAR : 0) |
+ (d[1] & UART_MSR_RI ? TIOCM_RI : 0) |
+ (d[1] & UART_MSR_DSR ? TIOCM_DSR : 0);
+
+mget_out:
+ kfree(d);
+ return r;
+}
+
+static int qt2_tiocmset(struct tty_struct *tty,
+ unsigned int set, unsigned int clear)
+{
+ struct qt2_port_private *port_priv;
+
+ port_priv = usb_get_serial_port_data(tty->driver_data);
+ return update_mctrl(port_priv, set, clear);
+}
+
+static void qt2_break_ctl(struct tty_struct *tty, int break_state)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct qt2_port_private *port_priv;
+ int status;
+ u16 val;
+
+ port_priv = usb_get_serial_port_data(port);
+
+ val = (break_state == -1) ? 1 : 0;
+
+ status = qt2_control_msg(port->serial->dev, QT2_BREAK_CONTROL,
+ val, port_priv->device_port);
+ if (status < 0)
+ dev_warn(&port->dev,
+ "%s - failed to send control message: %i\n", __func__,
+ status);
+}
+
+
+
+static void qt2_dtr_rts(struct usb_serial_port *port, int on)
+{
+ struct usb_device *dev = port->serial->dev;
+ struct qt2_port_private *port_priv = usb_get_serial_port_data(port);
+
+ /* Disable flow control */
+ if (!on) {
+ if (qt2_setregister(dev, port_priv->device_port,
+ UART_MCR, 0) < 0)
+ dev_warn(&port->dev, "error from flowcontrol urb\n");
+ }
+ /* drop RTS and DTR */
+ if (on)
+ update_mctrl(port_priv, TIOCM_DTR | TIOCM_RTS, 0);
+ else
+ update_mctrl(port_priv, 0, TIOCM_DTR | TIOCM_RTS);
+}
+
+static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)
+{
+ struct qt2_port_private *port_priv;
+ u8 newMSR = (u8) *ch;
+ unsigned long flags;
+
+ port_priv = usb_get_serial_port_data(port);
+
+ spin_lock_irqsave(&port_priv->lock, flags);
+ port_priv->shadowMSR = newMSR;
+ spin_unlock_irqrestore(&port_priv->lock, flags);
+
+ if (newMSR & UART_MSR_ANY_DELTA) {
+ /* update input line counters */
+ if (newMSR & UART_MSR_DCTS)
+ port->icount.cts++;
+ if (newMSR & UART_MSR_DDSR)
+ port->icount.dsr++;
+ if (newMSR & UART_MSR_DDCD)
+ port->icount.dcd++;
+ if (newMSR & UART_MSR_TERI)
+ port->icount.rng++;
+
+ wake_up_interruptible(&port->port.delta_msr_wait);
+ }
+}
+
+static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch)
+{
+ struct qt2_port_private *port_priv;
+ struct async_icount *icount;
+ unsigned long flags;
+ u8 newLSR = (u8) *ch;
+
+ port_priv = usb_get_serial_port_data(port);
+
+ if (newLSR & UART_LSR_BI)
+ newLSR &= (u8) (UART_LSR_OE | UART_LSR_BI);
+
+ spin_lock_irqsave(&port_priv->lock, flags);
+ port_priv->shadowLSR = newLSR;
+ spin_unlock_irqrestore(&port_priv->lock, flags);
+
+ icount = &port->icount;
+
+ if (newLSR & UART_LSR_BRK_ERROR_BITS) {
+
+ if (newLSR & UART_LSR_BI)
+ icount->brk++;
+
+ if (newLSR & UART_LSR_OE)
+ icount->overrun++;
+
+ if (newLSR & UART_LSR_PE)
+ icount->parity++;
+
+ if (newLSR & UART_LSR_FE)
+ icount->frame++;
+ }
+
+}
+
+static int qt2_write_room(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct qt2_port_private *port_priv;
+ unsigned long flags = 0;
+ int r;
+
+ port_priv = usb_get_serial_port_data(port);
+
+ spin_lock_irqsave(&port_priv->urb_lock, flags);
+
+ if (port_priv->urb_in_use)
+ r = 0;
+ else
+ r = QT2_WRITE_BUFFER_SIZE - QT2_WRITE_CONTROL_SIZE;
+
+ spin_unlock_irqrestore(&port_priv->urb_lock, flags);
+
+ return r;
+}
+
+static int qt2_write(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ const unsigned char *buf, int count)
+{
+ struct qt2_port_private *port_priv;
+ struct urb *write_urb;
+ unsigned char *data;
+ unsigned long flags;
+ int status;
+ int bytes_out = 0;
+
+ port_priv = usb_get_serial_port_data(port);
+
+ if (port_priv->write_urb == NULL) {
+ dev_err(&port->dev, "%s - no output urb\n", __func__);
+ return 0;
+ }
+ write_urb = port_priv->write_urb;
+
+ count = min(count, QT2_WRITE_BUFFER_SIZE - QT2_WRITE_CONTROL_SIZE);
+
+ data = write_urb->transfer_buffer;
+ spin_lock_irqsave(&port_priv->urb_lock, flags);
+ if (port_priv->urb_in_use == true) {
+ dev_err(&port->dev, "qt2_write - urb is in use\n");
+ goto write_out;
+ }
+
+ *data++ = QT2_CONTROL_BYTE;
+ *data++ = QT2_CONTROL_BYTE;
+ *data++ = port_priv->device_port;
+ put_unaligned_le16(count, data);
+ data += 2;
+ memcpy(data, buf, count);
+
+ write_urb->transfer_buffer_length = count + QT2_WRITE_CONTROL_SIZE;
+
+ status = usb_submit_urb(write_urb, GFP_ATOMIC);
+ if (status == 0) {
+ port_priv->urb_in_use = true;
+ bytes_out += count;
+ }
+
+write_out:
+ spin_unlock_irqrestore(&port_priv->urb_lock, flags);
+ return bytes_out;
+}
+
+
+static struct usb_serial_driver qt2_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "quatech-serial",
+ },
+ .description = DRIVER_DESC,
+ .id_table = id_table,
+ .open = qt2_open,
+ .close = qt2_close,
+ .write = qt2_write,
+ .write_room = qt2_write_room,
+ .calc_num_ports = qt2_calc_num_ports,
+ .attach = qt2_attach,
+ .release = qt2_release,
+ .disconnect = qt2_disconnect,
+ .port_probe = qt2_port_probe,
+ .port_remove = qt2_port_remove,
+ .dtr_rts = qt2_dtr_rts,
+ .break_ctl = qt2_break_ctl,
+ .tiocmget = qt2_tiocmget,
+ .tiocmset = qt2_tiocmset,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
+ .ioctl = qt2_ioctl,
+ .set_termios = qt2_set_termios,
+};
+
+static struct usb_serial_driver *const serial_drivers[] = {
+ &qt2_device, NULL
+};
+
+module_usb_serial_driver(serial_drivers, id_table);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index a36e2313eed..b2dff0f1474 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -62,11 +62,11 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/gfp.h>
-#include <linux/init.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
@@ -81,11 +81,9 @@
#define CONFIG_USB_SERIAL_SAFE_PADDED 0
#endif
-static int debug;
-static int safe = 1;
-static int padded = CONFIG_USB_SERIAL_SAFE_PADDED;
+static bool safe = 1;
+static bool padded = CONFIG_USB_SERIAL_SAFE_PADDED;
-#define DRIVER_VERSION "v0.1"
#define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com, Johan Hovold <jhovold@gmail.com>"
#define DRIVER_DESC "USB Safe Encapsulated Serial"
@@ -93,16 +91,6 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-static __u16 vendor; /* no default */
-static __u16 product; /* no default */
-module_param(vendor, ushort, 0);
-MODULE_PARM_DESC(vendor, "User specified USB idVendor (required)");
-module_param(product, ushort, 0);
-MODULE_PARM_DESC(product, "User specified USB idProduct (required)");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
module_param(safe, bool, 0);
MODULE_PARM_DESC(safe, "Turn Safe Encapsulation On/Off");
@@ -136,7 +124,7 @@ MODULE_PARM_DESC(padded, "Pad to full wMaxPacketSize On/Off");
.bInterfaceClass = (ic), \
.bInterfaceSubClass = (isc),
-static struct usb_device_id id_table[] = {
+static const struct usb_device_id id_table[] = {
{MY_USB_DEVICE(0x49f, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Itsy */
{MY_USB_DEVICE(0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Calypso */
{MY_USB_DEVICE(0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Iris */
@@ -144,21 +132,11 @@ static struct usb_device_id id_table[] = {
{MY_USB_DEVICE(0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */
{MY_USB_DEVICE(0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */
{MY_USB_DEVICE(0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Sharp tmp */
- /* extra null entry for module vendor/produc parameters */
- {MY_USB_DEVICE(0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
{} /* terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver safe_driver = {
- .name = "safe_serial",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
static const __u16 crc10_table[256] = {
0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff,
0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
@@ -219,38 +197,31 @@ static void safe_process_read_urb(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
unsigned char length = urb->actual_length;
int actual_length;
- struct tty_struct *tty;
__u16 fcs;
if (!length)
return;
- tty = tty_port_tty_get(&port->port);
- if (!tty)
- return;
-
if (!safe)
goto out;
fcs = fcs_compute10(data, length, CRC10_INITFCS);
if (fcs) {
dev_err(&port->dev, "%s - bad CRC %x\n", __func__, fcs);
- goto err;
+ return;
}
actual_length = data[length - 2] >> 2;
if (actual_length > (length - 2)) {
dev_err(&port->dev, "%s - inconsistent lengths %d:%d\n",
__func__, actual_length, length);
- goto err;
+ return;
}
dev_info(&urb->dev->dev, "%s - actual: %d\n", __func__, actual_length);
length = actual_length;
out:
- tty_insert_flip_string(tty, data, length);
- tty_flip_buffer_push(tty);
-err:
- tty_kref_put(tty);
+ tty_insert_flip_string(&port->port, data, length);
+ tty_flip_buffer_push(&port->port);
}
static int safe_prepare_write_buffer(struct usb_serial_port *port,
@@ -291,7 +262,19 @@ static int safe_prepare_write_buffer(struct usb_serial_port *port,
static int safe_startup(struct usb_serial *serial)
{
- switch (serial->interface->cur_altsetting->desc.bInterfaceProtocol) {
+ struct usb_interface_descriptor *desc;
+
+ if (serial->dev->descriptor.bDeviceClass != CDC_DEVICE_CLASS)
+ return -ENODEV;
+
+ desc = &serial->interface->cur_altsetting->desc;
+
+ if (desc->bInterfaceClass != LINEO_INTERFACE_CLASS)
+ return -ENODEV;
+ if (desc->bInterfaceSubClass != LINEO_INTERFACE_SUBCLASS_SAFESERIAL)
+ return -ENODEV;
+
+ switch (desc->bInterfaceProtocol) {
case LINEO_SAFESERIAL_CRC:
break;
case LINEO_SAFESERIAL_CRC_PADDED:
@@ -309,53 +292,14 @@ static struct usb_serial_driver safe_device = {
.name = "safe_serial",
},
.id_table = id_table,
- .usb_driver = &safe_driver,
.num_ports = 1,
.process_read_urb = safe_process_read_urb,
.prepare_write_buffer = safe_prepare_write_buffer,
.attach = safe_startup,
};
-static int __init safe_init(void)
-{
- int i, retval;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- /* if we have vendor / product parameters patch them into id list */
- if (vendor || product) {
- printk(KERN_INFO KBUILD_MODNAME ": vendor: %x product: %x\n",
- vendor, product);
-
- for (i = 0; i < ARRAY_SIZE(id_table); i++) {
- if (!id_table[i].idVendor && !id_table[i].idProduct) {
- id_table[i].idVendor = vendor;
- id_table[i].idProduct = product;
- break;
- }
- }
- }
-
- retval = usb_serial_register(&safe_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&safe_driver);
- if (retval)
- goto failed_usb_register;
-
- return 0;
-failed_usb_register:
- usb_serial_deregister(&safe_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit safe_exit(void)
-{
- usb_deregister(&safe_driver);
- usb_serial_deregister(&safe_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &safe_device, NULL
+};
-module_init(safe_init);
-module_exit(safe_exit);
+module_usb_serial_driver(serial_drivers, id_table);
diff --git a/drivers/usb/serial/sam-ba.c b/drivers/usb/serial/sam-ba.c
deleted file mode 100644
index e3bba64afc5..00000000000
--- a/drivers/usb/serial/sam-ba.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Atmel SAM Boot Assistant (SAM-BA) driver
- *
- * Copyright (C) 2010 Johan Hovold <jhovold@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/tty.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-
-
-#define DRIVER_VERSION "v1.0"
-#define DRIVER_AUTHOR "Johan Hovold <jhovold@gmail.com>"
-#define DRIVER_DESC "Atmel SAM Boot Assistant (SAM-BA) driver"
-
-#define SAMBA_VENDOR_ID 0x3eb
-#define SAMBA_PRODUCT_ID 0x6124
-
-
-static int debug;
-
-static const struct usb_device_id id_table[] = {
- /*
- * NOTE: Only match the CDC Data interface.
- */
- { USB_DEVICE_AND_INTERFACE_INFO(SAMBA_VENDOR_ID, SAMBA_PRODUCT_ID,
- USB_CLASS_CDC_DATA, 0, 0) },
- { }
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static struct usb_driver samba_driver = {
- .name = "sam-ba",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
-
-/*
- * NOTE: The SAM-BA firmware cannot handle merged write requests so we cannot
- * use the generic write implementation (which uses the port write fifo).
- */
-static int samba_write(struct tty_struct *tty, struct usb_serial_port *port,
- const unsigned char *buf, int count)
-{
- struct urb *urb;
- unsigned long flags;
- int result;
- int i;
-
- if (!count)
- return 0;
-
- count = min_t(int, count, port->bulk_out_size);
-
- spin_lock_irqsave(&port->lock, flags);
- if (!port->write_urbs_free) {
- spin_unlock_irqrestore(&port->lock, flags);
- return 0;
- }
- i = find_first_bit(&port->write_urbs_free,
- ARRAY_SIZE(port->write_urbs));
- __clear_bit(i, &port->write_urbs_free);
- port->tx_bytes += count;
- spin_unlock_irqrestore(&port->lock, flags);
-
- urb = port->write_urbs[i];
- memcpy(urb->transfer_buffer, buf, count);
- urb->transfer_buffer_length = count;
- usb_serial_debug_data(debug, &port->dev, __func__, count,
- urb->transfer_buffer);
- result = usb_submit_urb(urb, GFP_ATOMIC);
- if (result) {
- dev_err(&port->dev, "%s - error submitting urb: %d\n",
- __func__, result);
- spin_lock_irqsave(&port->lock, flags);
- __set_bit(i, &port->write_urbs_free);
- port->tx_bytes -= count;
- spin_unlock_irqrestore(&port->lock, flags);
-
- return result;
- }
-
- return count;
-}
-
-static int samba_write_room(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- unsigned long flags;
- unsigned long free;
- int count;
- int room;
-
- spin_lock_irqsave(&port->lock, flags);
- free = port->write_urbs_free;
- spin_unlock_irqrestore(&port->lock, flags);
-
- count = hweight_long(free);
- room = count * port->bulk_out_size;
-
- dbg("%s - returns %d", __func__, room);
-
- return room;
-}
-
-static int samba_chars_in_buffer(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- unsigned long flags;
- int chars;
-
- spin_lock_irqsave(&port->lock, flags);
- chars = port->tx_bytes;
- spin_unlock_irqrestore(&port->lock, flags);
-
- dbg("%s - returns %d", __func__, chars);
-
- return chars;
-}
-
-static void samba_write_bulk_callback(struct urb *urb)
-{
- struct usb_serial_port *port = urb->context;
- unsigned long flags;
- int i;
-
- dbg("%s - port %d", __func__, port->number);
-
- for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) {
- if (port->write_urbs[i] == urb)
- break;
- }
- spin_lock_irqsave(&port->lock, flags);
- __set_bit(i, &port->write_urbs_free);
- port->tx_bytes -= urb->transfer_buffer_length;
- spin_unlock_irqrestore(&port->lock, flags);
-
- if (urb->status)
- dbg("%s - non-zero urb status: %d", __func__, urb->status);
-
- usb_serial_port_softint(port);
-}
-
-static struct usb_serial_driver samba_device = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "sam-ba",
- },
- .usb_driver = &samba_driver,
- .id_table = id_table,
- .num_ports = 1,
- .bulk_in_size = 512,
- .bulk_out_size = 2048,
- .write = samba_write,
- .write_room = samba_write_room,
- .chars_in_buffer = samba_chars_in_buffer,
- .write_bulk_callback = samba_write_bulk_callback,
- .throttle = usb_serial_generic_throttle,
- .unthrottle = usb_serial_generic_unthrottle,
-};
-
-static int __init samba_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&samba_device);
- if (retval)
- return retval;
-
- retval = usb_register(&samba_driver);
- if (retval) {
- usb_serial_deregister(&samba_device);
- return retval;
- }
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ": "
- DRIVER_DESC "\n");
- return 0;
-}
-
-static void __exit samba_exit(void)
-{
- usb_deregister(&samba_driver);
- usb_serial_deregister(&samba_device);
-}
-
-module_init(samba_init);
-module_exit(samba_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable verbose debugging messages");
diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c
deleted file mode 100644
index cb8195cabfd..00000000000
--- a/drivers/usb/serial/siemens_mpi.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Siemens USB-MPI Serial USB driver
- *
- * Copyright (C) 2005 Thomas Hergenhahn <thomas.hergenhahn@suse.de>
- * Copyright (C) 2005,2008 Greg Kroah-Hartman <gregkh@suse.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-
-/* Version Information */
-#define DRIVER_VERSION "Version 0.1 09/26/2005"
-#define DRIVER_AUTHOR "Thomas Hergenhahn@web.de http://libnodave.sf.net"
-#define DRIVER_DESC "Driver for Siemens USB/MPI adapter"
-
-
-static const struct usb_device_id id_table[] = {
- /* Vendor and product id for 6ES7-972-0CB20-0XA0 */
- { USB_DEVICE(0x908, 0x0004) },
- { },
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static struct usb_driver siemens_usb_mpi_driver = {
- .name = "siemens_mpi",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
-static struct usb_serial_driver siemens_usb_mpi_device = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "siemens_mpi",
- },
- .id_table = id_table,
- .num_ports = 1,
-};
-
-static int __init siemens_usb_mpi_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&siemens_usb_mpi_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&siemens_usb_mpi_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO DRIVER_DESC "\n");
- printk(KERN_INFO DRIVER_VERSION " " DRIVER_AUTHOR "\n");
- return retval;
-failed_usb_register:
- usb_serial_deregister(&siemens_usb_mpi_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit siemens_usb_mpi_exit(void)
-{
- usb_deregister(&siemens_usb_mpi_driver);
- usb_serial_deregister(&siemens_usb_mpi_device);
-}
-
-module_init(siemens_usb_mpi_init);
-module_exit(siemens_usb_mpi_exit);
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 7481ff8a49e..6f7f01eb556 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -18,7 +18,7 @@
*/
/* Uncomment to log function calls */
/* #define DEBUG */
-#define DRIVER_VERSION "v.1.7.16"
+
#define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer"
#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
@@ -46,8 +46,7 @@
allocations > PAGE_SIZE and the number of packets in a page
is an integer 512 is the largest possible packet on EHCI */
-static int debug;
-static int nmea;
+static bool nmea;
/* Used in interface blacklisting */
struct sierra_iface_info {
@@ -59,13 +58,12 @@ struct sierra_intf_private {
spinlock_t susp_lock;
unsigned int suspended:1;
int in_flight;
+ unsigned int open_ports;
};
static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
{
- int result;
- dev_dbg(&udev->dev, "%s\n", __func__);
- result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
SWIMS_USB_REQUEST_SetPower, /* __u8 request */
USB_TYPE_VENDOR, /* __u8 request type */
swiState, /* __u16 value */
@@ -73,14 +71,11 @@ static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
NULL, /* void *data */
0, /* __u16 size */
USB_CTRL_SET_TIMEOUT); /* int timeout */
- return result;
}
static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
{
- int result;
- dev_dbg(&udev->dev, "%s\n", __func__);
- result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
SWIMS_USB_REQUEST_SetNmea, /* __u8 request */
USB_TYPE_VENDOR, /* __u8 request type */
enable, /* __u16 value */
@@ -88,7 +83,6 @@ static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
NULL, /* void *data */
0, /* __u16 size */
USB_CTRL_SET_TIMEOUT); /* int timeout */
- return result;
}
static int sierra_calc_num_ports(struct usb_serial *serial)
@@ -96,8 +90,6 @@ static int sierra_calc_num_ports(struct usb_serial *serial)
int num_ports = 0;
u8 ifnum, numendpoints;
- dev_dbg(&serial->dev->dev, "%s\n", __func__);
-
ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
numendpoints = serial->interface->cur_altsetting->desc.bNumEndpoints;
@@ -150,7 +142,6 @@ static int sierra_calc_interface(struct usb_serial *serial)
int interface;
struct usb_interface *p_interface;
struct usb_host_interface *p_host_interface;
- dev_dbg(&serial->dev->dev, "%s\n", __func__);
/* Get the interface structure pointer from the serial struct */
p_interface = serial->interface;
@@ -171,13 +162,11 @@ static int sierra_probe(struct usb_serial *serial,
{
int result = 0;
struct usb_device *udev;
- struct sierra_intf_private *data;
u8 ifnum;
udev = serial->dev;
- dev_dbg(&udev->dev, "%s\n", __func__);
-
ifnum = sierra_calc_interface(serial);
+
/*
* If this interface supports more than 1 alternate
* select the 2nd one
@@ -199,11 +188,6 @@ static int sierra_probe(struct usb_serial *serial,
return -ENODEV;
}
- data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
- spin_lock_init(&data->susp_lock);
-
return result;
}
@@ -221,7 +205,7 @@ static const struct sierra_iface_info typeB_interface_list = {
};
/* 'blacklist' of interfaces not served by this driver */
-static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 };
+static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11, 19, 20 };
static const struct sierra_iface_info direct_ip_interface_blacklist = {
.infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces),
.ifaceinfo = direct_ip_non_serial_ifaces,
@@ -301,7 +285,13 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
},
- { USB_DEVICE(0x413C, 0x08133) }, /* Dell Computer Corp. Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port */
+ /* AT&T Direct IP LTE modems */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF),
+ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+ },
+ { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */
+ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+ },
{ }
};
@@ -326,7 +316,6 @@ struct sierra_port_private {
int dsr_state;
int dcd_state;
int ri_state;
- unsigned int opened:1;
};
static int sierra_send_setup(struct usb_serial_port *port)
@@ -338,8 +327,6 @@ static int sierra_send_setup(struct usb_serial_port *port)
int do_send = 0;
int retval;
- dev_dbg(&port->dev, "%s\n", __func__);
-
portdata = usb_get_serial_port_data(port);
if (portdata->dtr_state)
@@ -373,29 +360,23 @@ static int sierra_send_setup(struct usb_serial_port *port)
if (!do_send)
return 0;
- usb_autopm_get_interface(serial->interface);
- retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ retval = usb_autopm_get_interface(serial->interface);
+ if (retval < 0)
+ return retval;
+
+ retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
0x22, 0x21, val, interface, NULL, 0, USB_CTRL_SET_TIMEOUT);
usb_autopm_put_interface(serial->interface);
return retval;
}
-static void sierra_set_termios(struct tty_struct *tty,
- struct usb_serial_port *port, struct ktermios *old_termios)
-{
- dev_dbg(&port->dev, "%s\n", __func__);
- tty_termios_copy_hw(tty->termios, old_termios);
- sierra_send_setup(port);
-}
-
-static int sierra_tiocmget(struct tty_struct *tty, struct file *file)
+static int sierra_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
unsigned int value;
struct sierra_port_private *portdata;
- dev_dbg(&port->dev, "%s\n", __func__);
portdata = usb_get_serial_port_data(port);
value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
@@ -408,7 +389,7 @@ static int sierra_tiocmget(struct tty_struct *tty, struct file *file)
return value;
}
-static int sierra_tiocmset(struct tty_struct *tty, struct file *file,
+static int sierra_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
@@ -430,10 +411,7 @@ static int sierra_tiocmset(struct tty_struct *tty, struct file *file,
static void sierra_release_urb(struct urb *urb)
{
- struct usb_serial_port *port;
if (urb) {
- port = urb->context;
- dev_dbg(&port->dev, "%s: %p\n", __func__, urb);
kfree(urb->transfer_buffer);
usb_free_urb(urb);
}
@@ -446,8 +424,7 @@ static void sierra_outdat_callback(struct urb *urb)
struct sierra_intf_private *intfdata;
int status = urb->status;
- dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number);
- intfdata = port->serial->private;
+ intfdata = usb_get_serial_data(port->serial);
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree(urb->transfer_buffer);
@@ -484,7 +461,7 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
return 0;
portdata = usb_get_serial_port_data(port);
- intfdata = serial->private;
+ intfdata = usb_get_serial_data(serial);
dev_dbg(&port->dev, "%s: write (%zd bytes)\n", __func__, writesize);
spin_lock_irqsave(&portdata->lock, flags);
@@ -510,21 +487,19 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
buffer = kmalloc(writesize, GFP_ATOMIC);
if (!buffer) {
- dev_err(&port->dev, "out of memory\n");
retval = -ENOMEM;
goto error_no_buffer;
}
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
- dev_err(&port->dev, "no more free urbs\n");
retval = -ENOMEM;
goto error_no_urb;
}
memcpy(buffer, buf, writesize);
- usb_serial_debug_data(debug, &port->dev, __func__, writesize, buffer);
+ usb_serial_debug_data(&port->dev, __func__, writesize, buffer);
usb_fill_bulk_urb(urb, serial->dev,
usb_sndbulkpipe(serial->dev,
@@ -582,30 +557,23 @@ static void sierra_indat_callback(struct urb *urb)
int err;
int endpoint;
struct usb_serial_port *port;
- struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
endpoint = usb_pipeendpoint(urb->pipe);
port = urb->context;
- dev_dbg(&port->dev, "%s: %p\n", __func__, urb);
-
if (status) {
dev_dbg(&port->dev, "%s: nonzero status: %d on"
" endpoint %02x\n", __func__, status, endpoint);
} else {
if (urb->actual_length) {
- tty = tty_port_tty_get(&port->port);
- if (tty) {
- tty_insert_flip_string(tty, data,
- urb->actual_length);
- tty_flip_buffer_push(tty);
-
- tty_kref_put(tty);
- usb_serial_debug_data(debug, &port->dev,
- __func__, urb->actual_length, data);
- }
+ tty_insert_flip_string(&port->port, data,
+ urb->actual_length);
+ tty_flip_buffer_push(&port->port);
+
+ usb_serial_debug_data(&port->dev, __func__,
+ urb->actual_length, data);
} else {
dev_dbg(&port->dev, "%s: empty read urb"
" received\n", __func__);
@@ -648,7 +616,6 @@ static void sierra_instat_callback(struct urb *urb)
unsigned char signals = *((unsigned char *)
urb->transfer_buffer +
sizeof(struct usb_ctrlrequest));
- struct tty_struct *tty;
dev_dbg(&port->dev, "%s: signal x%x\n", __func__,
signals);
@@ -659,11 +626,8 @@ static void sierra_instat_callback(struct urb *urb)
portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
portdata->ri_state = ((signals & 0x08) ? 1 : 0);
- tty = tty_port_tty_get(&port->port);
- if (tty && !C_CLOCAL(tty) &&
- old_dcd_state && !portdata->dcd_state)
- tty_hangup(tty);
- tty_kref_put(tty);
+ if (old_dcd_state && !portdata->dcd_state)
+ tty_port_tty_hangup(&port->port, true);
} else {
dev_dbg(&port->dev, "%s: type %x req %x\n",
__func__, req_pkt->bRequestType,
@@ -675,7 +639,6 @@ static void sierra_instat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving IRQ data */
if (status != -ESHUTDOWN && status != -ENOENT) {
usb_mark_last_busy(serial->dev);
- urb->dev = serial->dev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err && err != -EPERM)
dev_err(&port->dev, "%s: resubmit intr urb "
@@ -689,8 +652,6 @@ static int sierra_write_room(struct tty_struct *tty)
struct sierra_port_private *portdata = usb_get_serial_port_data(port);
unsigned long flags;
- dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number);
-
/* try to give a good number back based on if we have any free urbs at
* this point in time */
spin_lock_irqsave(&portdata->lock, flags);
@@ -704,6 +665,23 @@ static int sierra_write_room(struct tty_struct *tty)
return 2048;
}
+static int sierra_chars_in_buffer(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ unsigned long flags;
+ int chars;
+
+ /* NOTE: This overcounts somewhat. */
+ spin_lock_irqsave(&portdata->lock, flags);
+ chars = portdata->outstanding_urbs * MAX_TRANSFER;
+ spin_unlock_irqrestore(&portdata->lock, flags);
+
+ dev_dbg(&port->dev, "%s - %d\n", __func__, chars);
+
+ return chars;
+}
+
static void sierra_stop_rx_urbs(struct usb_serial_port *port)
{
int i;
@@ -759,15 +737,9 @@ static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint,
struct urb *urb;
u8 *buf;
- if (endpoint == -1)
- return NULL;
-
urb = usb_alloc_urb(0, mem_flags);
- if (urb == NULL) {
- dev_dbg(&serial->dev->dev, "%s: alloc for endpoint %d failed\n",
- __func__, endpoint);
+ if (!urb)
return NULL;
- }
buf = kmalloc(len, mem_flags);
if (buf) {
@@ -776,13 +748,9 @@ static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint,
usb_sndbulkpipe(serial->dev, endpoint) | dir,
buf, len, callback, ctx);
- /* debug */
dev_dbg(&serial->dev->dev, "%s %c u : %p d:%p\n", __func__,
dir == USB_DIR_IN ? 'i' : 'o', urb, buf);
} else {
- dev_dbg(&serial->dev->dev, "%s %c u:%p d:%p\n", __func__,
- dir == USB_DIR_IN ? 'i' : 'o', urb, buf);
-
sierra_release_urb(urb);
urb = NULL;
}
@@ -795,43 +763,48 @@ static void sierra_close(struct usb_serial_port *port)
int i;
struct usb_serial *serial = port->serial;
struct sierra_port_private *portdata;
- struct sierra_intf_private *intfdata = port->serial->private;
-
+ struct sierra_intf_private *intfdata = usb_get_serial_data(serial);
+ struct urb *urb;
- dev_dbg(&port->dev, "%s\n", __func__);
portdata = usb_get_serial_port_data(port);
- portdata->rts_state = 0;
- portdata->dtr_state = 0;
+ /*
+ * Need to take susp_lock to make sure port is not already being
+ * resumed, but no need to hold it due to ASYNC_INITIALIZED.
+ */
+ spin_lock_irq(&intfdata->susp_lock);
+ if (--intfdata->open_ports == 0)
+ serial->interface->needs_remote_wakeup = 0;
+ spin_unlock_irq(&intfdata->susp_lock);
- if (serial->dev) {
- mutex_lock(&serial->disc_mutex);
- if (!serial->disconnected) {
- serial->interface->needs_remote_wakeup = 0;
- usb_autopm_get_interface(serial->interface);
- sierra_send_setup(port);
- }
- mutex_unlock(&serial->disc_mutex);
- spin_lock_irq(&intfdata->susp_lock);
- portdata->opened = 0;
- spin_unlock_irq(&intfdata->susp_lock);
+ for (;;) {
+ urb = usb_get_from_anchor(&portdata->delayed);
+ if (!urb)
+ break;
+ kfree(urb->transfer_buffer);
+ usb_free_urb(urb);
+ usb_autopm_put_interface_async(serial->interface);
+ spin_lock(&portdata->lock);
+ portdata->outstanding_urbs--;
+ spin_unlock(&portdata->lock);
+ }
+ sierra_stop_rx_urbs(port);
+ usb_kill_anchored_urbs(&portdata->active);
- /* Stop reading urbs */
- sierra_stop_rx_urbs(port);
- /* .. and release them */
- for (i = 0; i < portdata->num_in_urbs; i++) {
- sierra_release_urb(portdata->in_urbs[i]);
- portdata->in_urbs[i] = NULL;
- }
+ for (i = 0; i < portdata->num_in_urbs; i++) {
+ sierra_release_urb(portdata->in_urbs[i]);
+ portdata->in_urbs[i] = NULL;
}
+
+ usb_autopm_get_interface_no_resume(serial->interface);
}
static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct sierra_port_private *portdata;
struct usb_serial *serial = port->serial;
- struct sierra_intf_private *intfdata = serial->private;
+ struct sierra_intf_private *intfdata = usb_get_serial_data(serial);
int i;
int err;
int endpoint;
@@ -839,13 +812,6 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port)
portdata = usb_get_serial_port_data(port);
- dev_dbg(&port->dev, "%s\n", __func__);
-
- /* Set some sane defaults */
- portdata->rts_state = 1;
- portdata->dtr_state = 1;
-
-
endpoint = port->bulk_in_endpointAddress;
for (i = 0; i < portdata->num_in_urbs; i++) {
urb = sierra_setup_urb(serial, endpoint, USB_DIR_IN, port,
@@ -858,51 +824,51 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port)
usb_sndbulkpipe(serial->dev, endpoint) | USB_DIR_IN);
err = sierra_submit_rx_urbs(port, GFP_KERNEL);
- if (err) {
- /* get rid of everything as in close */
- sierra_close(port);
- /* restore balance for autopm */
- usb_autopm_put_interface(serial->interface);
- return err;
- }
- sierra_send_setup(port);
+ if (err)
+ goto err_submit;
- serial->interface->needs_remote_wakeup = 1;
spin_lock_irq(&intfdata->susp_lock);
- portdata->opened = 1;
+ if (++intfdata->open_ports == 1)
+ serial->interface->needs_remote_wakeup = 1;
spin_unlock_irq(&intfdata->susp_lock);
usb_autopm_put_interface(serial->interface);
return 0;
+
+err_submit:
+ sierra_stop_rx_urbs(port);
+
+ for (i = 0; i < portdata->num_in_urbs; i++) {
+ sierra_release_urb(portdata->in_urbs[i]);
+ portdata->in_urbs[i] = NULL;
+ }
+
+ return err;
}
static void sierra_dtr_rts(struct usb_serial_port *port, int on)
{
- struct usb_serial *serial = port->serial;
struct sierra_port_private *portdata;
portdata = usb_get_serial_port_data(port);
portdata->rts_state = on;
portdata->dtr_state = on;
- if (serial->dev) {
- mutex_lock(&serial->disc_mutex);
- if (!serial->disconnected)
- sierra_send_setup(port);
- mutex_unlock(&serial->disc_mutex);
- }
+ sierra_send_setup(port);
}
static int sierra_startup(struct usb_serial *serial)
{
- struct usb_serial_port *port;
- struct sierra_port_private *portdata;
- struct sierra_iface_info *himemoryp = NULL;
- int i;
- u8 ifnum;
+ struct sierra_intf_private *intfdata;
- dev_dbg(&serial->dev->dev, "%s\n", __func__);
+ intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL);
+ if (!intfdata)
+ return -ENOMEM;
+
+ spin_lock_init(&intfdata->susp_lock);
+
+ usb_set_serial_data(serial, intfdata);
/* Set Device mode to D0 */
sierra_set_power_state(serial->dev, 0x0000);
@@ -911,70 +877,72 @@ static int sierra_startup(struct usb_serial *serial)
if (nmea)
sierra_vsc_set_nmea(serial->dev, 1);
- /* Now setup per port private data */
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
- if (!portdata) {
- dev_dbg(&port->dev, "%s: kmalloc for "
- "sierra_port_private (%d) failed!\n",
- __func__, i);
- return -ENOMEM;
- }
- spin_lock_init(&portdata->lock);
- init_usb_anchor(&portdata->active);
- init_usb_anchor(&portdata->delayed);
- ifnum = i;
- /* Assume low memory requirements */
- portdata->num_out_urbs = N_OUT_URB;
- portdata->num_in_urbs = N_IN_URB;
-
- /* Determine actual memory requirements */
- if (serial->num_ports == 1) {
- /* Get interface number for composite device */
- ifnum = sierra_calc_interface(serial);
- himemoryp =
- (struct sierra_iface_info *)&typeB_interface_list;
- if (is_himemory(ifnum, himemoryp)) {
- portdata->num_out_urbs = N_OUT_URB_HM;
- portdata->num_in_urbs = N_IN_URB_HM;
- }
- }
- else {
- himemoryp =
- (struct sierra_iface_info *)&typeA_interface_list;
- if (is_himemory(i, himemoryp)) {
- portdata->num_out_urbs = N_OUT_URB_HM;
- portdata->num_in_urbs = N_IN_URB_HM;
- }
- }
- dev_dbg(&serial->dev->dev,
- "Memory usage (urbs) interface #%d, in=%d, out=%d\n",
- ifnum,portdata->num_in_urbs, portdata->num_out_urbs );
- /* Set the port private data pointer */
- usb_set_serial_port_data(port, portdata);
- }
-
return 0;
}
static void sierra_release(struct usb_serial *serial)
{
- int i;
- struct usb_serial_port *port;
+ struct sierra_intf_private *intfdata;
+
+ intfdata = usb_get_serial_data(serial);
+ kfree(intfdata);
+}
+
+static int sierra_port_probe(struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
struct sierra_port_private *portdata;
+ const struct sierra_iface_info *himemoryp;
+ u8 ifnum;
- dev_dbg(&serial->dev->dev, "%s\n", __func__);
+ portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+ if (!portdata)
+ return -ENOMEM;
- for (i = 0; i < serial->num_ports; ++i) {
- port = serial->port[i];
- if (!port)
- continue;
- portdata = usb_get_serial_port_data(port);
- if (!portdata)
- continue;
- kfree(portdata);
+ spin_lock_init(&portdata->lock);
+ init_usb_anchor(&portdata->active);
+ init_usb_anchor(&portdata->delayed);
+
+ /* Assume low memory requirements */
+ portdata->num_out_urbs = N_OUT_URB;
+ portdata->num_in_urbs = N_IN_URB;
+
+ /* Determine actual memory requirements */
+ if (serial->num_ports == 1) {
+ /* Get interface number for composite device */
+ ifnum = sierra_calc_interface(serial);
+ himemoryp = &typeB_interface_list;
+ } else {
+ /* This is really the usb-serial port number of the interface
+ * rather than the interface number.
+ */
+ ifnum = port->port_number;
+ himemoryp = &typeA_interface_list;
}
+
+ if (is_himemory(ifnum, himemoryp)) {
+ portdata->num_out_urbs = N_OUT_URB_HM;
+ portdata->num_in_urbs = N_IN_URB_HM;
+ }
+
+ dev_dbg(&port->dev,
+ "Memory usage (urbs) interface #%d, in=%d, out=%d\n",
+ ifnum, portdata->num_in_urbs, portdata->num_out_urbs);
+
+ usb_set_serial_port_data(port, portdata);
+
+ return 0;
+}
+
+static int sierra_port_remove(struct usb_serial_port *port)
+{
+ struct sierra_port_private *portdata;
+
+ portdata = usb_get_serial_port_data(port);
+ usb_set_serial_port_data(port, NULL);
+ kfree(portdata);
+
+ return 0;
}
#ifdef CONFIG_PM
@@ -988,6 +956,8 @@ static void stop_read_write_urbs(struct usb_serial *serial)
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
portdata = usb_get_serial_port_data(port);
+ if (!portdata)
+ continue;
sierra_stop_rx_urbs(port);
usb_kill_anchored_urbs(&portdata->active);
}
@@ -995,58 +965,84 @@ static void stop_read_write_urbs(struct usb_serial *serial)
static int sierra_suspend(struct usb_serial *serial, pm_message_t message)
{
- struct sierra_intf_private *intfdata;
- int b;
-
- if (message.event & PM_EVENT_AUTO) {
- intfdata = serial->private;
- spin_lock_irq(&intfdata->susp_lock);
- b = intfdata->in_flight;
+ struct sierra_intf_private *intfdata = usb_get_serial_data(serial);
- if (b) {
+ spin_lock_irq(&intfdata->susp_lock);
+ if (PMSG_IS_AUTO(message)) {
+ if (intfdata->in_flight) {
spin_unlock_irq(&intfdata->susp_lock);
return -EBUSY;
- } else {
- intfdata->suspended = 1;
- spin_unlock_irq(&intfdata->susp_lock);
}
}
+ intfdata->suspended = 1;
+ spin_unlock_irq(&intfdata->susp_lock);
+
stop_read_write_urbs(serial);
return 0;
}
+/* Caller must hold susp_lock. */
+static int sierra_submit_delayed_urbs(struct usb_serial_port *port)
+{
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ struct sierra_intf_private *intfdata;
+ struct urb *urb;
+ int ec = 0;
+ int err;
+
+ intfdata = usb_get_serial_data(port->serial);
+
+ for (;;) {
+ urb = usb_get_from_anchor(&portdata->delayed);
+ if (!urb)
+ break;
+
+ usb_anchor_urb(urb, &portdata->active);
+ intfdata->in_flight++;
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err) {
+ dev_err(&port->dev, "%s - submit urb failed: %d",
+ __func__, err);
+ ec++;
+ intfdata->in_flight--;
+ usb_unanchor_urb(urb);
+ kfree(urb->transfer_buffer);
+ usb_free_urb(urb);
+
+ spin_lock(&portdata->lock);
+ portdata->outstanding_urbs--;
+ spin_unlock(&portdata->lock);
+ }
+ }
+
+ if (ec)
+ return -EIO;
+
+ return 0;
+}
+
static int sierra_resume(struct usb_serial *serial)
{
struct usb_serial_port *port;
- struct sierra_intf_private *intfdata = serial->private;
- struct sierra_port_private *portdata;
- struct urb *urb;
+ struct sierra_intf_private *intfdata = usb_get_serial_data(serial);
int ec = 0;
int i, err;
spin_lock_irq(&intfdata->susp_lock);
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
- portdata = usb_get_serial_port_data(port);
- while ((urb = usb_get_from_anchor(&portdata->delayed))) {
- usb_anchor_urb(urb, &portdata->active);
- intfdata->in_flight++;
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (err < 0) {
- intfdata->in_flight--;
- usb_unanchor_urb(urb);
- usb_scuttle_anchored_urbs(&portdata->delayed);
- break;
- }
- }
+ if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+ continue;
- if (portdata->opened) {
- err = sierra_submit_rx_urbs(port, GFP_ATOMIC);
- if (err)
- ec++;
- }
+ err = sierra_submit_delayed_urbs(port);
+ if (err)
+ ec++;
+
+ err = sierra_submit_rx_urbs(port, GFP_ATOMIC);
+ if (err)
+ ec++;
}
intfdata->suspended = 0;
spin_unlock_irq(&intfdata->susp_lock);
@@ -1054,30 +1050,11 @@ static int sierra_resume(struct usb_serial *serial)
return ec ? -EIO : 0;
}
-static int sierra_reset_resume(struct usb_interface *intf)
-{
- struct usb_serial *serial = usb_get_intfdata(intf);
- dev_err(&serial->dev->dev, "%s\n", __func__);
- return usb_serial_resume(intf);
-}
#else
#define sierra_suspend NULL
#define sierra_resume NULL
-#define sierra_reset_resume NULL
#endif
-static struct usb_driver sierra_driver = {
- .name = "sierra",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .reset_resume = sierra_reset_resume,
- .id_table = id_table,
- .no_dynamic_id = 1,
- .supports_autosuspend = 1,
-};
-
static struct usb_serial_driver sierra_device = {
.driver = {
.owner = THIS_MODULE,
@@ -1085,7 +1062,6 @@ static struct usb_serial_driver sierra_device = {
},
.description = "Sierra USB modem",
.id_table = id_table,
- .usb_driver = &sierra_driver,
.calc_num_ports = sierra_calc_num_ports,
.probe = sierra_probe,
.open = sierra_open,
@@ -1093,56 +1069,27 @@ static struct usb_serial_driver sierra_device = {
.dtr_rts = sierra_dtr_rts,
.write = sierra_write,
.write_room = sierra_write_room,
- .set_termios = sierra_set_termios,
+ .chars_in_buffer = sierra_chars_in_buffer,
.tiocmget = sierra_tiocmget,
.tiocmset = sierra_tiocmset,
.attach = sierra_startup,
.release = sierra_release,
+ .port_probe = sierra_port_probe,
+ .port_remove = sierra_port_remove,
.suspend = sierra_suspend,
.resume = sierra_resume,
.read_int_callback = sierra_instat_callback,
};
-/* Functions used by new usb-serial code. */
-static int __init sierra_init(void)
-{
- int retval;
- retval = usb_serial_register(&sierra_device);
- if (retval)
- goto failed_device_register;
-
-
- retval = usb_register(&sierra_driver);
- if (retval)
- goto failed_driver_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-
-failed_driver_register:
- usb_serial_deregister(&sierra_device);
-failed_device_register:
- return retval;
-}
-
-static void __exit sierra_exit(void)
-{
- usb_deregister(&sierra_driver);
- usb_serial_deregister(&sierra_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &sierra_device, NULL
+};
-module_init(sierra_init);
-module_exit(sierra_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
module_param(nmea, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(nmea, "NMEA streaming");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug messages");
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 765aa983bf5..ef0dbf0703c 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -1,7 +1,7 @@
/*
* spcp8x5 USB to serial adaptor driver
*
- * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com)
+ * Copyright (C) 2010-2013 Johan Hovold (jhovold@gmail.com)
* Copyright (C) 2006 Linxb (xubin.lin@worldplus.com.cn)
* Copyright (C) 2006 S1 Corp.
*
@@ -13,12 +13,9 @@
* 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.
- *
- *
*/
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -28,12 +25,10 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
+#define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver"
-/* Version Information */
-#define DRIVER_VERSION "v0.10"
-#define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver"
-
-static int debug;
+#define SPCP825_QUIRK_NO_UART_STATUS 0x01
+#define SPCP825_QUIRK_NO_WORK_MODE 0x02
#define SPCP8x5_007_VID 0x04FC
#define SPCP8x5_007_PID 0x0201
@@ -51,13 +46,15 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)},
{ USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)},
{ USB_DEVICE(SPCP8x5_008_VID, SPCP8x5_008_PID)},
- { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID)},
+ { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID),
+ .driver_info = SPCP825_QUIRK_NO_UART_STATUS |
+ SPCP825_QUIRK_NO_WORK_MODE },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
struct spcp8x5_usb_ctrl_arg {
- u8 type;
+ u8 type;
u8 cmd;
u8 cmd_type;
u16 value;
@@ -133,7 +130,7 @@ struct spcp8x5_usb_ctrl_arg {
/* how come ??? */
#define UART_STATE 0x08
-#define UART_STATE_TRANSIENT_MASK 0x74
+#define UART_STATE_TRANSIENT_MASK 0x75
#define UART_DCD 0x01
#define UART_DSR 0x02
#define UART_BREAK_ERROR 0x04
@@ -143,164 +140,122 @@ struct spcp8x5_usb_ctrl_arg {
#define UART_OVERRUN_ERROR 0x40
#define UART_CTS 0x80
-enum spcp8x5_type {
- SPCP825_007_TYPE,
- SPCP825_008_TYPE,
- SPCP825_PHILIP_TYPE,
- SPCP825_INTERMATIC_TYPE,
- SPCP835_TYPE,
-};
-
-static struct usb_driver spcp8x5_driver = {
- .name = "spcp8x5",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
+struct spcp8x5_private {
+ unsigned quirks;
+ spinlock_t lock;
+ u8 line_control;
};
+static int spcp8x5_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
+{
+ usb_set_serial_data(serial, (void *)id);
-struct spcp8x5_private {
- spinlock_t lock;
- enum spcp8x5_type type;
- wait_queue_head_t delta_msr_wait;
- u8 line_control;
- u8 line_status;
-};
+ return 0;
+}
-/* desc : when device plug in,this function would be called.
- * thanks to usb_serial subsystem,then do almost every things for us. And what
- * we should do just alloc the buffer */
-static int spcp8x5_startup(struct usb_serial *serial)
+static int spcp8x5_port_probe(struct usb_serial_port *port)
{
+ const struct usb_device_id *id = usb_get_serial_data(port->serial);
struct spcp8x5_private *priv;
- int i;
- enum spcp8x5_type type = SPCP825_007_TYPE;
- u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
-
- if (product == 0x0201)
- type = SPCP825_007_TYPE;
- else if (product == 0x0231)
- type = SPCP835_TYPE;
- else if (product == 0x0235)
- type = SPCP825_008_TYPE;
- else if (product == 0x0204)
- type = SPCP825_INTERMATIC_TYPE;
- else if (product == 0x0471 &&
- serial->dev->descriptor.idVendor == cpu_to_le16(0x081e))
- type = SPCP825_PHILIP_TYPE;
- dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);
-
- for (i = 0; i < serial->num_ports; ++i) {
- priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL);
- if (!priv)
- goto cleanup;
-
- spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
- priv->type = type;
- usb_set_serial_port_data(serial->port[i] , priv);
- }
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ spin_lock_init(&priv->lock);
+ priv->quirks = id->driver_info;
+
+ usb_set_serial_port_data(port, priv);
+
+ port->port.drain_delay = 256;
return 0;
-cleanup:
- for (--i; i >= 0; --i) {
- priv = usb_get_serial_port_data(serial->port[i]);
- kfree(priv);
- usb_set_serial_port_data(serial->port[i] , NULL);
- }
- return -ENOMEM;
}
-/* call when the device plug out. free all the memory alloced by probe */
-static void spcp8x5_release(struct usb_serial *serial)
+static int spcp8x5_port_remove(struct usb_serial_port *port)
{
- int i;
+ struct spcp8x5_private *priv;
+
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
- for (i = 0; i < serial->num_ports; i++)
- kfree(usb_get_serial_port_data(serial->port[i]));
+ return 0;
}
-/* set the modem control line of the device.
- * NOTE spcp825-007 not supported this */
-static int spcp8x5_set_ctrlLine(struct usb_device *dev, u8 value,
- enum spcp8x5_type type)
+static int spcp8x5_set_ctrl_line(struct usb_serial_port *port, u8 mcr)
{
+ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+ struct usb_device *dev = port->serial->dev;
int retval;
- u8 mcr = 0 ;
- if (type == SPCP825_007_TYPE)
+ if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)
return -EPERM;
- mcr = (unsigned short)value;
retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
SET_UART_STATUS_TYPE, SET_UART_STATUS,
mcr, 0x04, NULL, 0, 100);
- if (retval != 0)
- dev_dbg(&dev->dev, "usb_control_msg return %#x\n", retval);
+ if (retval != 0) {
+ dev_err(&port->dev, "failed to set control lines: %d\n",
+ retval);
+ }
return retval;
}
-/* get the modem status register of the device
- * NOTE spcp825-007 not supported this */
-static int spcp8x5_get_msr(struct usb_device *dev, u8 *status,
- enum spcp8x5_type type)
+static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status)
{
- u8 *status_buffer;
+ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+ struct usb_device *dev = port->serial->dev;
+ u8 *buf;
int ret;
- /* I return Permited not support here but seem inval device
- * is more fix */
- if (type == SPCP825_007_TYPE)
+ if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)
return -EPERM;
- if (status == NULL)
- return -EINVAL;
- status_buffer = kmalloc(1, GFP_KERNEL);
- if (!status_buffer)
+ buf = kzalloc(1, GFP_KERNEL);
+ if (!buf)
return -ENOMEM;
- status_buffer[0] = status[0];
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
GET_UART_STATUS, GET_UART_STATUS_TYPE,
- 0, GET_UART_STATUS_MSR, status_buffer, 1, 100);
+ 0, GET_UART_STATUS_MSR, buf, 1, 100);
if (ret < 0)
- dev_dbg(&dev->dev, "Get MSR = 0x%p failed (error = %d)",
- status_buffer, ret);
+ dev_err(&port->dev, "failed to get modem status: %d\n", ret);
- dev_dbg(&dev->dev, "0xc0:0x22:0:6 %d - 0x%p ", ret, status_buffer);
- status[0] = status_buffer[0];
- kfree(status_buffer);
+ dev_dbg(&port->dev, "0xc0:0x22:0:6 %d - 0x02%x\n", ret, *buf);
+ *status = *buf;
+ kfree(buf);
return ret;
}
-/* select the work mode.
- * NOTE this function not supported by spcp825-007 */
-static void spcp8x5_set_workMode(struct usb_device *dev, u16 value,
- u16 index, enum spcp8x5_type type)
+static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value,
+ u16 index)
{
+ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+ struct usb_device *dev = port->serial->dev;
int ret;
- /* I return Permited not support here but seem inval device
- * is more fix */
- if (type == SPCP825_007_TYPE)
+ if (priv->quirks & SPCP825_QUIRK_NO_WORK_MODE)
return;
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
SET_WORKING_MODE_TYPE, SET_WORKING_MODE,
value, index, NULL, 0, 100);
- dev_dbg(&dev->dev, "value = %#x , index = %#x\n", value, index);
+ dev_dbg(&port->dev, "value = %#x , index = %#x\n", value, index);
if (ret < 0)
- dev_dbg(&dev->dev,
- "RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret);
+ dev_err(&port->dev, "failed to set work mode: %d\n", ret);
}
static int spcp8x5_carrier_raised(struct usb_serial_port *port)
{
- struct spcp8x5_private *priv = usb_get_serial_port_data(port);
- if (priv->line_status & MSR_STATUS_LINE_DCD)
+ u8 msr;
+ int ret;
+
+ ret = spcp8x5_get_msr(port, &msr);
+ if (ret || msr & MSR_STATUS_LINE_DCD)
return 1;
+
return 0;
}
@@ -319,51 +274,46 @@ static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on)
| MCR_CONTROL_LINE_RTS);
control = priv->line_control;
spin_unlock_irqrestore(&priv->lock, flags);
- spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
+ spcp8x5_set_ctrl_line(port, control);
}
static void spcp8x5_init_termios(struct tty_struct *tty)
{
- /* for the 1st time call this function */
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
- tty->termios->c_ispeed = 115200;
- tty->termios->c_ospeed = 115200;
+ tty->termios = tty_std_termios;
+ tty->termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios.c_ispeed = 115200;
+ tty->termios.c_ospeed = 115200;
}
-/* set the serial param for transfer. we should check if we really need to
- * transfer. if we set flow control we should do this too. */
static void spcp8x5_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- unsigned int cflag = tty->termios->c_cflag;
- unsigned int old_cflag = old_termios->c_cflag;
+ unsigned int cflag = tty->termios.c_cflag;
unsigned short uartdata;
unsigned char buf[2] = {0, 0};
int baud;
int i;
u8 control;
-
/* check that they really want us to change something */
- if (!tty_termios_hw_change(tty->termios, old_termios))
+ if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios))
return;
/* set DTR/RTS active */
spin_lock_irqsave(&priv->lock, flags);
control = priv->line_control;
- if ((old_cflag & CBAUD) == B0) {
+ if (old_termios && (old_termios->c_cflag & CBAUD) == B0) {
priv->line_control |= MCR_DTR;
- if (!(old_cflag & CRTSCTS))
+ if (!(old_termios->c_cflag & CRTSCTS))
priv->line_control |= MCR_RTS;
}
if (control != priv->line_control) {
control = priv->line_control;
spin_unlock_irqrestore(&priv->lock, flags);
- spcp8x5_set_ctrlLine(serial->dev, control , priv->type);
+ spcp8x5_set_ctrl_line(port, control);
} else {
spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -392,27 +342,24 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
case 1000000:
buf[0] = 0x0b; break;
default:
- dev_err(&port->dev, "spcp825 driver does not support the "
- "baudrate requested, using default of 9600.\n");
+ dev_err(&port->dev, "unsupported baudrate, using 9600\n");
}
/* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */
- if (cflag & CSIZE) {
- switch (cflag & CSIZE) {
- case CS5:
- buf[1] |= SET_UART_FORMAT_SIZE_5;
- break;
- case CS6:
- buf[1] |= SET_UART_FORMAT_SIZE_6;
- break;
- case CS7:
- buf[1] |= SET_UART_FORMAT_SIZE_7;
- break;
- default:
- case CS8:
- buf[1] |= SET_UART_FORMAT_SIZE_8;
- break;
- }
+ switch (cflag & CSIZE) {
+ case CS5:
+ buf[1] |= SET_UART_FORMAT_SIZE_5;
+ break;
+ case CS6:
+ buf[1] |= SET_UART_FORMAT_SIZE_6;
+ break;
+ case CS7:
+ buf[1] |= SET_UART_FORMAT_SIZE_7;
+ break;
+ default:
+ case CS8:
+ buf[1] |= SET_UART_FORMAT_SIZE_8;
+ break;
}
/* Set Stop bit2 : 0:1bit 1:2bit */
@@ -423,9 +370,9 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
if (cflag & PARENB) {
buf[1] |= (cflag & PARODD) ?
SET_UART_FORMAT_PAR_ODD : SET_UART_FORMAT_PAR_EVEN ;
- } else
+ } else {
buf[1] |= SET_UART_FORMAT_PAR_NONE;
-
+ }
uartdata = buf[0] | buf[1]<<8;
i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
@@ -434,28 +381,19 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
if (i < 0)
dev_err(&port->dev, "Set UART format %#x failed (error = %d)\n",
uartdata, i);
- dbg("0x21:0x40:0:0 %d", i);
+ dev_dbg(&port->dev, "0x21:0x40:0:0 %d\n", i);
if (cflag & CRTSCTS) {
/* enable hardware flow control */
- spcp8x5_set_workMode(serial->dev, 0x000a,
- SET_WORKING_MODE_U2C, priv->type);
+ spcp8x5_set_work_mode(port, 0x000a, SET_WORKING_MODE_U2C);
}
}
-/* open the serial port. do some usb system call. set termios and get the line
- * status of the device. */
static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)
{
- struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
int ret;
- unsigned long flags;
- u8 status = 0x30;
- /* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */
-
- dbg("%s - port %d", __func__, port->number);
usb_clear_halt(serial->dev, port->write_urb->pipe);
usb_clear_halt(serial->dev, port->read_urb->pipe);
@@ -466,132 +404,15 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)
if (ret)
return ret;
- spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
+ spcp8x5_set_ctrl_line(port, priv->line_control);
- /* Setup termios */
if (tty)
- spcp8x5_set_termios(tty, port, &tmp_termios);
-
- spcp8x5_get_msr(serial->dev, &status, priv->type);
-
- /* may be we should update uart status here but now we did not do */
- spin_lock_irqsave(&priv->lock, flags);
- priv->line_status = status & 0xf0 ;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- port->port.drain_delay = 256;
+ spcp8x5_set_termios(tty, port, NULL);
return usb_serial_generic_open(tty, port);
}
-static void spcp8x5_process_read_urb(struct urb *urb)
-{
- struct usb_serial_port *port = urb->context;
- struct spcp8x5_private *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty;
- unsigned char *data = urb->transfer_buffer;
- unsigned long flags;
- u8 status;
- char tty_flag;
-
- /* get tty_flag from status */
- tty_flag = TTY_NORMAL;
-
- spin_lock_irqsave(&priv->lock, flags);
- status = priv->line_status;
- priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
- spin_unlock_irqrestore(&priv->lock, flags);
- /* wake up the wait for termios */
- wake_up_interruptible(&priv->delta_msr_wait);
-
- if (!urb->actual_length)
- return;
-
- tty = tty_port_tty_get(&port->port);
- if (!tty)
- return;
-
- if (status & UART_STATE_TRANSIENT_MASK) {
- /* break takes precedence over parity, which takes precedence
- * over framing errors */
- if (status & UART_BREAK_ERROR)
- tty_flag = TTY_BREAK;
- else if (status & UART_PARITY_ERROR)
- tty_flag = TTY_PARITY;
- else if (status & UART_FRAME_ERROR)
- tty_flag = TTY_FRAME;
- dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
-
- /* overrun is special, not associated with a char */
- if (status & UART_OVERRUN_ERROR)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
-
- tty_insert_flip_string_fixed_flag(tty, data, tty_flag,
- urb->actual_length);
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
-}
-
-static int spcp8x5_wait_modem_info(struct usb_serial_port *port,
- unsigned int arg)
-{
- struct spcp8x5_private *priv = usb_get_serial_port_data(port);
- unsigned long flags;
- unsigned int prevstatus;
- unsigned int status;
- unsigned int changed;
-
- spin_lock_irqsave(&priv->lock, flags);
- prevstatus = priv->line_status;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- while (1) {
- /* wake up in bulk read */
- interruptible_sleep_on(&priv->delta_msr_wait);
-
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- spin_lock_irqsave(&priv->lock, flags);
- status = priv->line_status;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- changed = prevstatus^status;
-
- if (((arg & TIOCM_RNG) && (changed & MSR_STATUS_LINE_RI)) ||
- ((arg & TIOCM_DSR) && (changed & MSR_STATUS_LINE_DSR)) ||
- ((arg & TIOCM_CD) && (changed & MSR_STATUS_LINE_DCD)) ||
- ((arg & TIOCM_CTS) && (changed & MSR_STATUS_LINE_CTS)))
- return 0;
-
- prevstatus = status;
- }
- /* NOTREACHED */
- return 0;
-}
-
-static int spcp8x5_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct usb_serial_port *port = tty->driver_data;
- dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
-
- switch (cmd) {
- case TIOCMIWAIT:
- dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
- return spcp8x5_wait_modem_info(port, arg);
-
- default:
- dbg("%s not supported = 0x%04x", __func__, cmd);
- break;
- }
-
- return -ENOIOCTLCMD;
-}
-
-static int spcp8x5_tiocmset(struct tty_struct *tty, struct file *file,
+static int spcp8x5_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
@@ -611,21 +432,24 @@ static int spcp8x5_tiocmset(struct tty_struct *tty, struct file *file,
control = priv->line_control;
spin_unlock_irqrestore(&priv->lock, flags);
- return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
+ return spcp8x5_set_ctrl_line(port, control);
}
-static int spcp8x5_tiocmget(struct tty_struct *tty, struct file *file)
+static int spcp8x5_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int mcr;
- unsigned int status;
+ u8 status;
unsigned int result;
+ result = spcp8x5_get_msr(port, &status);
+ if (result)
+ return result;
+
spin_lock_irqsave(&priv->lock, flags);
mcr = priv->line_control;
- status = priv->line_status;
spin_unlock_irqrestore(&priv->lock, flags);
result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)
@@ -638,7 +462,6 @@ static int spcp8x5_tiocmget(struct tty_struct *tty, struct file *file)
return result;
}
-/* All of the device info needed for the spcp8x5 SIO serial converter */
static struct usb_serial_driver spcp8x5_device = {
.driver = {
.owner = THIS_MODULE,
@@ -646,49 +469,23 @@ static struct usb_serial_driver spcp8x5_device = {
},
.id_table = id_table,
.num_ports = 1,
- .open = spcp8x5_open,
+ .open = spcp8x5_open,
.dtr_rts = spcp8x5_dtr_rts,
.carrier_raised = spcp8x5_carrier_raised,
- .set_termios = spcp8x5_set_termios,
+ .set_termios = spcp8x5_set_termios,
.init_termios = spcp8x5_init_termios,
- .ioctl = spcp8x5_ioctl,
- .tiocmget = spcp8x5_tiocmget,
- .tiocmset = spcp8x5_tiocmset,
- .attach = spcp8x5_startup,
- .release = spcp8x5_release,
- .process_read_urb = spcp8x5_process_read_urb,
+ .tiocmget = spcp8x5_tiocmget,
+ .tiocmset = spcp8x5_tiocmset,
+ .probe = spcp8x5_probe,
+ .port_probe = spcp8x5_port_probe,
+ .port_remove = spcp8x5_port_remove,
};
-static int __init spcp8x5_init(void)
-{
- int retval;
- retval = usb_serial_register(&spcp8x5_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&spcp8x5_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&spcp8x5_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit spcp8x5_exit(void)
-{
- usb_deregister(&spcp8x5_driver);
- usb_serial_deregister(&spcp8x5_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &spcp8x5_device, NULL
+};
-module_init(spcp8x5_init);
-module_exit(spcp8x5_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index f5312dd3331..a7fe664b6b7 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -6,7 +6,6 @@
*/
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -46,10 +45,6 @@
#define FULLPWRBIT 0x00000080
#define NEXT_BOARD_POWER_BIT 0x00000004
-static int debug;
-
-/* Version Information */
-#define DRIVER_VERSION "v0.1"
#define DRIVER_DESC "Quatech SSU-100 USB to Serial Driver"
#define USB_VENDOR_ID_QUATECH 0x061d /* Quatech VID */
@@ -59,38 +54,14 @@ static const struct usb_device_id id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100)},
{} /* Terminating entry */
};
-
MODULE_DEVICE_TABLE(usb, id_table);
-
-static struct usb_driver ssu100_driver = {
- .name = "ssu100",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .no_dynamic_id = 1,
- .supports_autosuspend = 1,
-};
-
struct ssu100_port_private {
spinlock_t status_lock;
u8 shadowLSR;
u8 shadowMSR;
- wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
- unsigned short max_packet_size;
- struct async_icount icount;
};
-static void ssu100_release(struct usb_serial *serial)
-{
- struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port);
-
- dbg("%s", __func__);
- kfree(priv);
-}
-
static inline int ssu100_control_msg(struct usb_device *dev,
u8 request, u16 data, u16 index)
{
@@ -150,7 +121,7 @@ static inline int update_mctrl(struct usb_device *dev, unsigned int set,
int result;
if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
- dbg("%s - DTR|RTS not being set|cleared", __func__);
+ dev_dbg(&dev->dev, "%s - DTR|RTS not being set|cleared\n", __func__);
return 0; /* no change */
}
@@ -163,7 +134,7 @@ static inline int update_mctrl(struct usb_device *dev, unsigned int set,
result = ssu100_setregister(dev, 0, UART_MCR, urb_value);
if (result < 0)
- dbg("%s Error from MODEM_CTRL urb", __func__);
+ dev_dbg(&dev->dev, "%s Error from MODEM_CTRL urb\n", __func__);
return result;
}
@@ -173,15 +144,13 @@ static int ssu100_initdevice(struct usb_device *dev)
u8 *data;
int result = 0;
- dbg("%s", __func__);
-
data = kzalloc(3, GFP_KERNEL);
if (!data)
return -ENOMEM;
result = ssu100_getdevice(dev, data);
if (result < 0) {
- dbg("%s - get_device failed %i", __func__, result);
+ dev_dbg(&dev->dev, "%s - get_device failed %i\n", __func__, result);
goto out;
}
@@ -189,25 +158,25 @@ static int ssu100_initdevice(struct usb_device *dev)
result = ssu100_setdevice(dev, data);
if (result < 0) {
- dbg("%s - setdevice failed %i", __func__, result);
+ dev_dbg(&dev->dev, "%s - setdevice failed %i\n", __func__, result);
goto out;
}
result = ssu100_control_msg(dev, QT_GET_SET_PREBUF_TRIG_LVL, 128, 0);
if (result < 0) {
- dbg("%s - set prebuffer level failed %i", __func__, result);
+ dev_dbg(&dev->dev, "%s - set prebuffer level failed %i\n", __func__, result);
goto out;
}
result = ssu100_control_msg(dev, QT_SET_ATF, ATC_DISABLED, 0);
if (result < 0) {
- dbg("%s - set ATFprebuffer level failed %i", __func__, result);
+ dev_dbg(&dev->dev, "%s - set ATFprebuffer level failed %i\n", __func__, result);
goto out;
}
result = ssu100_getdevice(dev, data);
if (result < 0) {
- dbg("%s - get_device failed %i", __func__, result);
+ dev_dbg(&dev->dev, "%s - get_device failed %i\n", __func__, result);
goto out;
}
@@ -218,7 +187,7 @@ static int ssu100_initdevice(struct usb_device *dev)
result = ssu100_setdevice(dev, data);
if (result < 0) {
- dbg("%s - setdevice failed %i", __func__, result);
+ dev_dbg(&dev->dev, "%s - setdevice failed %i\n", __func__, result);
goto out;
}
@@ -233,14 +202,12 @@ static void ssu100_set_termios(struct tty_struct *tty,
struct ktermios *old_termios)
{
struct usb_device *dev = port->serial->dev;
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
u16 baud, divisor, remainder;
unsigned int cflag = termios->c_cflag;
u16 urb_value = 0; /* will hold the new flags */
int result;
- dbg("%s", __func__);
-
if (cflag & PARENB) {
if (cflag & PARODD)
urb_value |= UART_LCR_PARITY;
@@ -268,7 +235,7 @@ static void ssu100_set_termios(struct tty_struct *tty,
if (!baud)
baud = 9600;
- dbg("%s - got baud = %d\n", __func__, baud);
+ dev_dbg(&port->dev, "%s - got baud = %d\n", __func__, baud);
divisor = MAX_BAUD_RATE / baud;
@@ -280,7 +247,7 @@ static void ssu100_set_termios(struct tty_struct *tty,
result = ssu100_control_msg(dev, QT_GET_SET_UART, divisor, urb_value);
if (result < 0)
- dbg("%s - set uart failed", __func__);
+ dev_dbg(&port->dev, "%s - set uart failed\n", __func__);
if (cflag & CRTSCTS)
result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
@@ -289,7 +256,7 @@ static void ssu100_set_termios(struct tty_struct *tty,
result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
0, 0);
if (result < 0)
- dbg("%s - set HW flow control failed", __func__);
+ dev_dbg(&port->dev, "%s - set HW flow control failed\n", __func__);
if (I_IXOFF(tty) || I_IXON(tty)) {
u16 x = ((u16)(START_CHAR(tty) << 8) | (u16)(STOP_CHAR(tty)));
@@ -301,7 +268,7 @@ static void ssu100_set_termios(struct tty_struct *tty,
0, 0);
if (result < 0)
- dbg("%s - set SW flow control failed", __func__);
+ dev_dbg(&port->dev, "%s - set SW flow control failed\n", __func__);
}
@@ -314,8 +281,6 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
int result;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
data = kzalloc(2, GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -325,7 +290,7 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
QT_TRANSFER_IN, 0x01,
0, data, 2, 300);
if (result < 0) {
- dbg("%s - open failed %i", __func__, result);
+ dev_dbg(&port->dev, "%s - open failed %i\n", __func__, result);
kfree(data);
return result;
}
@@ -340,20 +305,14 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
/* set to 9600 */
result = ssu100_control_msg(dev, QT_GET_SET_UART, 0x30, 0x0300);
if (result < 0)
- dbg("%s - set uart failed", __func__);
+ dev_dbg(&port->dev, "%s - set uart failed\n", __func__);
if (tty)
- ssu100_set_termios(tty, port, tty->termios);
+ ssu100_set_termios(tty, port, &tty->termios);
return usb_serial_generic_open(tty, port);
}
-static void ssu100_close(struct usb_serial_port *port)
-{
- dbg("%s", __func__);
- usb_serial_generic_close(port);
-}
-
static int get_serial_info(struct usb_serial_port *port,
struct serial_struct __user *retinfo)
{
@@ -363,7 +322,7 @@ static int get_serial_info(struct usb_serial_port *port,
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
- tmp.line = port->serial->minor;
+ tmp.line = port->minor;
tmp.port = 0;
tmp.irq = 0;
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
@@ -377,154 +336,59 @@ static int get_serial_info(struct usb_serial_port *port,
return 0;
}
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
-{
- struct ssu100_port_private *priv = usb_get_serial_port_data(port);
- struct async_icount prev, cur;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->status_lock, flags);
- prev = priv->icount;
- spin_unlock_irqrestore(&priv->status_lock, flags);
-
- while (1) {
- wait_event_interruptible(priv->delta_msr_wait,
- ((priv->icount.rng != prev.rng) ||
- (priv->icount.dsr != prev.dsr) ||
- (priv->icount.dcd != prev.dcd) ||
- (priv->icount.cts != prev.cts)));
-
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- spin_lock_irqsave(&priv->status_lock, flags);
- cur = priv->icount;
- spin_unlock_irqrestore(&priv->status_lock, flags);
-
- if ((prev.rng == cur.rng) &&
- (prev.dsr == cur.dsr) &&
- (prev.dcd == cur.dcd) &&
- (prev.cts == cur.cts))
- return -EIO;
-
- if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) ||
- (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) ||
- (arg & TIOCM_CD && (prev.dcd != cur.dcd)) ||
- (arg & TIOCM_CTS && (prev.cts != cur.cts)))
- return 0;
- }
- return 0;
-}
-
-static int ssu100_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct ssu100_port_private *priv = usb_get_serial_port_data(port);
- struct async_icount cnow = priv->icount;
-
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
-
- return 0;
-}
-
-
-
-static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
+static int ssu100_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s cmd 0x%04x", __func__, cmd);
-
switch (cmd) {
case TIOCGSERIAL:
return get_serial_info(port,
(struct serial_struct __user *) arg);
-
- case TIOCMIWAIT:
- return wait_modem_info(port, arg);
-
default:
break;
}
- dbg("%s arg not supported", __func__);
-
return -ENOIOCTLCMD;
}
-static void ssu100_set_max_packet_size(struct usb_serial_port *port)
+static int ssu100_attach(struct usb_serial *serial)
{
- struct ssu100_port_private *priv = usb_get_serial_port_data(port);
- struct usb_serial *serial = port->serial;
- struct usb_device *udev = serial->dev;
-
- struct usb_interface *interface = serial->interface;
- struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc;
-
- unsigned num_endpoints;
- int i;
- unsigned long flags;
-
- num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
- dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
-
- for (i = 0; i < num_endpoints; i++) {
- dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1,
- interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
- ep_desc = &interface->cur_altsetting->endpoint[i].desc;
- }
-
- /* set max packet size based on descriptor */
- spin_lock_irqsave(&priv->status_lock, flags);
- priv->max_packet_size = ep_desc->wMaxPacketSize;
- spin_unlock_irqrestore(&priv->status_lock, flags);
-
- dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
+ return ssu100_initdevice(serial->dev);
}
-static int ssu100_attach(struct usb_serial *serial)
+static int ssu100_port_probe(struct usb_serial_port *port)
{
struct ssu100_port_private *priv;
- struct usb_serial_port *port = *serial->port;
-
- dbg("%s", __func__);
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__,
- sizeof(*priv));
+ if (!priv)
return -ENOMEM;
- }
spin_lock_init(&priv->status_lock);
- init_waitqueue_head(&priv->delta_msr_wait);
+
usb_set_serial_port_data(port, priv);
- ssu100_set_max_packet_size(port);
- return ssu100_initdevice(serial->dev);
+ return 0;
+}
+
+static int ssu100_port_remove(struct usb_serial_port *port)
+{
+ struct ssu100_port_private *priv;
+
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
}
-static int ssu100_tiocmget(struct tty_struct *tty, struct file *file)
+static int ssu100_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct usb_device *dev = port->serial->dev;
u8 *d;
int r;
- dbg("%s\n", __func__);
-
d = kzalloc(2, GFP_KERNEL);
if (!d)
return -ENOMEM;
@@ -549,13 +413,12 @@ mget_out:
return r;
}
-static int ssu100_tiocmset(struct tty_struct *tty, struct file *file,
+static int ssu100_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
struct usb_device *dev = port->serial->dev;
- dbg("%s\n", __func__);
return update_mctrl(dev, set, clear);
}
@@ -563,21 +426,16 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on)
{
struct usb_device *dev = port->serial->dev;
- dbg("%s\n", __func__);
-
- mutex_lock(&port->serial->disc_mutex);
- if (!port->serial->disconnected) {
- /* Disable flow control */
- if (!on &&
- ssu100_setregister(dev, 0, UART_MCR, 0) < 0)
+ /* Disable flow control */
+ if (!on) {
+ if (ssu100_setregister(dev, 0, UART_MCR, 0) < 0)
dev_err(&port->dev, "error from flowcontrol urb\n");
- /* drop RTS and DTR */
- if (on)
- set_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
- else
- clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
}
- mutex_unlock(&port->serial->disc_mutex);
+ /* drop RTS and DTR */
+ if (on)
+ set_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
+ else
+ clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
}
static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
@@ -592,14 +450,14 @@ static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
if (msr & UART_MSR_ANY_DELTA) {
/* update input line counters */
if (msr & UART_MSR_DCTS)
- priv->icount.cts++;
+ port->icount.cts++;
if (msr & UART_MSR_DDSR)
- priv->icount.dsr++;
+ port->icount.dsr++;
if (msr & UART_MSR_DDCD)
- priv->icount.dcd++;
+ port->icount.dcd++;
if (msr & UART_MSR_TERI)
- priv->icount.rng++;
- wake_up_interruptible(&priv->delta_msr_wait);
+ port->icount.rng++;
+ wake_up_interruptible(&port->port.delta_msr_wait);
}
}
@@ -618,22 +476,22 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
/* we always want to update icount, but we only want to
* update tty_flag for one case */
if (lsr & UART_LSR_BI) {
- priv->icount.brk++;
+ port->icount.brk++;
*tty_flag = TTY_BREAK;
usb_serial_handle_break(port);
}
if (lsr & UART_LSR_PE) {
- priv->icount.parity++;
+ port->icount.parity++;
if (*tty_flag == TTY_NORMAL)
*tty_flag = TTY_PARITY;
}
if (lsr & UART_LSR_FE) {
- priv->icount.frame++;
+ port->icount.frame++;
if (*tty_flag == TTY_NORMAL)
*tty_flag = TTY_FRAME;
}
if (lsr & UART_LSR_OE){
- priv->icount.overrun++;
+ port->icount.overrun++;
if (*tty_flag == TTY_NORMAL)
*tty_flag = TTY_OVERRUN;
}
@@ -641,24 +499,23 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
}
-static int ssu100_process_packet(struct tty_struct *tty,
- struct usb_serial_port *port,
- struct ssu100_port_private *priv,
- char *packet, int len)
+static void ssu100_process_read_urb(struct urb *urb)
{
- int i;
+ struct usb_serial_port *port = urb->context;
+ char *packet = (char *)urb->transfer_buffer;
char flag = TTY_NORMAL;
+ u32 len = urb->actual_length;
+ int i;
char *ch;
- dbg("%s - port %d", __func__, port->number);
-
if ((len >= 4) &&
(packet[0] == 0x1b) && (packet[1] == 0x1b) &&
((packet[2] == 0x00) || (packet[2] == 0x01))) {
if (packet[2] == 0x00) {
ssu100_update_lsr(port, packet[3], &flag);
if (flag == TTY_OVERRUN)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ tty_insert_flip_char(&port->port, 0,
+ TTY_OVERRUN);
}
if (packet[2] == 0x01)
ssu100_update_msr(port, packet[3]);
@@ -669,43 +526,17 @@ static int ssu100_process_packet(struct tty_struct *tty,
ch = packet;
if (!len)
- return 0; /* status only */
+ return; /* status only */
if (port->port.console && port->sysrq) {
for (i = 0; i < len; i++, ch++) {
if (!usb_serial_handle_sysrq_char(port, *ch))
- tty_insert_flip_char(tty, *ch, flag);
+ tty_insert_flip_char(&port->port, *ch, flag);
}
} else
- tty_insert_flip_string_fixed_flag(tty, ch, flag, len);
-
- return len;
-}
-
-static void ssu100_process_read_urb(struct urb *urb)
-{
- struct usb_serial_port *port = urb->context;
- struct ssu100_port_private *priv = usb_get_serial_port_data(port);
- char *data = (char *)urb->transfer_buffer;
- struct tty_struct *tty;
- int count = 0;
- int i;
- int len;
+ tty_insert_flip_string_fixed_flag(&port->port, ch, flag, len);
- dbg("%s", __func__);
-
- tty = tty_port_tty_get(&port->port);
- if (!tty)
- return;
-
- for (i = 0; i < urb->actual_length; i += priv->max_packet_size) {
- len = min_t(int, urb->actual_length - i, priv->max_packet_size);
- count += ssu100_process_packet(tty, port, priv, &data[i], len);
- }
-
- if (count)
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
+ tty_flip_buffer_push(&port->port);
}
static struct usb_serial_driver ssu100_device = {
@@ -715,62 +546,26 @@ static struct usb_serial_driver ssu100_device = {
},
.description = DRIVER_DESC,
.id_table = id_table,
- .usb_driver = &ssu100_driver,
.num_ports = 1,
- .bulk_in_size = 256,
- .bulk_out_size = 256,
.open = ssu100_open,
- .close = ssu100_close,
.attach = ssu100_attach,
- .release = ssu100_release,
+ .port_probe = ssu100_port_probe,
+ .port_remove = ssu100_port_remove,
.dtr_rts = ssu100_dtr_rts,
.process_read_urb = ssu100_process_read_urb,
.tiocmget = ssu100_tiocmget,
.tiocmset = ssu100_tiocmset,
- .get_icount = ssu100_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.ioctl = ssu100_ioctl,
.set_termios = ssu100_set_termios,
- .disconnect = usb_serial_generic_disconnect,
};
-static int __init ssu100_init(void)
-{
- int retval;
-
- dbg("%s", __func__);
-
- /* register with usb-serial */
- retval = usb_serial_register(&ssu100_device);
-
- if (retval)
- goto failed_usb_sio_register;
-
- retval = usb_register(&ssu100_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-
-failed_usb_register:
- usb_serial_deregister(&ssu100_device);
-failed_usb_sio_register:
- return retval;
-}
-
-static void __exit ssu100_exit(void)
-{
- usb_deregister(&ssu100_driver);
- usb_serial_deregister(&ssu100_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ssu100_device, NULL
+};
-module_init(ssu100_init);
-module_exit(ssu100_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c
index d9457bd4fe1..8fceec7298e 100644
--- a/drivers/usb/serial/symbolserial.c
+++ b/drivers/usb/serial/symbolserial.c
@@ -1,6 +1,7 @@
/*
* Symbol USB barcode to serial driver
*
+ * Copyright (C) 2013 Johan Hovold <jhovold@gmail.com>
* Copyright (C) 2009 Greg Kroah-Hartman <gregkh@suse.de>
* Copyright (C) 2009 Novell Inc.
*
@@ -10,7 +11,6 @@
*/
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/tty_driver.h>
@@ -20,42 +20,27 @@
#include <linux/usb/serial.h>
#include <linux/uaccess.h>
-static int debug;
-
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x05e0, 0x0600) },
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
-/* This structure holds all of the individual device information */
struct symbol_private {
- struct usb_device *udev;
- struct usb_serial *serial;
- struct usb_serial_port *port;
- unsigned char *int_buffer;
- struct urb *int_urb;
- int buffer_size;
- u8 bInterval;
- u8 int_address;
spinlock_t lock; /* protects the following flags */
bool throttled;
bool actually_throttled;
- bool rts;
};
static void symbol_int_callback(struct urb *urb)
{
- struct symbol_private *priv = urb->context;
+ struct usb_serial_port *port = urb->context;
+ struct symbol_private *priv = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
- struct usb_serial_port *port = priv->port;
int status = urb->status;
- struct tty_struct *tty;
int result;
int data_length;
- dbg("%s - port %d", __func__, port->number);
-
switch (status) {
case 0:
/* success */
@@ -64,17 +49,16 @@ static void symbol_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
goto exit;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length,
- data);
+ usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
if (urb->actual_length > 1) {
data_length = urb->actual_length - 1;
@@ -87,16 +71,10 @@ static void symbol_int_callback(struct urb *urb)
* we pretty much just ignore the size and send everything
* else to the tty layer.
*/
- tty = tty_port_tty_get(&port->port);
- if (tty) {
- tty_insert_flip_string(tty, &data[1], data_length);
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
- }
+ tty_insert_flip_string(&port->port, &data[1], data_length);
+ tty_flip_buffer_push(&port->port);
} else {
- dev_dbg(&priv->udev->dev,
- "Improper amount of data received from the device, "
- "%d bytes", urb->actual_length);
+ dev_dbg(&port->dev, "%s - short packet\n", __func__);
}
exit:
@@ -104,12 +82,7 @@ exit:
/* Continue trying to always read if we should */
if (!priv->throttled) {
- usb_fill_int_urb(priv->int_urb, priv->udev,
- usb_rcvintpipe(priv->udev,
- priv->int_address),
- priv->int_buffer, priv->buffer_size,
- symbol_int_callback, priv, priv->bInterval);
- result = usb_submit_urb(priv->int_urb, GFP_ATOMIC);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result)
dev_err(&port->dev,
"%s - failed resubmitting read urb, error %d\n",
@@ -125,20 +98,13 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)
unsigned long flags;
int result = 0;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
priv->throttled = false;
priv->actually_throttled = false;
- priv->port = port;
spin_unlock_irqrestore(&priv->lock, flags);
/* Start reading from the device */
- usb_fill_int_urb(priv->int_urb, priv->udev,
- usb_rcvintpipe(priv->udev, priv->int_address),
- priv->int_buffer, priv->buffer_size,
- symbol_int_callback, priv, priv->bInterval);
- result = usb_submit_urb(priv->int_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result)
dev_err(&port->dev,
"%s - failed resubmitting read urb, error %d\n",
@@ -148,12 +114,7 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)
static void symbol_close(struct usb_serial_port *port)
{
- struct symbol_private *priv = usb_get_serial_data(port->serial);
-
- dbg("%s - port %d", __func__, port->number);
-
- /* shutdown our urbs */
- usb_kill_urb(priv->int_urb);
+ usb_kill_urb(port->interrupt_in_urb);
}
static void symbol_throttle(struct tty_struct *tty)
@@ -161,7 +122,6 @@ static void symbol_throttle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct symbol_private *priv = usb_get_serial_data(port->serial);
- dbg("%s - port %d", __func__, port->number);
spin_lock_irq(&priv->lock);
priv->throttled = true;
spin_unlock_irq(&priv->lock);
@@ -174,17 +134,14 @@ static void symbol_unthrottle(struct tty_struct *tty)
int result;
bool was_throttled;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irq(&priv->lock);
priv->throttled = false;
was_throttled = priv->actually_throttled;
priv->actually_throttled = false;
spin_unlock_irq(&priv->lock);
- priv->int_urb->dev = port->serial->dev;
if (was_throttled) {
- result = usb_submit_urb(priv->int_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result)
dev_err(&port->dev,
"%s - failed submitting read urb, error %d\n",
@@ -194,102 +151,37 @@ static void symbol_unthrottle(struct tty_struct *tty)
static int symbol_startup(struct usb_serial *serial)
{
- struct symbol_private *priv;
- struct usb_host_interface *intf;
- int i;
- int retval = -ENOMEM;
- bool int_in_found = false;
-
- /* create our private serial structure */
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (priv == NULL) {
- dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
- return -ENOMEM;
+ if (!serial->num_interrupt_in) {
+ dev_err(&serial->dev->dev, "no interrupt-in endpoint\n");
+ return -ENODEV;
}
- spin_lock_init(&priv->lock);
- priv->serial = serial;
- priv->port = serial->port[0];
- priv->udev = serial->dev;
-
- /* find our interrupt endpoint */
- intf = serial->interface->altsetting;
- for (i = 0; i < intf->desc.bNumEndpoints; ++i) {
- struct usb_endpoint_descriptor *endpoint;
-
- endpoint = &intf->endpoint[i].desc;
- if (!usb_endpoint_is_int_in(endpoint))
- continue;
-
- priv->int_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!priv->int_urb) {
- dev_err(&priv->udev->dev, "out of memory\n");
- goto error;
- }
-
- priv->buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2;
- priv->int_buffer = kmalloc(priv->buffer_size, GFP_KERNEL);
- if (!priv->int_buffer) {
- dev_err(&priv->udev->dev, "out of memory\n");
- goto error;
- }
-
- priv->int_address = endpoint->bEndpointAddress;
- priv->bInterval = endpoint->bInterval;
-
- /* set up our int urb */
- usb_fill_int_urb(priv->int_urb, priv->udev,
- usb_rcvintpipe(priv->udev,
- endpoint->bEndpointAddress),
- priv->int_buffer, priv->buffer_size,
- symbol_int_callback, priv, priv->bInterval);
-
- int_in_found = true;
- break;
- }
- if (!int_in_found) {
- dev_err(&priv->udev->dev,
- "Error - the proper endpoints were not found!\n");
- goto error;
- }
-
- usb_set_serial_data(serial, priv);
return 0;
-
-error:
- usb_free_urb(priv->int_urb);
- kfree(priv->int_buffer);
- kfree(priv);
- return retval;
}
-static void symbol_disconnect(struct usb_serial *serial)
+static int symbol_port_probe(struct usb_serial_port *port)
{
- struct symbol_private *priv = usb_get_serial_data(serial);
+ struct symbol_private *priv;
- dbg("%s", __func__);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ spin_lock_init(&priv->lock);
+
+ usb_set_serial_port_data(port, priv);
- usb_kill_urb(priv->int_urb);
- usb_free_urb(priv->int_urb);
+ return 0;
}
-static void symbol_release(struct usb_serial *serial)
+static int symbol_port_remove(struct usb_serial_port *port)
{
- struct symbol_private *priv = usb_get_serial_data(serial);
-
- dbg("%s", __func__);
+ struct symbol_private *priv = usb_get_serial_port_data(port);
- kfree(priv->int_buffer);
kfree(priv);
-}
-static struct usb_driver symbol_driver = {
- .name = "symbol",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
+ return 0;
+}
static struct usb_serial_driver symbol_device = {
.driver = {
@@ -297,39 +189,21 @@ static struct usb_serial_driver symbol_device = {
.name = "symbol",
},
.id_table = id_table,
- .usb_driver = &symbol_driver,
.num_ports = 1,
.attach = symbol_startup,
+ .port_probe = symbol_port_probe,
+ .port_remove = symbol_port_remove,
.open = symbol_open,
.close = symbol_close,
- .disconnect = symbol_disconnect,
- .release = symbol_release,
.throttle = symbol_throttle,
.unthrottle = symbol_unthrottle,
+ .read_int_callback = symbol_int_callback,
};
-static int __init symbol_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&symbol_device);
- if (retval)
- return retval;
- retval = usb_register(&symbol_driver);
- if (retval)
- usb_serial_deregister(&symbol_device);
- return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &symbol_device, NULL
+};
-static void __exit symbol_exit(void)
-{
- usb_deregister(&symbol_driver);
- usb_serial_deregister(&symbol_device);
-}
+module_usb_serial_driver(serial_drivers, id_table);
-module_init(symbol_init);
-module_exit(symbol_exit);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index b2902f307b4..3dd3ff8c50d 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -21,7 +21,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/firmware.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -40,14 +39,11 @@
/* Defines */
-#define TI_DRIVER_VERSION "v0.10"
#define TI_DRIVER_AUTHOR "Al Borchers <alborchers@steinerpoint.com>"
#define TI_DRIVER_DESC "TI USB 3410/5052 Serial Driver"
#define TI_FIRMWARE_BUF_SIZE 16284
-#define TI_WRITE_BUF_SIZE 1024
-
#define TI_TRANSFER_TIMEOUT 2
#define TI_DEFAULT_CLOSING_WAIT 4000 /* in .01 secs */
@@ -68,21 +64,15 @@
struct ti_port {
int tp_is_open;
__u8 tp_msr;
- __u8 tp_lsr;
__u8 tp_shadow_mcr;
__u8 tp_uart_mode; /* 232 or 485 modes */
unsigned int tp_uart_base_addr;
int tp_flags;
- int tp_closing_wait;/* in .01 secs */
- struct async_icount tp_icount;
- wait_queue_head_t tp_msr_wait; /* wait for msr change */
- wait_queue_head_t tp_write_wait;
struct ti_device *tp_tdev;
struct usb_serial_port *tp_port;
spinlock_t tp_lock;
int tp_read_urb_state;
int tp_write_urb_in_use;
- struct kfifo write_fifo;
};
struct ti_device {
@@ -98,41 +88,40 @@ struct ti_device {
static int ti_startup(struct usb_serial *serial);
static void ti_release(struct usb_serial *serial);
+static int ti_port_probe(struct usb_serial_port *port);
+static int ti_port_remove(struct usb_serial_port *port);
static int ti_open(struct tty_struct *tty, struct usb_serial_port *port);
static void ti_close(struct usb_serial_port *port);
static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *data, int count);
static int ti_write_room(struct tty_struct *tty);
static int ti_chars_in_buffer(struct tty_struct *tty);
+static bool ti_tx_empty(struct usb_serial_port *port);
static void ti_throttle(struct tty_struct *tty);
static void ti_unthrottle(struct tty_struct *tty);
-static int ti_ioctl(struct tty_struct *tty, struct file *file,
+static int ti_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
-static int ti_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount);
static void ti_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios);
-static int ti_tiocmget(struct tty_struct *tty, struct file *file);
-static int ti_tiocmset(struct tty_struct *tty, struct file *file,
+static int ti_tiocmget(struct tty_struct *tty);
+static int ti_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
static void ti_break(struct tty_struct *tty, int break_state);
static void ti_interrupt_callback(struct urb *urb);
static void ti_bulk_in_callback(struct urb *urb);
static void ti_bulk_out_callback(struct urb *urb);
-static void ti_recv(struct device *dev, struct tty_struct *tty,
- unsigned char *data, int length);
+static void ti_recv(struct usb_serial_port *port, unsigned char *data,
+ int length);
static void ti_send(struct ti_port *tport);
static int ti_set_mcr(struct ti_port *tport, unsigned int mcr);
-static int ti_get_lsr(struct ti_port *tport);
+static int ti_get_lsr(struct ti_port *tport, u8 *lsr);
static int ti_get_serial_info(struct ti_port *tport,
struct serial_struct __user *ret_arg);
static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,
struct serial_struct __user *new_arg);
static void ti_handle_new_msr(struct ti_port *tport, __u8 msr);
-static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush);
-
static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty);
static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty);
@@ -141,8 +130,8 @@ static int ti_command_out_sync(struct ti_device *tdev, __u8 command,
static int ti_command_in_sync(struct ti_device *tdev, __u8 command,
__u16 moduleid, __u16 value, __u8 *data, int size);
-static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
- __u8 mask, __u8 byte);
+static int ti_write_byte(struct usb_serial_port *port, struct ti_device *tdev,
+ unsigned long addr, __u8 mask, __u8 byte);
static int ti_download_firmware(struct ti_device *tdev);
@@ -150,22 +139,10 @@ static int ti_download_firmware(struct ti_device *tdev);
/* Data */
/* module parameters */
-static int debug;
static int closing_wait = TI_DEFAULT_CLOSING_WAIT;
-static ushort vendor_3410[TI_EXTRA_VID_PID_COUNT];
-static unsigned int vendor_3410_count;
-static ushort product_3410[TI_EXTRA_VID_PID_COUNT];
-static unsigned int product_3410_count;
-static ushort vendor_5052[TI_EXTRA_VID_PID_COUNT];
-static unsigned int vendor_5052_count;
-static ushort product_5052[TI_EXTRA_VID_PID_COUNT];
-static unsigned int product_5052_count;
/* supported devices */
-/* the array dimension is the number of default entries plus */
-/* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */
-/* null entry */
-static struct usb_device_id ti_id_table_3410[13+TI_EXTRA_VID_PID_COUNT+1] = {
+static const struct usb_device_id ti_id_table_3410[] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -179,16 +156,21 @@ static struct usb_device_id ti_id_table_3410[13+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
+ { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STEREO_PLUG_ID) },
+ { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
+ { } /* terminator */
};
-static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
+static const struct usb_device_id ti_id_table_5052[] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
+ { } /* terminator */
};
-static struct usb_device_id ti_id_table_combined[17+2*TI_EXTRA_VID_PID_COUNT+1] = {
+static const struct usb_device_id ti_id_table_combined[] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -206,15 +188,10 @@ static struct usb_device_id ti_id_table_combined[17+2*TI_EXTRA_VID_PID_COUNT+1]
{ USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
- { }
-};
-
-static struct usb_driver ti_usb_driver = {
- .name = "ti_usb_3410_5052",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = ti_id_table_combined,
- .no_dynamic_id = 1,
+ { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
+ { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
+ { } /* terminator */
};
static struct usb_serial_driver ti_1port_device = {
@@ -223,23 +200,26 @@ static struct usb_serial_driver ti_1port_device = {
.name = "ti_usb_3410_5052_1",
},
.description = "TI USB 3410 1 port adapter",
- .usb_driver = &ti_usb_driver,
.id_table = ti_id_table_3410,
.num_ports = 1,
.attach = ti_startup,
.release = ti_release,
+ .port_probe = ti_port_probe,
+ .port_remove = ti_port_remove,
.open = ti_open,
.close = ti_close,
.write = ti_write,
.write_room = ti_write_room,
.chars_in_buffer = ti_chars_in_buffer,
+ .tx_empty = ti_tx_empty,
.throttle = ti_throttle,
.unthrottle = ti_unthrottle,
.ioctl = ti_ioctl,
.set_termios = ti_set_termios,
.tiocmget = ti_tiocmget,
.tiocmset = ti_tiocmset,
- .get_icount = ti_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.break_ctl = ti_break,
.read_int_callback = ti_interrupt_callback,
.read_bulk_callback = ti_bulk_in_callback,
@@ -252,35 +232,40 @@ static struct usb_serial_driver ti_2port_device = {
.name = "ti_usb_3410_5052_2",
},
.description = "TI USB 5052 2 port adapter",
- .usb_driver = &ti_usb_driver,
.id_table = ti_id_table_5052,
.num_ports = 2,
.attach = ti_startup,
.release = ti_release,
+ .port_probe = ti_port_probe,
+ .port_remove = ti_port_remove,
.open = ti_open,
.close = ti_close,
.write = ti_write,
.write_room = ti_write_room,
.chars_in_buffer = ti_chars_in_buffer,
+ .tx_empty = ti_tx_empty,
.throttle = ti_throttle,
.unthrottle = ti_unthrottle,
.ioctl = ti_ioctl,
.set_termios = ti_set_termios,
.tiocmget = ti_tiocmget,
.tiocmset = ti_tiocmset,
- .get_icount = ti_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.break_ctl = ti_break,
.read_int_callback = ti_interrupt_callback,
.read_bulk_callback = ti_bulk_in_callback,
.write_bulk_callback = ti_bulk_out_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ti_1port_device, &ti_2port_device, NULL
+};
/* Module */
MODULE_AUTHOR(TI_DRIVER_AUTHOR);
MODULE_DESCRIPTION(TI_DRIVER_DESC);
-MODULE_VERSION(TI_DRIVER_VERSION);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("ti_3410.fw");
@@ -291,127 +276,48 @@ MODULE_FIRMWARE("mts_edge.fw");
MODULE_FIRMWARE("mts_mt9234mu.fw");
MODULE_FIRMWARE("mts_mt9234zba.fw");
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging, 0=no, 1=yes");
-
module_param(closing_wait, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(closing_wait,
"Maximum wait for data to drain in close, in .01 secs, default is 4000");
-module_param_array(vendor_3410, ushort, &vendor_3410_count, S_IRUGO);
-MODULE_PARM_DESC(vendor_3410,
- "Vendor ids for 3410 based devices, 1-5 short integers");
-module_param_array(product_3410, ushort, &product_3410_count, S_IRUGO);
-MODULE_PARM_DESC(product_3410,
- "Product ids for 3410 based devices, 1-5 short integers");
-module_param_array(vendor_5052, ushort, &vendor_5052_count, S_IRUGO);
-MODULE_PARM_DESC(vendor_5052,
- "Vendor ids for 5052 based devices, 1-5 short integers");
-module_param_array(product_5052, ushort, &product_5052_count, S_IRUGO);
-MODULE_PARM_DESC(product_5052,
- "Product ids for 5052 based devices, 1-5 short integers");
-
MODULE_DEVICE_TABLE(usb, ti_id_table_combined);
+module_usb_serial_driver(serial_drivers, ti_id_table_combined);
/* Functions */
-static int __init ti_init(void)
-{
- int i, j, c;
- int ret;
-
- /* insert extra vendor and product ids */
- c = ARRAY_SIZE(ti_id_table_combined) - 2 * TI_EXTRA_VID_PID_COUNT - 1;
- j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1;
- for (i = 0; i < min(vendor_3410_count, product_3410_count); i++, j++, c++) {
- ti_id_table_3410[j].idVendor = vendor_3410[i];
- ti_id_table_3410[j].idProduct = product_3410[i];
- ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
- ti_id_table_combined[c].idVendor = vendor_3410[i];
- ti_id_table_combined[c].idProduct = product_3410[i];
- ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
- }
- j = ARRAY_SIZE(ti_id_table_5052) - TI_EXTRA_VID_PID_COUNT - 1;
- for (i = 0; i < min(vendor_5052_count, product_5052_count); i++, j++, c++) {
- ti_id_table_5052[j].idVendor = vendor_5052[i];
- ti_id_table_5052[j].idProduct = product_5052[i];
- ti_id_table_5052[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
- ti_id_table_combined[c].idVendor = vendor_5052[i];
- ti_id_table_combined[c].idProduct = product_5052[i];
- ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
- }
-
- ret = usb_serial_register(&ti_1port_device);
- if (ret)
- goto failed_1port;
- ret = usb_serial_register(&ti_2port_device);
- if (ret)
- goto failed_2port;
-
- ret = usb_register(&ti_usb_driver);
- if (ret)
- goto failed_usb;
-
- printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":"
- TI_DRIVER_DESC "\n");
-
- return 0;
-
-failed_usb:
- usb_serial_deregister(&ti_2port_device);
-failed_2port:
- usb_serial_deregister(&ti_1port_device);
-failed_1port:
- return ret;
-}
-
-
-static void __exit ti_exit(void)
-{
- usb_serial_deregister(&ti_1port_device);
- usb_serial_deregister(&ti_2port_device);
- usb_deregister(&ti_usb_driver);
-}
-
-
-module_init(ti_init);
-module_exit(ti_exit);
-
-
static int ti_startup(struct usb_serial *serial)
{
struct ti_device *tdev;
- struct ti_port *tport;
struct usb_device *dev = serial->dev;
int status;
- int i;
-
- dbg("%s - product 0x%4X, num configurations %d, configuration value %d",
- __func__, le16_to_cpu(dev->descriptor.idProduct),
- dev->descriptor.bNumConfigurations,
- dev->actconfig->desc.bConfigurationValue);
+ dev_dbg(&dev->dev,
+ "%s - product 0x%4X, num configurations %d, configuration value %d\n",
+ __func__, le16_to_cpu(dev->descriptor.idProduct),
+ dev->descriptor.bNumConfigurations,
+ dev->actconfig->desc.bConfigurationValue);
/* create device structure */
tdev = kzalloc(sizeof(struct ti_device), GFP_KERNEL);
- if (tdev == NULL) {
- dev_err(&dev->dev, "%s - out of memory\n", __func__);
+ if (!tdev)
return -ENOMEM;
- }
+
mutex_init(&tdev->td_open_close_lock);
tdev->td_serial = serial;
usb_set_serial_data(serial, tdev);
/* determine device type */
- if (usb_match_id(serial->interface, ti_id_table_3410))
+ if (serial->type == &ti_1port_device)
tdev->td_is_3410 = 1;
- dbg("%s - device type is %s", __func__,
- tdev->td_is_3410 ? "3410" : "5052");
+ dev_dbg(&dev->dev, "%s - device type is %s\n", __func__,
+ tdev->td_is_3410 ? "3410" : "5052");
/* if we have only 1 configuration, download firmware */
if (dev->descriptor.bNumConfigurations == 1) {
- if ((status = ti_download_firmware(tdev)) != 0)
+ status = ti_download_firmware(tdev);
+
+ if (status != 0)
goto free_tdev;
/* 3410 must be reset, 5052 resets itself */
@@ -431,42 +337,8 @@ static int ti_startup(struct usb_serial *serial)
goto free_tdev;
}
- /* set up port structures */
- for (i = 0; i < serial->num_ports; ++i) {
- tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL);
- if (tport == NULL) {
- dev_err(&dev->dev, "%s - out of memory\n", __func__);
- status = -ENOMEM;
- goto free_tports;
- }
- spin_lock_init(&tport->tp_lock);
- tport->tp_uart_base_addr = (i == 0 ?
- TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
- tport->tp_closing_wait = closing_wait;
- init_waitqueue_head(&tport->tp_msr_wait);
- init_waitqueue_head(&tport->tp_write_wait);
- if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE,
- GFP_KERNEL)) {
- dev_err(&dev->dev, "%s - out of memory\n", __func__);
- kfree(tport);
- status = -ENOMEM;
- goto free_tports;
- }
- tport->tp_port = serial->port[i];
- tport->tp_tdev = tdev;
- usb_set_serial_port_data(serial->port[i], tport);
- tport->tp_uart_mode = 0; /* default is RS232 */
- }
-
return 0;
-free_tports:
- for (--i; i >= 0; --i) {
- tport = usb_get_serial_port_data(serial->port[i]);
- kfifo_free(&tport->write_fifo);
- kfree(tport);
- usb_set_serial_port_data(serial->port[i], NULL);
- }
free_tdev:
kfree(tdev);
usb_set_serial_data(serial, NULL);
@@ -476,23 +348,45 @@ free_tdev:
static void ti_release(struct usb_serial *serial)
{
- int i;
struct ti_device *tdev = usb_get_serial_data(serial);
+
+ kfree(tdev);
+}
+
+static int ti_port_probe(struct usb_serial_port *port)
+{
struct ti_port *tport;
- dbg("%s", __func__);
+ tport = kzalloc(sizeof(*tport), GFP_KERNEL);
+ if (!tport)
+ return -ENOMEM;
- for (i = 0; i < serial->num_ports; ++i) {
- tport = usb_get_serial_port_data(serial->port[i]);
- if (tport) {
- kfifo_free(&tport->write_fifo);
- kfree(tport);
- }
- }
+ spin_lock_init(&tport->tp_lock);
+ if (port == port->serial->port[0])
+ tport->tp_uart_base_addr = TI_UART1_BASE_ADDR;
+ else
+ tport->tp_uart_base_addr = TI_UART2_BASE_ADDR;
+ port->port.closing_wait = msecs_to_jiffies(10 * closing_wait);
+ tport->tp_port = port;
+ tport->tp_tdev = usb_get_serial_data(port->serial);
+ tport->tp_uart_mode = 0; /* default is RS232 */
- kfree(tdev);
+ usb_set_serial_port_data(port, tport);
+
+ port->port.drain_delay = 3;
+
+ return 0;
}
+static int ti_port_remove(struct usb_serial_port *port)
+{
+ struct ti_port *tport;
+
+ tport = usb_get_serial_port_data(port);
+ kfree(tport);
+
+ return 0;
+}
static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
{
@@ -506,8 +400,6 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
TI_PIPE_TIMEOUT_ENABLE |
(TI_TRANSFER_TIMEOUT << 2));
- dbg("%s - port %d", __func__, port->number);
-
if (tport == NULL)
return -ENODEV;
@@ -518,48 +410,41 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
if (mutex_lock_interruptible(&tdev->td_open_close_lock))
return -ERESTARTSYS;
- port_number = port->number - port->serial->minor;
-
- memset(&(tport->tp_icount), 0x00, sizeof(tport->tp_icount));
+ port_number = port->port_number;
tport->tp_msr = 0;
tport->tp_shadow_mcr |= (TI_MCR_RTS | TI_MCR_DTR);
/* start interrupt urb the first time a port is opened on this device */
if (tdev->td_open_port_count == 0) {
- dbg("%s - start interrupt in urb", __func__);
+ dev_dbg(&port->dev, "%s - start interrupt in urb\n", __func__);
urb = tdev->td_serial->port[0]->interrupt_in_urb;
if (!urb) {
- dev_err(&port->dev, "%s - no interrupt urb\n",
- __func__);
+ dev_err(&port->dev, "%s - no interrupt urb\n", __func__);
status = -EINVAL;
goto release_lock;
}
- urb->complete = ti_interrupt_callback;
urb->context = tdev;
- urb->dev = dev;
status = usb_submit_urb(urb, GFP_KERNEL);
if (status) {
- dev_err(&port->dev,
- "%s - submit interrupt urb failed, %d\n",
- __func__, status);
+ dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __func__, status);
goto release_lock;
}
}
if (tty)
- ti_set_termios(tty, port, tty->termios);
+ ti_set_termios(tty, port, &tty->termios);
- dbg("%s - sending TI_OPEN_PORT", __func__);
+ dev_dbg(&port->dev, "%s - sending TI_OPEN_PORT\n", __func__);
status = ti_command_out_sync(tdev, TI_OPEN_PORT,
(__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
if (status) {
dev_err(&port->dev, "%s - cannot send open command, %d\n",
- __func__, status);
+ __func__, status);
goto unlink_int_urb;
}
- dbg("%s - sending TI_START_PORT", __func__);
+ dev_dbg(&port->dev, "%s - sending TI_START_PORT\n", __func__);
status = ti_command_out_sync(tdev, TI_START_PORT,
(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
if (status) {
@@ -568,7 +453,7 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
goto unlink_int_urb;
}
- dbg("%s - sending TI_PURGE_PORT", __func__);
+ dev_dbg(&port->dev, "%s - sending TI_PURGE_PORT\n", __func__);
status = ti_command_out_sync(tdev, TI_PURGE_PORT,
(__u8)(TI_UART1_PORT + port_number), TI_PURGE_INPUT, NULL, 0);
if (status) {
@@ -590,9 +475,9 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
usb_clear_halt(dev, port->read_urb->pipe);
if (tty)
- ti_set_termios(tty, port, tty->termios);
+ ti_set_termios(tty, port, &tty->termios);
- dbg("%s - sending TI_OPEN_PORT (2)", __func__);
+ dev_dbg(&port->dev, "%s - sending TI_OPEN_PORT (2)\n", __func__);
status = ti_command_out_sync(tdev, TI_OPEN_PORT,
(__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
if (status) {
@@ -601,7 +486,7 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
goto unlink_int_urb;
}
- dbg("%s - sending TI_START_PORT (2)", __func__);
+ dev_dbg(&port->dev, "%s - sending TI_START_PORT (2)\n", __func__);
status = ti_command_out_sync(tdev, TI_START_PORT,
(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
if (status) {
@@ -611,7 +496,7 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
}
/* start read urb */
- dbg("%s - start read urb", __func__);
+ dev_dbg(&port->dev, "%s - start read urb\n", __func__);
urb = port->read_urb;
if (!urb) {
dev_err(&port->dev, "%s - no read urb\n", __func__);
@@ -619,9 +504,7 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
goto unlink_int_urb;
}
tport->tp_read_urb_state = TI_READ_URB_RUNNING;
- urb->complete = ti_bulk_in_callback;
urb->context = tport;
- urb->dev = dev;
status = usb_submit_urb(urb, GFP_KERNEL);
if (status) {
dev_err(&port->dev, "%s - submit read urb failed, %d\n",
@@ -639,7 +522,7 @@ unlink_int_urb:
usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
release_lock:
mutex_unlock(&tdev->td_open_close_lock);
- dbg("%s - exit %d", __func__, status);
+ dev_dbg(&port->dev, "%s - exit %d\n", __func__, status);
return status;
}
@@ -651,8 +534,7 @@ static void ti_close(struct usb_serial_port *port)
int port_number;
int status;
int do_unlock;
-
- dbg("%s - port %d", __func__, port->number);
+ unsigned long flags;
tdev = usb_get_serial_data(port->serial);
tport = usb_get_serial_port_data(port);
@@ -661,15 +543,16 @@ static void ti_close(struct usb_serial_port *port)
tport->tp_is_open = 0;
- ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 1);
-
usb_kill_urb(port->read_urb);
usb_kill_urb(port->write_urb);
tport->tp_write_urb_in_use = 0;
+ spin_lock_irqsave(&tport->tp_lock, flags);
+ kfifo_reset_out(&port->write_fifo);
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
- port_number = port->number - port->serial->minor;
+ port_number = port->port_number;
- dbg("%s - sending TI_CLOSE_PORT", __func__);
+ dev_dbg(&port->dev, "%s - sending TI_CLOSE_PORT\n", __func__);
status = ti_command_out_sync(tdev, TI_CLOSE_PORT,
(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
if (status)
@@ -687,8 +570,6 @@ static void ti_close(struct usb_serial_port *port)
}
if (do_unlock)
mutex_unlock(&tdev->td_open_close_lock);
-
- dbg("%s - exit", __func__);
}
@@ -697,17 +578,15 @@ static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
{
struct ti_port *tport = usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
-
if (count == 0) {
- dbg("%s - write request of 0 bytes", __func__);
+ dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__);
return 0;
}
if (tport == NULL || !tport->tp_is_open)
return -ENODEV;
- count = kfifo_in_locked(&tport->write_fifo, data, count,
+ count = kfifo_in_locked(&port->write_fifo, data, count,
&tport->tp_lock);
ti_send(tport);
@@ -722,16 +601,14 @@ static int ti_write_room(struct tty_struct *tty)
int room = 0;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
if (tport == NULL)
return 0;
spin_lock_irqsave(&tport->tp_lock, flags);
- room = kfifo_avail(&tport->write_fifo);
+ room = kfifo_avail(&port->write_fifo);
spin_unlock_irqrestore(&tport->tp_lock, flags);
- dbg("%s - returns %d", __func__, room);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, room);
return room;
}
@@ -743,27 +620,35 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
int chars = 0;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
if (tport == NULL)
return 0;
spin_lock_irqsave(&tport->tp_lock, flags);
- chars = kfifo_len(&tport->write_fifo);
+ chars = kfifo_len(&port->write_fifo);
spin_unlock_irqrestore(&tport->tp_lock, flags);
- dbg("%s - returns %d", __func__, chars);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
return chars;
}
+static bool ti_tx_empty(struct usb_serial_port *port)
+{
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ int ret;
+ u8 lsr;
+
+ ret = ti_get_lsr(tport, &lsr);
+ if (!ret && !(lsr & TI_LSR_TX_EMPTY))
+ return false;
+
+ return true;
+}
static void ti_throttle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
-
if (tport == NULL)
return;
@@ -779,8 +664,6 @@ static void ti_unthrottle(struct tty_struct *tty)
struct ti_port *tport = usb_get_serial_port_data(port);
int status;
- dbg("%s - port %d", __func__, port->number);
-
if (tport == NULL)
return;
@@ -792,73 +675,24 @@ static void ti_unthrottle(struct tty_struct *tty)
}
}
-static int ti_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct ti_port *tport = usb_get_serial_port_data(port);
- struct async_icount cnow = tport->tp_icount;
-
- dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d",
- __func__, port->number,
- cnow.rx, cnow.tx);
-
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
-
- return 0;
-}
-
-static int ti_ioctl(struct tty_struct *tty, struct file *file,
+static int ti_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
- struct async_icount cnow;
- struct async_icount cprev;
-
- dbg("%s - port %d, cmd = 0x%04X", __func__, port->number, cmd);
if (tport == NULL)
return -ENODEV;
switch (cmd) {
case TIOCGSERIAL:
- dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
+ dev_dbg(&port->dev, "%s - TIOCGSERIAL\n", __func__);
return ti_get_serial_info(tport,
(struct serial_struct __user *)arg);
case TIOCSSERIAL:
- dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
+ dev_dbg(&port->dev, "%s - TIOCSSERIAL\n", __func__);
return ti_set_serial_info(tty, tport,
(struct serial_struct __user *)arg);
- case TIOCMIWAIT:
- dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
- cprev = tport->tp_icount;
- while (1) {
- interruptible_sleep_on(&tport->tp_msr_wait);
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = tport->tp_icount;
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)))
- return 0;
- cprev = cnow;
- }
- break;
}
return -ENOIOCTLCMD;
}
@@ -872,26 +706,22 @@ static void ti_set_termios(struct tty_struct *tty,
tcflag_t cflag, iflag;
int baud;
int status;
- int port_number = port->number - port->serial->minor;
+ int port_number = port->port_number;
unsigned int mcr;
- dbg("%s - port %d", __func__, port->number);
+ cflag = tty->termios.c_cflag;
+ iflag = tty->termios.c_iflag;
- cflag = tty->termios->c_cflag;
- iflag = tty->termios->c_iflag;
-
- dbg("%s - cflag %08x, iflag %08x", __func__, cflag, iflag);
- dbg("%s - old clfag %08x, old iflag %08x", __func__,
- old_termios->c_cflag, old_termios->c_iflag);
+ dev_dbg(&port->dev, "%s - cflag %08x, iflag %08x\n", __func__, cflag, iflag);
+ dev_dbg(&port->dev, "%s - old clfag %08x, old iflag %08x\n", __func__,
+ old_termios->c_cflag, old_termios->c_iflag);
if (tport == NULL)
return;
config = kmalloc(sizeof(*config), GFP_KERNEL);
- if (!config) {
- dev_err(&port->dev, "%s - out of memory\n", __func__);
+ if (!config)
return;
- }
config->wFlags = 0;
@@ -917,7 +747,7 @@ static void ti_set_termios(struct tty_struct *tty,
}
/* CMSPAR isn't supported by this driver */
- tty->termios->c_cflag &= ~CMSPAR;
+ tty->termios.c_cflag &= ~CMSPAR;
if (cflag & PARENB) {
if (cflag & PARODD) {
@@ -972,8 +802,11 @@ static void ti_set_termios(struct tty_struct *tty,
if ((cflag & CBAUD) != B0)
tty_encode_baud_rate(tty, baud, baud);
- dbg("%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d",
- __func__, baud, config->wBaudRate, config->wFlags, config->bDataBits, config->bParity, config->bStopBits, config->cXon, config->cXoff, config->bUartMode);
+ dev_dbg(&port->dev,
+ "%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d\n",
+ __func__, baud, config->wBaudRate, config->wFlags,
+ config->bDataBits, config->bParity, config->bStopBits,
+ config->cXon, config->cXoff, config->bUartMode);
cpu_to_be16s(&config->wBaudRate);
cpu_to_be16s(&config->wFlags);
@@ -1000,7 +833,7 @@ static void ti_set_termios(struct tty_struct *tty,
}
-static int ti_tiocmget(struct tty_struct *tty, struct file *file)
+static int ti_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
@@ -1009,8 +842,6 @@ static int ti_tiocmget(struct tty_struct *tty, struct file *file)
unsigned int mcr;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
if (tport == NULL)
return -ENODEV;
@@ -1027,22 +858,20 @@ static int ti_tiocmget(struct tty_struct *tty, struct file *file)
| ((msr & TI_MSR_RI) ? TIOCM_RI : 0)
| ((msr & TI_MSR_DSR) ? TIOCM_DSR : 0);
- dbg("%s - 0x%04X", __func__, result);
+ dev_dbg(&port->dev, "%s - 0x%04X\n", __func__, result);
return result;
}
-static int ti_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
+static int ti_tiocmset(struct tty_struct *tty,
+ unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
unsigned int mcr;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
if (tport == NULL)
return -ENODEV;
@@ -1074,19 +903,17 @@ static void ti_break(struct tty_struct *tty, int break_state)
struct ti_port *tport = usb_get_serial_port_data(port);
int status;
- dbg("%s - state = %d", __func__, break_state);
+ dev_dbg(&port->dev, "%s - state = %d\n", __func__, break_state);
if (tport == NULL)
return;
- ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 0);
-
- status = ti_write_byte(tport->tp_tdev,
+ status = ti_write_byte(port, tport->tp_tdev,
tport->tp_uart_base_addr + TI_UART_OFFSET_LCR,
TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0);
if (status)
- dbg("%s - error setting break, %d", __func__, status);
+ dev_dbg(&port->dev, "%s - error setting break, %d\n", __func__, status);
}
@@ -1105,26 +932,23 @@ static void ti_interrupt_callback(struct urb *urb)
int retval;
__u8 msr;
- dbg("%s", __func__);
-
switch (status) {
case 0:
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
- dbg("%s - urb shutting down, %d", __func__, status);
+ dev_dbg(dev, "%s - urb shutting down, %d\n", __func__, status);
tdev->td_urb_error = 1;
return;
default:
- dev_err(dev, "%s - nonzero urb status, %d\n",
- __func__, status);
+ dev_err(dev, "%s - nonzero urb status, %d\n", __func__, status);
tdev->td_urb_error = 1;
goto exit;
}
if (length != 2) {
- dbg("%s - bad packet size, %d", __func__, length);
+ dev_dbg(dev, "%s - bad packet size, %d\n", __func__, length);
goto exit;
}
@@ -1136,8 +960,8 @@ static void ti_interrupt_callback(struct urb *urb)
port_number = TI_GET_PORT_FROM_CODE(data[0]);
function = TI_GET_FUNC_FROM_CODE(data[0]);
- dbg("%s - port_number %d, function %d, data 0x%02X",
- __func__, port_number, function, data[1]);
+ dev_dbg(dev, "%s - port_number %d, function %d, data 0x%02X\n",
+ __func__, port_number, function, data[1]);
if (port_number >= serial->num_ports) {
dev_err(dev, "%s - bad port number, %d\n",
@@ -1154,12 +978,12 @@ static void ti_interrupt_callback(struct urb *urb)
switch (function) {
case TI_CODE_DATA_ERROR:
dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n",
- __func__, port_number, data[1]);
+ __func__, port_number, data[1]);
break;
case TI_CODE_MODEM_STATUS:
msr = data[1];
- dbg("%s - port %d, msr 0x%02X", __func__, port_number, msr);
+ dev_dbg(dev, "%s - port %d, msr 0x%02X\n", __func__, port_number, msr);
ti_handle_new_msr(tport, msr);
break;
@@ -1184,9 +1008,6 @@ static void ti_bulk_in_callback(struct urb *urb)
struct device *dev = &urb->dev->dev;
int status = urb->status;
int retval = 0;
- struct tty_struct *tty;
-
- dbg("%s", __func__);
switch (status) {
case 0:
@@ -1194,15 +1015,13 @@ static void ti_bulk_in_callback(struct urb *urb)
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
- dbg("%s - urb shutting down, %d", __func__, status);
+ dev_dbg(dev, "%s - urb shutting down, %d\n", __func__, status);
tport->tp_tdev->td_urb_error = 1;
- wake_up_interruptible(&tport->tp_write_wait);
return;
default:
dev_err(dev, "%s - nonzero urb status, %d\n",
__func__, status);
tport->tp_tdev->td_urb_error = 1;
- wake_up_interruptible(&tport->tp_write_wait);
}
if (status == -EPIPE)
@@ -1213,35 +1032,28 @@ static void ti_bulk_in_callback(struct urb *urb)
return;
}
- tty = tty_port_tty_get(&port->port);
- if (tty) {
- if (urb->actual_length) {
- usb_serial_debug_data(debug, dev, __func__,
- urb->actual_length, urb->transfer_buffer);
+ if (urb->actual_length) {
+ usb_serial_debug_data(dev, __func__, urb->actual_length,
+ urb->transfer_buffer);
- if (!tport->tp_is_open)
- dbg("%s - port closed, dropping data",
- __func__);
- else
- ti_recv(&urb->dev->dev, tty,
- urb->transfer_buffer,
- urb->actual_length);
- spin_lock(&tport->tp_lock);
- tport->tp_icount.rx += urb->actual_length;
- spin_unlock(&tport->tp_lock);
- }
- tty_kref_put(tty);
+ if (!tport->tp_is_open)
+ dev_dbg(dev, "%s - port closed, dropping data\n",
+ __func__);
+ else
+ ti_recv(port, urb->transfer_buffer, urb->actual_length);
+ spin_lock(&tport->tp_lock);
+ port->icount.rx += urb->actual_length;
+ spin_unlock(&tport->tp_lock);
}
exit:
/* continue to read unless stopping */
spin_lock(&tport->tp_lock);
- if (tport->tp_read_urb_state == TI_READ_URB_RUNNING) {
- urb->dev = port->serial->dev;
+ if (tport->tp_read_urb_state == TI_READ_URB_RUNNING)
retval = usb_submit_urb(urb, GFP_ATOMIC);
- } else if (tport->tp_read_urb_state == TI_READ_URB_STOPPING) {
+ else if (tport->tp_read_urb_state == TI_READ_URB_STOPPING)
tport->tp_read_urb_state = TI_READ_URB_STOPPED;
- }
+
spin_unlock(&tport->tp_lock);
if (retval)
dev_err(dev, "%s - resubmit read urb failed, %d\n",
@@ -1253,11 +1065,8 @@ static void ti_bulk_out_callback(struct urb *urb)
{
struct ti_port *tport = urb->context;
struct usb_serial_port *port = tport->tp_port;
- struct device *dev = &urb->dev->dev;
int status = urb->status;
- dbg("%s - port %d", __func__, port->number);
-
tport->tp_write_urb_in_use = 0;
switch (status) {
@@ -1266,15 +1075,13 @@ static void ti_bulk_out_callback(struct urb *urb)
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
- dbg("%s - urb shutting down, %d", __func__, status);
+ dev_dbg(&port->dev, "%s - urb shutting down, %d\n", __func__, status);
tport->tp_tdev->td_urb_error = 1;
- wake_up_interruptible(&tport->tp_write_wait);
return;
default:
- dev_err(dev, "%s - nonzero urb status, %d\n",
+ dev_err_console(port, "%s - nonzero urb status, %d\n",
__func__, status);
tport->tp_tdev->td_urb_error = 1;
- wake_up_interruptible(&tport->tp_write_wait);
}
/* send any buffered data */
@@ -1282,24 +1089,23 @@ static void ti_bulk_out_callback(struct urb *urb)
}
-static void ti_recv(struct device *dev, struct tty_struct *tty,
- unsigned char *data, int length)
+static void ti_recv(struct usb_serial_port *port, unsigned char *data,
+ int length)
{
int cnt;
do {
- cnt = tty_insert_flip_string(tty, data, length);
+ cnt = tty_insert_flip_string(&port->port, data, length);
if (cnt < length) {
- dev_err(dev, "%s - dropping data, %d bytes lost\n",
+ dev_err(&port->dev, "%s - dropping data, %d bytes lost\n",
__func__, length - cnt);
if (cnt == 0)
break;
}
- tty_flip_buffer_push(tty);
+ tty_flip_buffer_push(&port->port);
data += cnt;
length -= cnt;
} while (length > 0);
-
}
@@ -1307,18 +1113,14 @@ static void ti_send(struct ti_port *tport)
{
int count, result;
struct usb_serial_port *port = tport->tp_port;
- struct tty_struct *tty = tty_port_tty_get(&port->port); /* FIXME */
unsigned long flags;
-
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&tport->tp_lock, flags);
if (tport->tp_write_urb_in_use)
goto unlock;
- count = kfifo_out(&tport->write_fifo,
+ count = kfifo_out(&port->write_fifo,
port->write_urb->transfer_buffer,
port->bulk_out_size);
@@ -1329,8 +1131,8 @@ static void ti_send(struct ti_port *tport)
spin_unlock_irqrestore(&tport->tp_lock, flags);
- usb_serial_debug_data(debug, &port->dev, __func__, count,
- port->write_urb->transfer_buffer);
+ usb_serial_debug_data(&port->dev, __func__, count,
+ port->write_urb->transfer_buffer);
usb_fill_bulk_urb(port->write_urb, port->serial->dev,
usb_sndbulkpipe(port->serial->dev,
@@ -1340,25 +1142,22 @@ static void ti_send(struct ti_port *tport)
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s - submit write urb failed, %d\n",
+ dev_err_console(port, "%s - submit write urb failed, %d\n",
__func__, result);
tport->tp_write_urb_in_use = 0;
/* TODO: reschedule ti_send */
} else {
spin_lock_irqsave(&tport->tp_lock, flags);
- tport->tp_icount.tx += count;
+ port->icount.tx += count;
spin_unlock_irqrestore(&tport->tp_lock, flags);
}
/* more room in the buffer for new writes, wakeup */
- if (tty)
- tty_wakeup(tty);
- tty_kref_put(tty);
- wake_up_interruptible(&tport->tp_write_wait);
+ tty_port_tty_wakeup(&port->port);
+
return;
unlock:
spin_unlock_irqrestore(&tport->tp_lock, flags);
- tty_kref_put(tty);
return;
}
@@ -1368,7 +1167,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr)
unsigned long flags;
int status;
- status = ti_write_byte(tport->tp_tdev,
+ status = ti_write_byte(tport->tp_port, tport->tp_tdev,
tport->tp_uart_base_addr + TI_UART_OFFSET_MCR,
TI_MCR_RTS | TI_MCR_DTR | TI_MCR_LOOP, mcr);
@@ -1381,22 +1180,18 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr)
}
-static int ti_get_lsr(struct ti_port *tport)
+static int ti_get_lsr(struct ti_port *tport, u8 *lsr)
{
int size, status;
struct ti_device *tdev = tport->tp_tdev;
struct usb_serial_port *port = tport->tp_port;
- int port_number = port->number - port->serial->minor;
+ int port_number = port->port_number;
struct ti_port_status *data;
- dbg("%s - port %d", __func__, port->number);
-
size = sizeof(struct ti_port_status);
data = kmalloc(size, GFP_KERNEL);
- if (!data) {
- dev_err(&port->dev, "%s - out of memory\n", __func__);
+ if (!data)
return -ENOMEM;
- }
status = ti_command_in_sync(tdev, TI_GET_PORT_STATUS,
(__u8)(TI_UART1_PORT+port_number), 0, (__u8 *)data, size);
@@ -1407,9 +1202,9 @@ static int ti_get_lsr(struct ti_port *tport)
goto free_data;
}
- dbg("%s - lsr 0x%02X", __func__, data->bLSR);
+ dev_dbg(&port->dev, "%s - lsr 0x%02X\n", __func__, data->bLSR);
- tport->tp_lsr = data->bLSR;
+ *lsr = data->bLSR;
free_data:
kfree(data);
@@ -1422,19 +1217,24 @@ static int ti_get_serial_info(struct ti_port *tport,
{
struct usb_serial_port *port = tport->tp_port;
struct serial_struct ret_serial;
+ unsigned cwait;
if (!ret_arg)
return -EFAULT;
+ cwait = port->port.closing_wait;
+ if (cwait != ASYNC_CLOSING_WAIT_NONE)
+ cwait = jiffies_to_msecs(cwait) / 10;
+
memset(&ret_serial, 0, sizeof(ret_serial));
ret_serial.type = PORT_16550A;
- ret_serial.line = port->serial->minor;
- ret_serial.port = port->number - port->serial->minor;
+ ret_serial.line = port->minor;
+ ret_serial.port = port->port_number;
ret_serial.flags = tport->tp_flags;
- ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE;
+ ret_serial.xmit_fifo_size = kfifo_size(&port->write_fifo);
ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800;
- ret_serial.closing_wait = tport->tp_closing_wait;
+ ret_serial.closing_wait = cwait;
if (copy_to_user(ret_arg, &ret_serial, sizeof(*ret_arg)))
return -EFAULT;
@@ -1447,12 +1247,17 @@ static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,
struct serial_struct __user *new_arg)
{
struct serial_struct new_serial;
+ unsigned cwait;
if (copy_from_user(&new_serial, new_arg, sizeof(new_serial)))
return -EFAULT;
+ cwait = new_serial.closing_wait;
+ if (cwait != ASYNC_CLOSING_WAIT_NONE)
+ cwait = msecs_to_jiffies(10 * new_serial.closing_wait);
+
tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS;
- tport->tp_closing_wait = new_serial.closing_wait;
+ tport->tp_port->port.closing_wait = cwait;
return 0;
}
@@ -1464,11 +1269,11 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
struct tty_struct *tty;
unsigned long flags;
- dbg("%s - msr 0x%02X", __func__, msr);
+ dev_dbg(&tport->tp_port->dev, "%s - msr 0x%02X\n", __func__, msr);
if (msr & TI_MSR_DELTA_MASK) {
spin_lock_irqsave(&tport->tp_lock, flags);
- icount = &tport->tp_icount;
+ icount = &tport->tp_port->icount;
if (msr & TI_MSR_DELTA_CTS)
icount->cts++;
if (msr & TI_MSR_DELTA_DSR)
@@ -1477,7 +1282,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
icount->dcd++;
if (msr & TI_MSR_DELTA_RI)
icount->rng++;
- wake_up_interruptible(&tport->tp_msr_wait);
+ wake_up_interruptible(&tport->tp_port->port.delta_msr_wait);
spin_unlock_irqrestore(&tport->tp_lock, flags);
}
@@ -1497,58 +1302,6 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
}
-static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
-{
- struct ti_device *tdev = tport->tp_tdev;
- struct usb_serial_port *port = tport->tp_port;
- wait_queue_t wait;
-
- dbg("%s - port %d", __func__, port->number);
-
- spin_lock_irq(&tport->tp_lock);
-
- /* wait for data to drain from the buffer */
- tdev->td_urb_error = 0;
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&tport->tp_write_wait, &wait);
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (kfifo_len(&tport->write_fifo) == 0
- || timeout == 0 || signal_pending(current)
- || tdev->td_urb_error
- || port->serial->disconnected) /* disconnect */
- break;
- spin_unlock_irq(&tport->tp_lock);
- timeout = schedule_timeout(timeout);
- spin_lock_irq(&tport->tp_lock);
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&tport->tp_write_wait, &wait);
-
- /* flush any remaining data in the buffer */
- if (flush)
- kfifo_reset_out(&tport->write_fifo);
-
- spin_unlock_irq(&tport->tp_lock);
-
- mutex_lock(&port->serial->disc_mutex);
- /* wait for data to drain from the device */
- /* wait for empty tx register, plus 20 ms */
- timeout += jiffies;
- tport->tp_lsr &= ~TI_LSR_TX_EMPTY;
- while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
- && !(tport->tp_lsr&TI_LSR_TX_EMPTY) && !tdev->td_urb_error
- && !port->serial->disconnected) {
- if (ti_get_lsr(tport))
- break;
- mutex_unlock(&port->serial->disc_mutex);
- msleep_interruptible(20);
- mutex_lock(&port->serial->disc_mutex);
- }
- mutex_unlock(&port->serial->disc_mutex);
-}
-
-
static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty)
{
unsigned long flags;
@@ -1574,9 +1327,7 @@ static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty)
tport->tp_read_urb_state = TI_READ_URB_RUNNING;
urb = tport->tp_port->read_urb;
spin_unlock_irqrestore(&tport->tp_lock, flags);
- urb->complete = ti_bulk_in_callback;
urb->context = tport;
- urb->dev = tport->tp_port->serial->dev;
status = usb_submit_urb(urb, GFP_KERNEL);
} else {
tport->tp_read_urb_state = TI_READ_URB_RUNNING;
@@ -1627,23 +1378,21 @@ static int ti_command_in_sync(struct ti_device *tdev, __u8 command,
}
-static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
- __u8 mask, __u8 byte)
+static int ti_write_byte(struct usb_serial_port *port,
+ struct ti_device *tdev, unsigned long addr,
+ __u8 mask, __u8 byte)
{
int status;
unsigned int size;
struct ti_write_data_bytes *data;
- struct device *dev = &tdev->td_serial->dev->dev;
- dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X",
- __func__, addr, mask, byte);
+ dev_dbg(&port->dev, "%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X\n", __func__,
+ addr, mask, byte);
size = sizeof(struct ti_write_data_bytes) + 2;
data = kmalloc(size, GFP_KERNEL);
- if (!data) {
- dev_err(dev, "%s - out of memory\n", __func__);
+ if (!data)
return -ENOMEM;
- }
data->bAddrType = TI_RW_DATA_ADDR_XDATA;
data->bDataType = TI_RW_DATA_BYTE;
@@ -1657,7 +1406,7 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
(__u8 *)data, size);
if (status < 0)
- dev_err(dev, "%s - failed, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - failed, %d\n", __func__, status);
kfree(data);
@@ -1682,7 +1431,7 @@ static int ti_do_download(struct usb_device *dev, int pipe,
- sizeof(struct ti_firmware_header)));
header->bCheckSum = cs;
- dbg("%s - downloading firmware", __func__);
+ dev_dbg(&dev->dev, "%s - downloading firmware\n", __func__);
for (pos = 0; pos < size; pos += done) {
len = min(size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
status = usb_bulk_msg(dev, pipe, buffer + pos, len,
@@ -1704,14 +1453,16 @@ static int ti_download_firmware(struct ti_device *tdev)
const struct firmware *fw_p;
char buf[32];
- dbg("%s\n", __func__);
/* try ID specific firmware first, then try generic firmware */
- sprintf(buf, "ti_usb-v%04x-p%04x.fw", dev->descriptor.idVendor,
- dev->descriptor.idProduct);
- if ((status = request_firmware(&fw_p, buf, &dev->dev)) != 0) {
+ sprintf(buf, "ti_usb-v%04x-p%04x.fw",
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
+ status = request_firmware(&fw_p, buf, &dev->dev);
+
+ if (status != 0) {
buf[0] = '\0';
- if (dev->descriptor.idVendor == MTS_VENDOR_ID) {
- switch (dev->descriptor.idProduct) {
+ if (le16_to_cpu(dev->descriptor.idVendor) == MTS_VENDOR_ID) {
+ switch (le16_to_cpu(dev->descriptor.idProduct)) {
case MTS_CDMA_PRODUCT_ID:
strcpy(buf, "mts_cdma.fw");
break;
@@ -1745,6 +1496,7 @@ static int ti_download_firmware(struct ti_device *tdev)
}
if (fw_p->size > TI_FIRMWARE_BUF_SIZE) {
dev_err(&dev->dev, "%s - firmware too large %zu\n", __func__, fw_p->size);
+ release_firmware(fw_p);
return -ENOENT;
}
@@ -1756,7 +1508,6 @@ static int ti_download_firmware(struct ti_device *tdev)
status = ti_do_download(dev, pipe, buffer, fw_p->size);
kfree(buffer);
} else {
- dbg("%s ENOMEM\n", __func__);
status = -ENOMEM;
}
release_firmware(fw_p);
@@ -1766,7 +1517,7 @@ static int ti_download_firmware(struct ti_device *tdev)
return status;
}
- dbg("%s - download successful", __func__);
+ dev_dbg(&dev->dev, "%s - download successful\n", __func__);
return 0;
}
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h
index 2aac1953993..4a2423e84d5 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.h
+++ b/drivers/usb/serial/ti_usb_3410_5052.h
@@ -37,6 +37,7 @@
#define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */
#define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */
#define TI_5052_FIRMWARE_PRODUCT_ID 0x505F /* firmware is running */
+#define FRI2_PRODUCT_ID 0x5053 /* Fish River Island II */
/* Multi-Tech vendor and product ids */
#define MTS_VENDOR_ID 0x06E0
@@ -49,6 +50,12 @@
#define MTS_MT9234ZBA_PRODUCT_ID 0xF115
#define MTS_MT9234ZBAOLD_PRODUCT_ID 0x0319
+/* Abbott Diabetics vendor and product ids */
+#define ABBOTT_VENDOR_ID 0x1a61
+#define ABBOTT_STEREO_PLUG_ID 0x3410
+#define ABBOTT_PRODUCT_ID ABBOTT_STEREO_PLUG_ID
+#define ABBOTT_STRIP_PORT_ID 0x3420
+
/* Commands */
#define TI_GET_VERSION 0x01
#define TI_GET_PORT_STATUS 0x02
diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c
new file mode 100644
index 00000000000..fb79775447b
--- /dev/null
+++ b/drivers/usb/serial/usb-serial-simple.c
@@ -0,0 +1,110 @@
+/*
+ * USB Serial "Simple" driver
+ *
+ * Copyright (C) 2001-2006,2008,2013 Greg Kroah-Hartman <greg@kroah.com>
+ * Copyright (C) 2005 Arthur Huillet (ahuillet@users.sf.net)
+ * Copyright (C) 2005 Thomas Hergenhahn <thomas.hergenhahn@suse.de>
+ * Copyright (C) 2009 Outpost Embedded, LLC
+ * Copyright (C) 2010 Zilogic Systems <code@zilogic.com>
+ * Copyright (C) 2013 Wei Shuai <cpuwolf@gmail.com>
+ * Copyright (C) 2013 Linux Foundation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+#define DEVICE(vendor, IDS) \
+static const struct usb_device_id vendor##_id_table[] = { \
+ IDS(), \
+ { }, \
+}; \
+static struct usb_serial_driver vendor##_device = { \
+ .driver = { \
+ .owner = THIS_MODULE, \
+ .name = #vendor, \
+ }, \
+ .id_table = vendor##_id_table, \
+ .num_ports = 1, \
+};
+
+
+/* ZIO Motherboard USB driver */
+#define ZIO_IDS() \
+ { USB_DEVICE(0x1CBE, 0x0103) }
+DEVICE(zio, ZIO_IDS);
+
+/* Funsoft Serial USB driver */
+#define FUNSOFT_IDS() \
+ { USB_DEVICE(0x1404, 0xcddc) }
+DEVICE(funsoft, FUNSOFT_IDS);
+
+/* Infineon Flashloader driver */
+#define FLASHLOADER_IDS() \
+ { USB_DEVICE(0x8087, 0x0716) }
+DEVICE(flashloader, FLASHLOADER_IDS);
+
+/* ViVOpay USB Serial Driver */
+#define VIVOPAY_IDS() \
+ { USB_DEVICE(0x1d5f, 0x1004) } /* ViVOpay 8800 */
+DEVICE(vivopay, VIVOPAY_IDS);
+
+/* Motorola USB Phone driver */
+#define MOTO_IDS() \
+ { USB_DEVICE(0x05c6, 0x3197) }, /* unknown Motorola phone */ \
+ { USB_DEVICE(0x0c44, 0x0022) }, /* unknown Mororola phone */ \
+ { USB_DEVICE(0x22b8, 0x2a64) }, /* Motorola KRZR K1m */ \
+ { USB_DEVICE(0x22b8, 0x2c84) }, /* Motorola VE240 phone */ \
+ { USB_DEVICE(0x22b8, 0x2c64) } /* Motorola V950 phone */
+DEVICE(moto_modem, MOTO_IDS);
+
+/* HP4x (48/49) Generic Serial driver */
+#define HP4X_IDS() \
+ { USB_DEVICE(0x03f0, 0x0121) }
+DEVICE(hp4x, HP4X_IDS);
+
+/* Suunto ANT+ USB Driver */
+#define SUUNTO_IDS() \
+ { USB_DEVICE(0x0fcf, 0x1008) }, \
+ { USB_DEVICE(0x0fcf, 0x1009) } /* Dynastream ANT USB-m Stick */
+DEVICE(suunto, SUUNTO_IDS);
+
+/* Siemens USB/MPI adapter */
+#define SIEMENS_IDS() \
+ { USB_DEVICE(0x908, 0x0004) }
+DEVICE(siemens_mpi, SIEMENS_IDS);
+
+/* All of the above structures mushed into two lists */
+static struct usb_serial_driver * const serial_drivers[] = {
+ &zio_device,
+ &funsoft_device,
+ &flashloader_device,
+ &vivopay_device,
+ &moto_modem_device,
+ &hp4x_device,
+ &suunto_device,
+ &siemens_mpi_device,
+ NULL
+};
+
+static const struct usb_device_id id_table[] = {
+ ZIO_IDS(),
+ FUNSOFT_IDS(),
+ FLASHLOADER_IDS(),
+ VIVOPAY_IDS(),
+ MOTO_IDS(),
+ HP4X_IDS(),
+ SUUNTO_IDS(),
+ SIEMENS_IDS(),
+ { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+module_usb_serial_driver(serial_drivers, id_table);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index e64da74bdcc..02de3110fe9 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1,7 +1,8 @@
/*
* USB Serial Converter driver
*
- * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2009 - 2013 Johan Hovold (jhovold@gmail.com)
+ * Copyright (C) 1999 - 2012 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2000 Peter Berger (pberger@brimson.com)
* Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
*
@@ -14,14 +15,14 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this
* driver
- *
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
@@ -36,23 +37,14 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include <linux/kfifo.h>
+#include <linux/idr.h>
#include "pl2303.h"
-/*
- * Version Information
- */
-#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
#define DRIVER_DESC "USB Serial Driver core"
-/* Driver structure we register with the USB core */
-static struct usb_driver usb_serial_driver = {
- .name = "usbserial",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .no_dynamic_id = 1,
-};
+#define USB_SERIAL_TTY_MAJOR 188
+#define USB_SERIAL_TTY_MINORS 512 /* should be enough for a while */
/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
the MODULE_DEVICE_TABLE declarations in each serial driver
@@ -61,85 +53,75 @@ static struct usb_driver usb_serial_driver = {
drivers depend on it.
*/
-static int debug;
-/* initially all NULL */
-static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
+static DEFINE_IDR(serial_minors);
static DEFINE_MUTEX(table_lock);
static LIST_HEAD(usb_serial_driver_list);
/*
- * Look up the serial structure. If it is found and it hasn't been
- * disconnected, return with its disc_mutex held and its refcount
- * incremented. Otherwise return NULL.
+ * Look up the serial port structure. If it is found and it hasn't been
+ * disconnected, return with the parent usb_serial structure's disc_mutex held
+ * and its refcount incremented. Otherwise return NULL.
*/
-struct usb_serial *usb_serial_get_by_index(unsigned index)
+struct usb_serial_port *usb_serial_port_get_by_minor(unsigned minor)
{
struct usb_serial *serial;
+ struct usb_serial_port *port;
mutex_lock(&table_lock);
- serial = serial_table[index];
-
- if (serial) {
- mutex_lock(&serial->disc_mutex);
- if (serial->disconnected) {
- mutex_unlock(&serial->disc_mutex);
- serial = NULL;
- } else {
- kref_get(&serial->kref);
- }
+ port = idr_find(&serial_minors, minor);
+ if (!port)
+ goto exit;
+
+ serial = port->serial;
+ mutex_lock(&serial->disc_mutex);
+ if (serial->disconnected) {
+ mutex_unlock(&serial->disc_mutex);
+ port = NULL;
+ } else {
+ kref_get(&serial->kref);
}
+exit:
mutex_unlock(&table_lock);
- return serial;
+ return port;
}
-static struct usb_serial *get_free_serial(struct usb_serial *serial,
- int num_ports, unsigned int *minor)
+static int allocate_minors(struct usb_serial *serial, int num_ports)
{
+ struct usb_serial_port *port;
unsigned int i, j;
- int good_spot;
+ int minor;
- dbg("%s %d", __func__, num_ports);
+ dev_dbg(&serial->interface->dev, "%s %d\n", __func__, num_ports);
- *minor = 0;
mutex_lock(&table_lock);
- for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
- if (serial_table[i])
- continue;
-
- good_spot = 1;
- for (j = 1; j <= num_ports-1; ++j)
- if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) {
- good_spot = 0;
- i += j;
- break;
- }
- if (good_spot == 0)
- continue;
-
- *minor = i;
- j = 0;
- dbg("%s - minor base = %d", __func__, *minor);
- for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
- serial_table[i] = serial;
- serial->port[j++]->number = i;
- }
- mutex_unlock(&table_lock);
- return serial;
+ for (i = 0; i < num_ports; ++i) {
+ port = serial->port[i];
+ minor = idr_alloc(&serial_minors, port, 0, 0, GFP_KERNEL);
+ if (minor < 0)
+ goto error;
+ port->minor = minor;
+ port->port_number = i;
}
+ serial->minors_reserved = 1;
mutex_unlock(&table_lock);
- return NULL;
+ return 0;
+error:
+ /* unwind the already allocated minors */
+ for (j = 0; j < i; ++j)
+ idr_remove(&serial_minors, serial->port[j]->minor);
+ mutex_unlock(&table_lock);
+ return minor;
}
-static void return_serial(struct usb_serial *serial)
+static void release_minors(struct usb_serial *serial)
{
int i;
- dbg("%s", __func__);
-
mutex_lock(&table_lock);
for (i = 0; i < serial->num_ports; ++i)
- serial_table[serial->minor + i] = NULL;
+ idr_remove(&serial_minors, serial->port[i]->minor);
mutex_unlock(&table_lock);
+ serial->minors_reserved = 0;
}
static void destroy_serial(struct kref *kref)
@@ -150,13 +132,11 @@ static void destroy_serial(struct kref *kref)
serial = to_usb_serial(kref);
- dbg("%s - %s", __func__, serial->type->description);
-
/* return the minor range that this device had */
- if (serial->minor != SERIAL_TTY_NO_MINOR)
- return_serial(serial);
+ if (serial->minors_reserved)
+ release_minors(serial);
- if (serial->attached)
+ if (serial->attached && serial->type->release)
serial->type->release(serial);
/* Now that nothing is using the ports, they can be freed */
@@ -168,6 +148,7 @@ static void destroy_serial(struct kref *kref)
}
}
+ usb_put_intf(serial->interface);
usb_put_dev(serial->dev);
kfree(serial);
}
@@ -202,27 +183,22 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
struct usb_serial_port *port;
int retval = -ENODEV;
- dbg("%s", __func__);
-
- serial = usb_serial_get_by_index(idx);
- if (!serial)
+ port = usb_serial_port_get_by_minor(idx);
+ if (!port)
return retval;
- port = serial->port[idx - serial->minor];
- if (!port)
- goto error_no_port;
+ serial = port->serial;
if (!try_module_get(serial->type->driver.owner))
goto error_module_get;
- /* perform the standard setup */
- retval = tty_init_termios(tty);
- if (retval)
- goto error_init_termios;
-
retval = usb_autopm_get_interface(serial->interface);
if (retval)
goto error_get_interface;
+ retval = tty_port_install(&port->port, driver, tty);
+ if (retval)
+ goto error_init_termios;
+
mutex_unlock(&serial->disc_mutex);
/* allow the driver to update the settings */
@@ -231,23 +207,19 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
tty->driver_data = port;
- /* Final install (we use the default method) */
- tty_driver_kref_get(driver);
- tty->count++;
- driver->ttys[idx] = tty;
return retval;
- error_get_interface:
error_init_termios:
+ usb_autopm_put_interface(serial->interface);
+ error_get_interface:
module_put(serial->type->driver.owner);
error_module_get:
- error_no_port:
usb_serial_put(serial);
mutex_unlock(&serial->disc_mutex);
return retval;
}
-static int serial_activate(struct tty_port *tport, struct tty_struct *tty)
+static int serial_port_activate(struct tty_port *tport, struct tty_struct *tty)
{
struct usb_serial_port *port =
container_of(tport, struct usb_serial_port, port);
@@ -260,6 +232,10 @@ static int serial_activate(struct tty_port *tport, struct tty_struct *tty)
else
retval = port->serial->type->open(tty, port);
mutex_unlock(&serial->disc_mutex);
+
+ if (retval < 0)
+ retval = usb_translate_errors(retval);
+
return retval;
}
@@ -267,30 +243,27 @@ static int serial_open(struct tty_struct *tty, struct file *filp)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s - port %d", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
+
return tty_port_open(&port->port, tty, filp);
}
/**
- * serial_down - shut down hardware
+ * serial_port_shutdown - shut down hardware
* @tport: tty port to shut down
*
- * Shut down a USB serial port unless it is the console. We never
- * shut down the console hardware as it will always be in use. Serialized
- * against activate by the tport mutex and kept to matching open/close pairs
+ * Shut down a USB serial port. Serialized against activate by the
+ * tport mutex and kept to matching open/close pairs
* of calls by the ASYNCB_INITIALIZED flag.
+ *
+ * Not called if tty is console.
*/
-static void serial_down(struct tty_port *tport)
+static void serial_port_shutdown(struct tty_port *tport)
{
struct usb_serial_port *port =
container_of(tport, struct usb_serial_port, port);
struct usb_serial_driver *drv = port->serial->type;
- /*
- * The console is magical. Do not hang up the console hardware
- * or there will be tears.
- */
- if (port->port.console)
- return;
+
if (drv->close)
drv->close(port);
}
@@ -298,14 +271,18 @@ static void serial_down(struct tty_port *tport)
static void serial_hangup(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s - port %d", __func__, port->number);
+
+ dev_dbg(tty->dev, "%s\n", __func__);
+
tty_port_hangup(&port->port);
}
static void serial_close(struct tty_struct *tty, struct file *filp)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s - port %d", __func__, port->number);
+
+ dev_dbg(tty->dev, "%s\n", __func__);
+
tty_port_close(&port->port, tty, filp);
}
@@ -316,8 +293,7 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
* Do the resource freeing and refcount dropping for the port.
* Avoid freeing the console.
*
- * Called asynchronously after the last tty kref is dropped,
- * and the tty layer has already done the tty_shutdown(tty);
+ * Called asynchronously after the last tty kref is dropped.
*/
static void serial_cleanup(struct tty_struct *tty)
{
@@ -325,14 +301,14 @@ static void serial_cleanup(struct tty_struct *tty)
struct usb_serial *serial;
struct module *owner;
+ dev_dbg(tty->dev, "%s\n", __func__);
+
/* The console is magical. Do not hang up the console hardware
* or there will be tears.
*/
if (port->port.console)
return;
- dbg("%s - port %d", __func__, port->number);
-
tty->driver_data = NULL;
serial = port->serial;
@@ -356,11 +332,11 @@ static int serial_write(struct tty_struct *tty, const unsigned char *buf,
if (port->serial->dev->state == USB_STATE_NOTATTACHED)
goto exit;
- dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
+ dev_dbg(tty->dev, "%s - %d byte(s)\n", __func__, count);
- /* pass on to the driver specific version of this function */
retval = port->serial->type->write(tty, port, buf, count);
-
+ if (retval < 0)
+ retval = usb_translate_errors(retval);
exit:
return retval;
}
@@ -368,30 +344,47 @@ exit:
static int serial_write_room(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s - port %d", __func__, port->number);
- /* pass on to the driver specific version of this function */
+
+ dev_dbg(tty->dev, "%s\n", __func__);
+
return port->serial->type->write_room(tty);
}
static int serial_chars_in_buffer(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s - port %d", __func__, port->number);
+ struct usb_serial *serial = port->serial;
+
+ dev_dbg(tty->dev, "%s\n", __func__);
- /* if the device was unplugged then any remaining characters
- fell out of the connector ;) */
- if (port->serial->disconnected)
+ if (serial->disconnected)
return 0;
- /* pass on to the driver specific version of this function */
- return port->serial->type->chars_in_buffer(tty);
+
+ return serial->type->chars_in_buffer(tty);
+}
+
+static void serial_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct usb_serial *serial = port->serial;
+
+ dev_dbg(tty->dev, "%s\n", __func__);
+
+ if (!port->serial->type->wait_until_sent)
+ return;
+
+ mutex_lock(&serial->disc_mutex);
+ if (!serial->disconnected)
+ port->serial->type->wait_until_sent(tty, timeout);
+ mutex_unlock(&serial->disc_mutex);
}
static void serial_throttle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s - port %d", __func__, port->number);
- /* pass on to the driver specific version of this function */
+ dev_dbg(tty->dev, "%s\n", __func__);
+
if (port->serial->type->throttle)
port->serial->type->throttle(tty);
}
@@ -399,68 +392,71 @@ static void serial_throttle(struct tty_struct *tty)
static void serial_unthrottle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s - port %d", __func__, port->number);
- /* pass on to the driver specific version of this function */
+ dev_dbg(tty->dev, "%s\n", __func__);
+
if (port->serial->type->unthrottle)
port->serial->type->unthrottle(tty);
}
-static int serial_ioctl(struct tty_struct *tty, struct file *file,
+static int serial_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
- int retval = -ENODEV;
-
- dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
+ int retval = -ENOIOCTLCMD;
+
+ dev_dbg(tty->dev, "%s - cmd 0x%04x\n", __func__, cmd);
+
+ switch (cmd) {
+ case TIOCMIWAIT:
+ if (port->serial->type->tiocmiwait)
+ retval = port->serial->type->tiocmiwait(tty, arg);
+ break;
+ default:
+ if (port->serial->type->ioctl)
+ retval = port->serial->type->ioctl(tty, cmd, arg);
+ }
- /* pass on to the driver specific version of this function
- if it is available */
- if (port->serial->type->ioctl) {
- retval = port->serial->type->ioctl(tty, file, cmd, arg);
- } else
- retval = -ENOIOCTLCMD;
return retval;
}
static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s - port %d", __func__, port->number);
- /* pass on to the driver specific version of this function
- if it is available */
+ dev_dbg(tty->dev, "%s\n", __func__);
+
if (port->serial->type->set_termios)
port->serial->type->set_termios(tty, port, old);
else
- tty_termios_copy_hw(tty->termios, old);
+ tty_termios_copy_hw(&tty->termios, old);
}
static int serial_break(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s - port %d", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
- /* pass on to the driver specific version of this function
- if it is available */
if (port->serial->type->break_ctl)
port->serial->type->break_ctl(tty, break_state);
+
return 0;
}
static int serial_proc_show(struct seq_file *m, void *v)
{
struct usb_serial *serial;
+ struct usb_serial_port *port;
int i;
char tmp[40];
- dbg("%s", __func__);
seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
- for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
- serial = usb_serial_get_by_index(i);
- if (serial == NULL)
+ for (i = 0; i < USB_SERIAL_TTY_MINORS; ++i) {
+ port = usb_serial_port_get_by_minor(i);
+ if (port == NULL)
continue;
+ serial = port->serial;
seq_printf(m, "%d:", i);
if (serial->type->driver.owner)
@@ -472,7 +468,7 @@ static int serial_proc_show(struct seq_file *m, void *v)
le16_to_cpu(serial->dev->descriptor.idVendor),
le16_to_cpu(serial->dev->descriptor.idProduct));
seq_printf(m, " num_ports:%d", serial->num_ports);
- seq_printf(m, " port:%d", i - serial->minor + 1);
+ seq_printf(m, " port:%d", port->port_number);
usb_make_path(serial->dev, tmp, sizeof(tmp));
seq_printf(m, " path:%s", tmp);
@@ -496,26 +492,26 @@ static const struct file_operations serial_proc_fops = {
.release = single_release,
};
-static int serial_tiocmget(struct tty_struct *tty, struct file *file)
+static int serial_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s - port %d", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
if (port->serial->type->tiocmget)
- return port->serial->type->tiocmget(tty, file);
+ return port->serial->type->tiocmget(tty);
return -EINVAL;
}
-static int serial_tiocmset(struct tty_struct *tty, struct file *file,
+static int serial_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s - port %d", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
if (port->serial->type->tiocmset)
- return port->serial->type->tiocmset(tty, file, set, clear);
+ return port->serial->type->tiocmset(tty, set, clear);
return -EINVAL;
}
@@ -524,7 +520,7 @@ static int serial_get_icount(struct tty_struct *tty,
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s - port %d", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
if (port->serial->type->get_icount)
return port->serial->type->get_icount(tty, icount);
@@ -546,68 +542,57 @@ static void usb_serial_port_work(struct work_struct *work)
{
struct usb_serial_port *port =
container_of(work, struct usb_serial_port, work);
- struct tty_struct *tty;
- dbg("%s - port %d", __func__, port->number);
+ tty_port_tty_wakeup(&port->port);
+}
- tty = tty_port_tty_get(&port->port);
- if (!tty)
- return;
+static void usb_serial_port_poison_urbs(struct usb_serial_port *port)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
+ usb_poison_urb(port->read_urbs[i]);
+ for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
+ usb_poison_urb(port->write_urbs[i]);
- tty_wakeup(tty);
- tty_kref_put(tty);
+ usb_poison_urb(port->interrupt_in_urb);
+ usb_poison_urb(port->interrupt_out_urb);
}
-static void kill_traffic(struct usb_serial_port *port)
+static void usb_serial_port_unpoison_urbs(struct usb_serial_port *port)
{
int i;
- usb_kill_urb(port->read_urb);
- usb_kill_urb(port->write_urb);
+ for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
+ usb_unpoison_urb(port->read_urbs[i]);
for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
- usb_kill_urb(port->write_urbs[i]);
- /*
- * This is tricky.
- * Some drivers submit the read_urb in the
- * handler for the write_urb or vice versa
- * this order determines the order in which
- * usb_kill_urb() must be used to reliably
- * kill the URBs. As it is unknown here,
- * both orders must be used in turn.
- * The call below is not redundant.
- */
- usb_kill_urb(port->read_urb);
- usb_kill_urb(port->interrupt_in_urb);
- usb_kill_urb(port->interrupt_out_urb);
+ usb_unpoison_urb(port->write_urbs[i]);
+
+ usb_unpoison_urb(port->interrupt_in_urb);
+ usb_unpoison_urb(port->interrupt_out_urb);
}
-static void port_release(struct device *dev)
+static void usb_serial_port_release(struct device *dev)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
int i;
- dbg ("%s - %s", __func__, dev_name(dev));
-
- /*
- * Stop all the traffic before cancelling the work, so that
- * nobody will restart it by calling usb_serial_port_softint.
- */
- kill_traffic(port);
- cancel_work_sync(&port->work);
+ dev_dbg(dev, "%s\n", __func__);
- usb_free_urb(port->read_urb);
- usb_free_urb(port->write_urb);
usb_free_urb(port->interrupt_in_urb);
usb_free_urb(port->interrupt_out_urb);
+ for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
+ usb_free_urb(port->read_urbs[i]);
+ kfree(port->bulk_in_buffers[i]);
+ }
for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) {
usb_free_urb(port->write_urbs[i]);
kfree(port->bulk_out_buffers[i]);
}
kfifo_free(&port->write_fifo);
- kfree(port->bulk_in_buffer);
- kfree(port->bulk_out_buffer);
kfree(port->interrupt_in_buffer);
kfree(port->interrupt_out_buffer);
+ tty_port_destroy(&port->port);
kfree(port);
}
@@ -618,16 +603,14 @@ static struct usb_serial *create_serial(struct usb_device *dev,
struct usb_serial *serial;
serial = kzalloc(sizeof(*serial), GFP_KERNEL);
- if (!serial) {
- dev_err(&dev->dev, "%s - out of memory\n", __func__);
+ if (!serial)
return NULL;
- }
serial->dev = usb_get_dev(dev);
serial->type = driver;
- serial->interface = interface;
+ serial->interface = usb_get_intf(interface);
kref_init(&serial->kref);
mutex_init(&serial->disc_mutex);
- serial->minor = SERIAL_TTY_NO_MINOR;
+ serial->minors_reserved = 0;
return serial;
}
@@ -655,12 +638,12 @@ static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
id = usb_match_id(intf, drv->id_table);
if (id) {
- dbg("static descriptor matches");
+ dev_dbg(&intf->dev, "static descriptor matches\n");
goto exit;
}
id = match_dynamic_id(intf, drv);
if (id)
- dbg("dynamic descriptor matches");
+ dev_dbg(&intf->dev, "dynamic descriptor matches\n");
exit:
return id;
}
@@ -669,12 +652,14 @@ exit:
static struct usb_serial_driver *search_serial_device(
struct usb_interface *iface)
{
- const struct usb_device_id *id;
+ const struct usb_device_id *id = NULL;
struct usb_serial_driver *drv;
+ struct usb_driver *driver = to_usb_driver(iface->dev.driver);
/* Check if the usb id matches a known device */
list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
- id = get_iface_id(drv, iface);
+ if (drv->usb_driver == driver)
+ id = get_iface_id(drv, iface);
if (id)
return drv;
}
@@ -682,34 +667,37 @@ static struct usb_serial_driver *search_serial_device(
return NULL;
}
-static int serial_carrier_raised(struct tty_port *port)
+static int serial_port_carrier_raised(struct tty_port *port)
{
struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
struct usb_serial_driver *drv = p->serial->type;
+
if (drv->carrier_raised)
return drv->carrier_raised(p);
/* No carrier control - don't block */
- return 1;
+ return 1;
}
-static void serial_dtr_rts(struct tty_port *port, int on)
+static void serial_port_dtr_rts(struct tty_port *port, int on)
{
struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
struct usb_serial_driver *drv = p->serial->type;
+
if (drv->dtr_rts)
drv->dtr_rts(p, on);
}
static const struct tty_port_operations serial_port_ops = {
- .carrier_raised = serial_carrier_raised,
- .dtr_rts = serial_dtr_rts,
- .activate = serial_activate,
- .shutdown = serial_down,
+ .carrier_raised = serial_port_carrier_raised,
+ .dtr_rts = serial_port_dtr_rts,
+ .activate = serial_port_activate,
+ .shutdown = serial_port_shutdown,
};
-int usb_serial_probe(struct usb_interface *interface,
+static int usb_serial_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
+ struct device *ddev = &interface->dev;
struct usb_device *dev = interface_to_usbdev(interface);
struct usb_serial *serial = NULL;
struct usb_serial_port *port;
@@ -721,9 +709,9 @@ int usb_serial_probe(struct usb_interface *interface,
struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
struct usb_serial_driver *type = NULL;
int retval;
- unsigned int minor;
int buffer_size;
int i;
+ int j;
int num_interrupt_in = 0;
int num_interrupt_out = 0;
int num_bulk_in = 0;
@@ -735,13 +723,13 @@ int usb_serial_probe(struct usb_interface *interface,
type = search_serial_device(interface);
if (!type) {
mutex_unlock(&table_lock);
- dbg("none matched");
+ dev_dbg(ddev, "none matched\n");
return -ENODEV;
}
if (!try_module_get(type->driver.owner)) {
mutex_unlock(&table_lock);
- dev_err(&interface->dev, "module get failed, exiting\n");
+ dev_err(ddev, "module get failed, exiting\n");
return -EIO;
}
mutex_unlock(&table_lock);
@@ -749,7 +737,6 @@ int usb_serial_probe(struct usb_interface *interface,
serial = create_serial(dev, interface, type);
if (!serial) {
module_put(type->driver.owner);
- dev_err(&interface->dev, "%s - out of memory\n", __func__);
return -ENOMEM;
}
@@ -761,8 +748,8 @@ int usb_serial_probe(struct usb_interface *interface,
retval = type->probe(serial, id);
if (retval) {
- dbg("sub driver rejected device");
- kfree(serial);
+ dev_dbg(ddev, "sub driver rejected device\n");
+ usb_serial_put(serial);
module_put(type->driver.owner);
return retval;
}
@@ -776,28 +763,28 @@ int usb_serial_probe(struct usb_interface *interface,
if (usb_endpoint_is_bulk_in(endpoint)) {
/* we found a bulk in endpoint */
- dbg("found bulk in on endpoint %d", i);
+ dev_dbg(ddev, "found bulk in on endpoint %d\n", i);
bulk_in_endpoint[num_bulk_in] = endpoint;
++num_bulk_in;
}
if (usb_endpoint_is_bulk_out(endpoint)) {
/* we found a bulk out endpoint */
- dbg("found bulk out on endpoint %d", i);
+ dev_dbg(ddev, "found bulk out on endpoint %d\n", i);
bulk_out_endpoint[num_bulk_out] = endpoint;
++num_bulk_out;
}
if (usb_endpoint_is_int_in(endpoint)) {
/* we found a interrupt in endpoint */
- dbg("found interrupt in on endpoint %d", i);
+ dev_dbg(ddev, "found interrupt in on endpoint %d\n", i);
interrupt_in_endpoint[num_interrupt_in] = endpoint;
++num_interrupt_in;
}
if (usb_endpoint_is_int_out(endpoint)) {
/* we found an interrupt out endpoint */
- dbg("found interrupt out on endpoint %d", i);
+ dev_dbg(ddev, "found interrupt out on endpoint %d\n", i);
interrupt_out_endpoint[num_interrupt_out] = endpoint;
++num_interrupt_out;
}
@@ -821,7 +808,7 @@ int usb_serial_probe(struct usb_interface *interface,
endpoint = &iface_desc->endpoint[i].desc;
if (usb_endpoint_is_int_in(endpoint)) {
/* we found a interrupt in endpoint */
- dbg("found interrupt in for Prolific device on separate interface");
+ dev_dbg(ddev, "found interrupt in for Prolific device on separate interface\n");
interrupt_in_endpoint[num_interrupt_in] = endpoint;
++num_interrupt_in;
}
@@ -833,8 +820,8 @@ int usb_serial_probe(struct usb_interface *interface,
* properly during a later invocation of usb_serial_probe
*/
if (num_bulk_in == 0 || num_bulk_out == 0) {
- dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
- kfree(serial);
+ dev_info(ddev, "PL-2303 hack: descriptors matched but endpoints did not\n");
+ usb_serial_put(serial);
module_put(type->driver.owner);
return -ENODEV;
}
@@ -846,12 +833,13 @@ int usb_serial_probe(struct usb_interface *interface,
if (type == &usb_serial_generic_device) {
num_ports = num_bulk_out;
if (num_ports == 0) {
- dev_err(&interface->dev,
- "Generic device with no bulk out, not allowed.\n");
- kfree(serial);
+ dev_err(ddev, "Generic device with no bulk out, not allowed.\n");
+ usb_serial_put(serial);
module_put(type->driver.owner);
return -EIO;
}
+ dev_info(ddev, "The \"generic\" usb-serial driver is only for testing and one-off prototypes.\n");
+ dev_info(ddev, "Tell linux-usb@vger.kernel.org to add your device to a proper driver.\n");
}
#endif
if (!num_ports) {
@@ -869,8 +857,7 @@ int usb_serial_probe(struct usb_interface *interface,
serial->num_interrupt_out = num_interrupt_out;
/* found all that we need */
- dev_info(&interface->dev, "%s converter detected\n",
- type->description);
+ dev_info(ddev, "%s converter detected\n", type->description);
/* create our ports, we need as many as the max endpoints */
/* we don't use num_ports here because some devices have more
@@ -881,8 +868,7 @@ int usb_serial_probe(struct usb_interface *interface,
max_endpoints = max(max_endpoints, (int)serial->num_ports);
serial->num_port_pointers = max_endpoints;
- dbg("%s - setting up %d port structures for this device",
- __func__, max_endpoints);
+ dev_dbg(ddev, "setting up %d port structure(s)\n", max_endpoints);
for (i = 0; i < max_endpoints; ++i) {
port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
if (!port)
@@ -898,7 +884,7 @@ int usb_serial_probe(struct usb_interface *interface,
port->dev.parent = &interface->dev;
port->dev.driver = NULL;
port->dev.bus = &usb_serial_bus_type;
- port->dev.release = &port_release;
+ port->dev.release = &usb_serial_port_release;
device_initialize(&port->dev);
}
@@ -906,72 +892,51 @@ int usb_serial_probe(struct usb_interface *interface,
for (i = 0; i < num_bulk_in; ++i) {
endpoint = bulk_in_endpoint[i];
port = serial->port[i];
- port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->read_urb) {
- dev_err(&interface->dev, "No free urbs available\n");
- goto probe_error;
- }
- buffer_size = serial->type->bulk_in_size;
- if (!buffer_size)
- buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+ buffer_size = max_t(int, serial->type->bulk_in_size,
+ usb_endpoint_maxp(endpoint));
port->bulk_in_size = buffer_size;
port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
- port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
- if (!port->bulk_in_buffer) {
- dev_err(&interface->dev,
- "Couldn't allocate bulk_in_buffer\n");
- goto probe_error;
- }
- usb_fill_bulk_urb(port->read_urb, dev,
- usb_rcvbulkpipe(dev,
+
+ for (j = 0; j < ARRAY_SIZE(port->read_urbs); ++j) {
+ set_bit(j, &port->read_urbs_free);
+ port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
+ if (!port->read_urbs[j])
+ goto probe_error;
+ port->bulk_in_buffers[j] = kmalloc(buffer_size,
+ GFP_KERNEL);
+ if (!port->bulk_in_buffers[j])
+ goto probe_error;
+ usb_fill_bulk_urb(port->read_urbs[j], dev,
+ usb_rcvbulkpipe(dev,
endpoint->bEndpointAddress),
- port->bulk_in_buffer, buffer_size,
- serial->type->read_bulk_callback, port);
+ port->bulk_in_buffers[j], buffer_size,
+ serial->type->read_bulk_callback,
+ port);
+ }
+
+ port->read_urb = port->read_urbs[0];
+ port->bulk_in_buffer = port->bulk_in_buffers[0];
}
for (i = 0; i < num_bulk_out; ++i) {
- int j;
-
endpoint = bulk_out_endpoint[i];
port = serial->port[i];
- port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->write_urb) {
- dev_err(&interface->dev, "No free urbs available\n");
- goto probe_error;
- }
if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
goto probe_error;
- buffer_size = serial->type->bulk_out_size;
- if (!buffer_size)
- buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+ buffer_size = max_t(int, serial->type->bulk_out_size,
+ usb_endpoint_maxp(endpoint));
port->bulk_out_size = buffer_size;
port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
- port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
- if (!port->bulk_out_buffer) {
- dev_err(&interface->dev,
- "Couldn't allocate bulk_out_buffer\n");
- goto probe_error;
- }
- usb_fill_bulk_urb(port->write_urb, dev,
- usb_sndbulkpipe(dev,
- endpoint->bEndpointAddress),
- port->bulk_out_buffer, buffer_size,
- serial->type->write_bulk_callback, port);
+
for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
set_bit(j, &port->write_urbs_free);
port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->write_urbs[j]) {
- dev_err(&interface->dev,
- "No free urbs available\n");
+ if (!port->write_urbs[j])
goto probe_error;
- }
port->bulk_out_buffers[j] = kmalloc(buffer_size,
GFP_KERNEL);
- if (!port->bulk_out_buffers[j]) {
- dev_err(&interface->dev,
- "Couldn't allocate bulk_out_buffer\n");
+ if (!port->bulk_out_buffers[j])
goto probe_error;
- }
usb_fill_bulk_urb(port->write_urbs[j], dev,
usb_sndbulkpipe(dev,
endpoint->bEndpointAddress),
@@ -979,6 +944,9 @@ int usb_serial_probe(struct usb_interface *interface,
serial->type->write_bulk_callback,
port);
}
+
+ port->write_urb = port->write_urbs[0];
+ port->bulk_out_buffer = port->bulk_out_buffers[0];
}
if (serial->type->read_int_callback) {
@@ -986,21 +954,15 @@ int usb_serial_probe(struct usb_interface *interface,
endpoint = interrupt_in_endpoint[i];
port = serial->port[i];
port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->interrupt_in_urb) {
- dev_err(&interface->dev,
- "No free urbs available\n");
+ if (!port->interrupt_in_urb)
goto probe_error;
- }
- buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+ buffer_size = usb_endpoint_maxp(endpoint);
port->interrupt_in_endpointAddress =
endpoint->bEndpointAddress;
port->interrupt_in_buffer = kmalloc(buffer_size,
GFP_KERNEL);
- if (!port->interrupt_in_buffer) {
- dev_err(&interface->dev,
- "Couldn't allocate interrupt_in_buffer\n");
+ if (!port->interrupt_in_buffer)
goto probe_error;
- }
usb_fill_int_urb(port->interrupt_in_urb, dev,
usb_rcvintpipe(dev,
endpoint->bEndpointAddress),
@@ -1009,7 +971,7 @@ int usb_serial_probe(struct usb_interface *interface,
endpoint->bInterval);
}
} else if (num_interrupt_in) {
- dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
+ dev_dbg(ddev, "The device claims to support interrupt in transfers, but read_int_callback is not defined\n");
}
if (serial->type->write_int_callback) {
@@ -1017,22 +979,16 @@ int usb_serial_probe(struct usb_interface *interface,
endpoint = interrupt_out_endpoint[i];
port = serial->port[i];
port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->interrupt_out_urb) {
- dev_err(&interface->dev,
- "No free urbs available\n");
+ if (!port->interrupt_out_urb)
goto probe_error;
- }
- buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+ buffer_size = usb_endpoint_maxp(endpoint);
port->interrupt_out_size = buffer_size;
port->interrupt_out_endpointAddress =
endpoint->bEndpointAddress;
port->interrupt_out_buffer = kmalloc(buffer_size,
GFP_KERNEL);
- if (!port->interrupt_out_buffer) {
- dev_err(&interface->dev,
- "Couldn't allocate interrupt_out_buffer\n");
+ if (!port->interrupt_out_buffer)
goto probe_error;
- }
usb_fill_int_urb(port->interrupt_out_urb, dev,
usb_sndintpipe(dev,
endpoint->bEndpointAddress),
@@ -1041,9 +997,11 @@ int usb_serial_probe(struct usb_interface *interface,
endpoint->bInterval);
}
} else if (num_interrupt_out) {
- dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
+ dev_dbg(ddev, "The device claims to support interrupt out transfers, but write_int_callback is not defined\n");
}
+ usb_set_intfdata(interface, serial);
+
/* if this device type has an attach function, call it */
if (type->attach) {
retval = type->attach(serial);
@@ -1060,35 +1018,33 @@ int usb_serial_probe(struct usb_interface *interface,
serial->attached = 1;
}
- if (get_free_serial(serial, num_ports, &minor) == NULL) {
- dev_err(&interface->dev, "No more free serial devices\n");
+ /* Avoid race with tty_open and serial_install by setting the
+ * disconnected flag and not clearing it until all ports have been
+ * registered.
+ */
+ serial->disconnected = 1;
+
+ if (allocate_minors(serial, num_ports)) {
+ dev_err(ddev, "No more free serial minor numbers\n");
goto probe_error;
}
- serial->minor = minor;
/* register all of the individual ports with the driver core */
for (i = 0; i < num_ports; ++i) {
port = serial->port[i];
- dev_set_name(&port->dev, "ttyUSB%d", port->number);
- dbg ("%s - registering %s", __func__, dev_name(&port->dev));
- port->dev_state = PORT_REGISTERING;
+ dev_set_name(&port->dev, "ttyUSB%d", port->minor);
+ dev_dbg(ddev, "registering %s\n", dev_name(&port->dev));
device_enable_async_suspend(&port->dev);
retval = device_add(&port->dev);
- if (retval) {
- dev_err(&port->dev, "Error registering port device, "
- "continuing\n");
- port->dev_state = PORT_UNREGISTERED;
- } else {
- port->dev_state = PORT_REGISTERED;
- }
+ if (retval)
+ dev_err(ddev, "Error registering port device, continuing\n");
}
- usb_serial_console_init(debug, minor);
+ serial->disconnected = 0;
+ usb_serial_console_init(serial->port[0]->minor);
exit:
- /* success */
- usb_set_intfdata(interface, serial);
module_put(type->driver.owner);
return 0;
@@ -1097,68 +1053,55 @@ probe_error:
module_put(type->driver.owner);
return -EIO;
}
-EXPORT_SYMBOL_GPL(usb_serial_probe);
-void usb_serial_disconnect(struct usb_interface *interface)
+static void usb_serial_disconnect(struct usb_interface *interface)
{
int i;
struct usb_serial *serial = usb_get_intfdata(interface);
struct device *dev = &interface->dev;
struct usb_serial_port *port;
+ struct tty_struct *tty;
usb_serial_console_disconnect(serial);
- dbg("%s", __func__);
mutex_lock(&serial->disc_mutex);
- usb_set_intfdata(interface, NULL);
/* must set a flag, to signal subdrivers */
serial->disconnected = 1;
mutex_unlock(&serial->disc_mutex);
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
- if (port) {
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- if (tty) {
- tty_vhangup(tty);
- tty_kref_put(tty);
- }
- kill_traffic(port);
- cancel_work_sync(&port->work);
- if (port->dev_state == PORT_REGISTERED) {
-
- /* Make sure the port is bound so that the
- * driver's port_remove method is called.
- */
- if (!port->dev.driver) {
- int rc;
-
- port->dev.driver =
- &serial->type->driver;
- rc = device_bind_driver(&port->dev);
- }
- port->dev_state = PORT_UNREGISTERING;
- device_del(&port->dev);
- port->dev_state = PORT_UNREGISTERED;
- }
+ tty = tty_port_tty_get(&port->port);
+ if (tty) {
+ tty_vhangup(tty);
+ tty_kref_put(tty);
}
+ usb_serial_port_poison_urbs(port);
+ wake_up_interruptible(&port->port.delta_msr_wait);
+ cancel_work_sync(&port->work);
+ if (device_is_registered(&port->dev))
+ device_del(&port->dev);
}
- serial->type->disconnect(serial);
+ if (serial->type->disconnect)
+ serial->type->disconnect(serial);
/* let the last holder of this object cause it to be cleaned up */
usb_serial_put(serial);
dev_info(dev, "device disconnected\n");
}
-EXPORT_SYMBOL_GPL(usb_serial_disconnect);
int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usb_serial *serial = usb_get_intfdata(intf);
- struct usb_serial_port *port;
int i, r = 0;
serial->suspending = 1;
+ /*
+ * serial->type->suspend() MUST return 0 in system sleep context,
+ * otherwise, the resume callback has to recover device from
+ * previous suspend failure.
+ */
if (serial->type->suspend) {
r = serial->type->suspend(serial, message);
if (r < 0) {
@@ -1167,22 +1110,28 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
}
}
- for (i = 0; i < serial->num_ports; ++i) {
- port = serial->port[i];
- if (port)
- kill_traffic(port);
- }
-
+ for (i = 0; i < serial->num_ports; ++i)
+ usb_serial_port_poison_urbs(serial->port[i]);
err_out:
return r;
}
EXPORT_SYMBOL(usb_serial_suspend);
+static void usb_serial_unpoison_port_urbs(struct usb_serial *serial)
+{
+ int i;
+
+ for (i = 0; i < serial->num_ports; ++i)
+ usb_serial_port_unpoison_urbs(serial->port[i]);
+}
+
int usb_serial_resume(struct usb_interface *intf)
{
struct usb_serial *serial = usb_get_intfdata(intf);
int rv;
+ usb_serial_unpoison_port_urbs(serial);
+
serial->suspending = 0;
if (serial->type->resume)
rv = serial->type->resume(serial);
@@ -1193,11 +1142,29 @@ int usb_serial_resume(struct usb_interface *intf)
}
EXPORT_SYMBOL(usb_serial_resume);
+static int usb_serial_reset_resume(struct usb_interface *intf)
+{
+ struct usb_serial *serial = usb_get_intfdata(intf);
+ int rv;
+
+ usb_serial_unpoison_port_urbs(serial);
+
+ serial->suspending = 0;
+ if (serial->type->reset_resume) {
+ rv = serial->type->reset_resume(serial);
+ } else {
+ rv = -EOPNOTSUPP;
+ intf->needs_binding = 1;
+ }
+
+ return rv;
+}
+
static const struct tty_operations serial_ops = {
.open = serial_open,
.close = serial_close,
.write = serial_write,
- .hangup = serial_hangup,
+ .hangup = serial_hangup,
.write_room = serial_write_room,
.ioctl = serial_ioctl,
.set_termios = serial_set_termios,
@@ -1205,41 +1172,47 @@ static const struct tty_operations serial_ops = {
.unthrottle = serial_unthrottle,
.break_ctl = serial_break,
.chars_in_buffer = serial_chars_in_buffer,
+ .wait_until_sent = serial_wait_until_sent,
.tiocmget = serial_tiocmget,
.tiocmset = serial_tiocmset,
- .get_icount = serial_get_icount,
- .cleanup = serial_cleanup,
- .install = serial_install,
+ .get_icount = serial_get_icount,
+ .cleanup = serial_cleanup,
+ .install = serial_install,
.proc_fops = &serial_proc_fops,
};
struct tty_driver *usb_serial_tty_driver;
+/* Driver structure we register with the USB core */
+static struct usb_driver usb_serial_driver = {
+ .name = "usbserial",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .suspend = usb_serial_suspend,
+ .resume = usb_serial_resume,
+ .no_dynamic_id = 1,
+ .supports_autosuspend = 1,
+};
+
static int __init usb_serial_init(void)
{
- int i;
int result;
- usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
+ usb_serial_tty_driver = alloc_tty_driver(USB_SERIAL_TTY_MINORS);
if (!usb_serial_tty_driver)
return -ENOMEM;
/* Initialize our global data */
- for (i = 0; i < SERIAL_TTY_MINORS; ++i)
- serial_table[i] = NULL;
-
result = bus_register(&usb_serial_bus_type);
if (result) {
- printk(KERN_ERR "usb-serial: %s - registering bus driver "
- "failed\n", __func__);
+ pr_err("%s - registering bus driver failed\n", __func__);
goto exit_bus;
}
- usb_serial_tty_driver->owner = THIS_MODULE;
usb_serial_tty_driver->driver_name = "usbserial";
- usb_serial_tty_driver->name = "ttyUSB";
- usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
+ usb_serial_tty_driver->name = "ttyUSB";
+ usb_serial_tty_driver->major = USB_SERIAL_TTY_MAJOR;
usb_serial_tty_driver->minor_start = 0;
usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
@@ -1253,29 +1226,24 @@ static int __init usb_serial_init(void)
tty_set_operations(usb_serial_tty_driver, &serial_ops);
result = tty_register_driver(usb_serial_tty_driver);
if (result) {
- printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
- __func__);
+ pr_err("%s - tty_register_driver failed\n", __func__);
goto exit_reg_driver;
}
/* register the USB driver */
result = usb_register(&usb_serial_driver);
if (result < 0) {
- printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
- __func__);
+ pr_err("%s - usb_register failed\n", __func__);
goto exit_tty;
}
/* register the generic driver, if we should */
- result = usb_serial_generic_register(debug);
+ result = usb_serial_generic_register();
if (result < 0) {
- printk(KERN_ERR "usb-serial: %s - registering generic "
- "driver failed\n", __func__);
+ pr_err("%s - registering generic driver failed\n", __func__);
goto exit_generic;
}
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
-
return result;
exit_generic:
@@ -1288,8 +1256,7 @@ exit_reg_driver:
bus_unregister(&usb_serial_bus_type);
exit_bus:
- printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
- __func__, result);
+ pr_err("%s - returning with error %d\n", __func__, result);
put_tty_driver(usb_serial_tty_driver);
return result;
}
@@ -1315,38 +1282,42 @@ module_exit(usb_serial_exit);
do { \
if (!type->function) { \
type->function = usb_serial_generic_##function; \
- dbg("Had to override the " #function \
- " usb serial operation with the generic one.");\
- } \
+ pr_debug("%s: using generic " #function "\n", \
+ type->driver.name); \
+ } \
} while (0)
-static void fixup_generic(struct usb_serial_driver *device)
+static void usb_serial_operations_init(struct usb_serial_driver *device)
{
set_to_generic_if_null(device, open);
set_to_generic_if_null(device, write);
set_to_generic_if_null(device, close);
set_to_generic_if_null(device, write_room);
set_to_generic_if_null(device, chars_in_buffer);
+ if (device->tx_empty)
+ set_to_generic_if_null(device, wait_until_sent);
set_to_generic_if_null(device, read_bulk_callback);
set_to_generic_if_null(device, write_bulk_callback);
- set_to_generic_if_null(device, disconnect);
- set_to_generic_if_null(device, release);
set_to_generic_if_null(device, process_read_urb);
set_to_generic_if_null(device, prepare_write_buffer);
}
-int usb_serial_register(struct usb_serial_driver *driver)
+static int usb_serial_register(struct usb_serial_driver *driver)
{
- /* must be called with BKL held */
int retval;
if (usb_disabled())
return -ENODEV;
- fixup_generic(driver);
-
if (!driver->description)
driver->description = driver->driver.name;
+ if (!driver->usb_driver) {
+ WARN(1, "Serial driver %s has no usb_driver\n",
+ driver->description);
+ return -EINVAL;
+ }
+
+ usb_serial_operations_init(driver);
/* Add this device to our list of devices */
mutex_lock(&table_lock);
@@ -1354,35 +1325,119 @@ int usb_serial_register(struct usb_serial_driver *driver)
retval = usb_serial_bus_register(driver);
if (retval) {
- printk(KERN_ERR "usb-serial: problem %d when registering "
- "driver %s\n", retval, driver->description);
+ pr_err("problem %d when registering driver %s\n", retval, driver->description);
list_del(&driver->driver_list);
- } else
- printk(KERN_INFO "USB Serial support registered for %s\n",
- driver->description);
-
+ } else {
+ pr_info("USB Serial support registered for %s\n", driver->description);
+ }
mutex_unlock(&table_lock);
return retval;
}
-EXPORT_SYMBOL_GPL(usb_serial_register);
-
-void usb_serial_deregister(struct usb_serial_driver *device)
+static void usb_serial_deregister(struct usb_serial_driver *device)
{
- /* must be called with BKL held */
- printk(KERN_INFO "USB Serial deregistering driver %s\n",
- device->description);
+ pr_info("USB Serial deregistering driver %s\n", device->description);
+
mutex_lock(&table_lock);
list_del(&device->driver_list);
- usb_serial_bus_deregister(device);
mutex_unlock(&table_lock);
+
+ usb_serial_bus_deregister(device);
+}
+
+/**
+ * usb_serial_register_drivers - register drivers for a usb-serial module
+ * @serial_drivers: NULL-terminated array of pointers to drivers to be registered
+ * @name: name of the usb_driver for this set of @serial_drivers
+ * @id_table: list of all devices this @serial_drivers set binds to
+ *
+ * Registers all the drivers in the @serial_drivers array, and dynamically
+ * creates a struct usb_driver with the name @name and id_table of @id_table.
+ */
+int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[],
+ const char *name,
+ const struct usb_device_id *id_table)
+{
+ int rc;
+ struct usb_driver *udriver;
+ struct usb_serial_driver * const *sd;
+
+ /*
+ * udriver must be registered before any of the serial drivers,
+ * because the store_new_id() routine for the serial drivers (in
+ * bus.c) probes udriver.
+ *
+ * Performance hack: We don't want udriver to be probed until
+ * the serial drivers are registered, because the probe would
+ * simply fail for lack of a matching serial driver.
+ * So we leave udriver's id_table set to NULL until we are all set.
+ *
+ * Suspend/resume support is implemented in the usb-serial core,
+ * so fill in the PM-related fields in udriver.
+ */
+ udriver = kzalloc(sizeof(*udriver), GFP_KERNEL);
+ if (!udriver)
+ return -ENOMEM;
+
+ udriver->name = name;
+ udriver->no_dynamic_id = 1;
+ udriver->supports_autosuspend = 1;
+ udriver->suspend = usb_serial_suspend;
+ udriver->resume = usb_serial_resume;
+ udriver->probe = usb_serial_probe;
+ udriver->disconnect = usb_serial_disconnect;
+
+ /* we only set the reset_resume field if the serial_driver has one */
+ for (sd = serial_drivers; *sd; ++sd) {
+ if ((*sd)->reset_resume) {
+ udriver->reset_resume = usb_serial_reset_resume;
+ break;
+ }
+ }
+
+ rc = usb_register(udriver);
+ if (rc)
+ return rc;
+
+ for (sd = serial_drivers; *sd; ++sd) {
+ (*sd)->usb_driver = udriver;
+ rc = usb_serial_register(*sd);
+ if (rc)
+ goto failed;
+ }
+
+ /* Now set udriver's id_table and look for matches */
+ udriver->id_table = id_table;
+ rc = driver_attach(&udriver->drvwrap.driver);
+ return 0;
+
+ failed:
+ while (sd-- > serial_drivers)
+ usb_serial_deregister(*sd);
+ usb_deregister(udriver);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(usb_serial_register_drivers);
+
+/**
+ * usb_serial_deregister_drivers - deregister drivers for a usb-serial module
+ * @serial_drivers: NULL-terminated array of pointers to drivers to be deregistered
+ *
+ * Deregisters all the drivers in the @serial_drivers array and deregisters and
+ * frees the struct usb_driver that was created by the call to
+ * usb_serial_register_drivers().
+ */
+void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_drivers[])
+{
+ struct usb_driver *udriver = (*serial_drivers)->usb_driver;
+
+ for (; *serial_drivers; ++serial_drivers)
+ usb_serial_deregister(*serial_drivers);
+ usb_deregister(udriver);
+ kfree(udriver);
}
-EXPORT_SYMBOL_GPL(usb_serial_deregister);
+EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers);
-/* Module information */
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h
index 2be298a1305..f22dff58b58 100644
--- a/drivers/usb/serial/usb-wwan.h
+++ b/drivers/usb/serial/usb-wwan.h
@@ -8,17 +8,14 @@
extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on);
extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port);
extern void usb_wwan_close(struct usb_serial_port *port);
-extern int usb_wwan_startup(struct usb_serial *serial);
-extern void usb_wwan_disconnect(struct usb_serial *serial);
-extern void usb_wwan_release(struct usb_serial *serial);
+extern int usb_wwan_port_probe(struct usb_serial_port *port);
+extern int usb_wwan_port_remove(struct usb_serial_port *port);
extern int usb_wwan_write_room(struct tty_struct *tty);
-extern void usb_wwan_set_termios(struct tty_struct *tty,
- struct usb_serial_port *port,
- struct ktermios *old);
-extern int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file);
-extern int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
+extern int usb_wwan_tiocmget(struct tty_struct *tty);
+extern int usb_wwan_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
-extern int usb_wwan_send_setup(struct usb_serial_port *port);
+extern int usb_wwan_ioctl(struct tty_struct *tty,
+ unsigned int cmd, unsigned long arg);
extern int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
extern int usb_wwan_chars_in_buffer(struct tty_struct *tty);
@@ -38,6 +35,7 @@ struct usb_wwan_intf_private {
spinlock_t susp_lock;
unsigned int suspended:1;
int in_flight;
+ unsigned int open_ports;
int (*send_setup) (struct usb_serial_port *port);
void *private;
};
@@ -50,7 +48,6 @@ struct usb_wwan_port_private {
struct urb *out_urbs[N_OUT_URB];
u8 *out_buffer[N_OUT_URB];
unsigned long out_busy; /* Bit vector of URBs in use */
- int opened;
struct usb_anchor delayed;
/* Settings for the port */
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
index f2ed6a31be7..ca2fa5bbe17 100644
--- a/drivers/usb/serial/usb_debug.c
+++ b/drivers/usb/serial/usb_debug.c
@@ -10,7 +10,6 @@
#include <linux/gfp.h>
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/usb.h>
@@ -35,14 +34,6 @@ static const struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver debug_driver = {
- .name = "debug",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
/* This HW really does not support a serial break, so one will be
* emulated when ever the break state is set to true.
*/
@@ -54,19 +45,18 @@ static void usb_debug_break_ctl(struct tty_struct *tty, int break_state)
usb_serial_generic_write(tty, port, USB_DEBUG_BRK, USB_DEBUG_BRK_SIZE);
}
-static void usb_debug_read_bulk_callback(struct urb *urb)
+static void usb_debug_process_read_urb(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
if (urb->actual_length == USB_DEBUG_BRK_SIZE &&
- memcmp(urb->transfer_buffer, USB_DEBUG_BRK,
- USB_DEBUG_BRK_SIZE) == 0) {
+ memcmp(urb->transfer_buffer, USB_DEBUG_BRK,
+ USB_DEBUG_BRK_SIZE) == 0) {
usb_serial_handle_break(port);
- usb_serial_generic_submit_read_urb(port, GFP_ATOMIC);
return;
}
- usb_serial_generic_read_bulk_callback(urb);
+ usb_serial_generic_process_read_urb(urb);
}
static struct usb_serial_driver debug_device = {
@@ -78,28 +68,12 @@ static struct usb_serial_driver debug_device = {
.num_ports = 1,
.bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE,
.break_ctl = usb_debug_break_ctl,
- .read_bulk_callback = usb_debug_read_bulk_callback,
+ .process_read_urb = usb_debug_process_read_urb,
};
-static int __init debug_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&debug_device);
- if (retval)
- return retval;
- retval = usb_register(&debug_driver);
- if (retval)
- usb_serial_deregister(&debug_device);
- return retval;
-}
-
-static void __exit debug_exit(void)
-{
- usb_deregister(&debug_driver);
- usb_serial_deregister(&debug_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &debug_device, NULL
+};
-module_init(debug_init);
-module_exit(debug_exit);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index fbc94679780..2f805cb386a 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -19,7 +19,6 @@
- controlling the baud rate doesn't make sense
*/
-#define DRIVER_VERSION "v0.7.2"
#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
#define DRIVER_DESC "USB Driver for GSM modems"
@@ -31,53 +30,32 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/bitops.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
+#include <linux/serial.h>
#include "usb-wwan.h"
-static int debug;
-
void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
{
- struct usb_serial *serial = port->serial;
struct usb_wwan_port_private *portdata;
-
struct usb_wwan_intf_private *intfdata;
- dbg("%s", __func__);
-
- intfdata = port->serial->private;
+ intfdata = usb_get_serial_data(port->serial);
if (!intfdata->send_setup)
return;
portdata = usb_get_serial_port_data(port);
- mutex_lock(&serial->disc_mutex);
+ /* FIXME: locking */
portdata->rts_state = on;
portdata->dtr_state = on;
- if (serial->dev)
- intfdata->send_setup(port);
- mutex_unlock(&serial->disc_mutex);
-}
-EXPORT_SYMBOL(usb_wwan_dtr_rts);
-void usb_wwan_set_termios(struct tty_struct *tty,
- struct usb_serial_port *port,
- struct ktermios *old_termios)
-{
- struct usb_wwan_intf_private *intfdata = port->serial->private;
-
- dbg("%s", __func__);
-
- /* Doesn't support option setting */
- tty_termios_copy_hw(tty->termios, old_termios);
-
- if (intfdata->send_setup)
- intfdata->send_setup(port);
+ intfdata->send_setup(port);
}
-EXPORT_SYMBOL(usb_wwan_set_termios);
+EXPORT_SYMBOL(usb_wwan_dtr_rts);
-int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file)
+int usb_wwan_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
unsigned int value;
@@ -96,7 +74,7 @@ int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file)
}
EXPORT_SYMBOL(usb_wwan_tiocmget);
-int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
+int usb_wwan_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
@@ -104,7 +82,7 @@ int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
struct usb_wwan_intf_private *intfdata;
portdata = usb_get_serial_port_data(port);
- intfdata = port->serial->private;
+ intfdata = usb_get_serial_data(port->serial);
if (!intfdata->send_setup)
return -EINVAL;
@@ -123,7 +101,83 @@ int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
}
EXPORT_SYMBOL(usb_wwan_tiocmset);
-/* Write */
+static int get_serial_info(struct usb_serial_port *port,
+ struct serial_struct __user *retinfo)
+{
+ struct serial_struct tmp;
+
+ if (!retinfo)
+ return -EFAULT;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.line = port->minor;
+ tmp.port = port->port_number;
+ tmp.baud_base = tty_get_baud_rate(port->port.tty);
+ tmp.close_delay = port->port.close_delay / 10;
+ tmp.closing_wait = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+ ASYNC_CLOSING_WAIT_NONE :
+ port->port.closing_wait / 10;
+
+ if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+ return -EFAULT;
+ return 0;
+}
+
+static int set_serial_info(struct usb_serial_port *port,
+ struct serial_struct __user *newinfo)
+{
+ struct serial_struct new_serial;
+ unsigned int closing_wait, close_delay;
+ int retval = 0;
+
+ if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
+ return -EFAULT;
+
+ close_delay = new_serial.close_delay * 10;
+ closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+ ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
+
+ mutex_lock(&port->port.mutex);
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ if ((close_delay != port->port.close_delay) ||
+ (closing_wait != port->port.closing_wait))
+ retval = -EPERM;
+ else
+ retval = -EOPNOTSUPP;
+ } else {
+ port->port.close_delay = close_delay;
+ port->port.closing_wait = closing_wait;
+ }
+
+ mutex_unlock(&port->port.mutex);
+ return retval;
+}
+
+int usb_wwan_ioctl(struct tty_struct *tty,
+ unsigned int cmd, unsigned long arg)
+{
+ struct usb_serial_port *port = tty->driver_data;
+
+ dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd);
+
+ switch (cmd) {
+ case TIOCGSERIAL:
+ return get_serial_info(port,
+ (struct serial_struct __user *) arg);
+ case TIOCSSERIAL:
+ return set_serial_info(port,
+ (struct serial_struct __user *) arg);
+ default:
+ break;
+ }
+
+ dev_dbg(&port->dev, "%s arg not supported\n", __func__);
+
+ return -ENOIOCTLCMD;
+}
+EXPORT_SYMBOL(usb_wwan_ioctl);
+
int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
@@ -136,9 +190,9 @@ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
unsigned long flags;
portdata = usb_get_serial_port_data(port);
- intfdata = port->serial->private;
+ intfdata = usb_get_serial_data(port->serial);
- dbg("%s: write (%d chars)", __func__, count);
+ dev_dbg(&port->dev, "%s: write (%d chars)\n", __func__, count);
i = 0;
left = count;
@@ -155,12 +209,14 @@ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
usb_unlink_urb(this_urb);
continue;
}
- dbg("%s: endpoint %d buf %d", __func__,
- usb_pipeendpoint(this_urb->pipe), i);
+ dev_dbg(&port->dev, "%s: endpoint %d buf %d\n", __func__,
+ usb_pipeendpoint(this_urb->pipe), i);
err = usb_autopm_get_interface_async(port->serial->interface);
- if (err < 0)
+ if (err < 0) {
+ clear_bit(i, &portdata->out_busy);
break;
+ }
/* send the data */
memcpy(this_urb->transfer_buffer, buf, todo);
@@ -175,14 +231,16 @@ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
spin_unlock_irqrestore(&intfdata->susp_lock, flags);
err = usb_submit_urb(this_urb, GFP_ATOMIC);
if (err) {
- dbg("usb_submit_urb %p (write bulk) failed "
- "(%d)", this_urb, err);
+ dev_err(&port->dev,
+ "%s: submit urb %d failed: %d\n",
+ __func__, i, err);
clear_bit(i, &portdata->out_busy);
spin_lock_irqsave(&intfdata->susp_lock, flags);
intfdata->in_flight--;
spin_unlock_irqrestore(&intfdata->susp_lock,
flags);
- continue;
+ usb_autopm_put_interface_async(port->serial->interface);
+ break;
}
}
@@ -192,7 +250,7 @@ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
}
count -= left;
- dbg("%s: wrote (did %d)", __func__, count);
+ dev_dbg(&port->dev, "%s: wrote (did %d)\n", __func__, count);
return count;
}
EXPORT_SYMBOL(usb_wwan_write);
@@ -202,37 +260,36 @@ static void usb_wwan_indat_callback(struct urb *urb)
int err;
int endpoint;
struct usb_serial_port *port;
- struct tty_struct *tty;
+ struct device *dev;
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg("%s: %p", __func__, urb);
-
endpoint = usb_pipeendpoint(urb->pipe);
port = urb->context;
+ dev = &port->dev;
if (status) {
- dbg("%s: nonzero status: %d on endpoint %02x.",
- __func__, status, endpoint);
+ dev_dbg(dev, "%s: nonzero status: %d on endpoint %02x.\n",
+ __func__, status, endpoint);
} else {
- tty = tty_port_tty_get(&port->port);
if (urb->actual_length) {
- tty_insert_flip_string(tty, data, urb->actual_length);
- tty_flip_buffer_push(tty);
+ tty_insert_flip_string(&port->port, data,
+ urb->actual_length);
+ tty_flip_buffer_push(&port->port);
} else
- dbg("%s: empty read urb received", __func__);
- tty_kref_put(tty);
-
- /* Resubmit urb so we continue receiving */
- if (status != -ESHUTDOWN) {
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (err && err != -EPERM)
- printk(KERN_ERR "%s: resubmit read urb failed. "
- "(%d)", __func__, err);
- else
- usb_mark_last_busy(port->serial->dev);
+ dev_dbg(dev, "%s: empty read urb received\n", __func__);
+ }
+ /* Resubmit urb so we continue receiving */
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err) {
+ if (err != -EPERM) {
+ dev_err(dev, "%s: resubmit read urb failed. (%d)\n",
+ __func__, err);
+ /* busy also in error unless we are killed */
+ usb_mark_last_busy(port->serial->dev);
}
-
+ } else {
+ usb_mark_last_busy(port->serial->dev);
}
}
@@ -243,10 +300,8 @@ static void usb_wwan_outdat_callback(struct urb *urb)
struct usb_wwan_intf_private *intfdata;
int i;
- dbg("%s", __func__);
-
port = urb->context;
- intfdata = port->serial->private;
+ intfdata = usb_get_serial_data(port->serial);
usb_serial_port_softint(port);
usb_autopm_put_interface_async(port->serial->interface);
@@ -257,7 +312,7 @@ static void usb_wwan_outdat_callback(struct urb *urb)
for (i = 0; i < N_OUT_URB; ++i) {
if (portdata->out_urbs[i] == urb) {
- smp_mb__before_clear_bit();
+ smp_mb__before_atomic();
clear_bit(i, &portdata->out_busy);
break;
}
@@ -280,7 +335,7 @@ int usb_wwan_write_room(struct tty_struct *tty)
data_len += OUT_BUFLEN;
}
- dbg("%s: %d", __func__, data_len);
+ dev_dbg(&port->dev, "%s: %d\n", __func__, data_len);
return data_len;
}
EXPORT_SYMBOL(usb_wwan_write_room);
@@ -302,7 +357,7 @@ int usb_wwan_chars_in_buffer(struct tty_struct *tty)
if (this_urb && test_bit(i, &portdata->out_busy))
data_len += this_urb->transfer_buffer_length;
}
- dbg("%s: %d", __func__, data_len);
+ dev_dbg(&port->dev, "%s: %d\n", __func__, data_len);
return data_len;
}
EXPORT_SYMBOL(usb_wwan_chars_in_buffer);
@@ -316,9 +371,15 @@ int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port)
struct urb *urb;
portdata = usb_get_serial_port_data(port);
- intfdata = serial->private;
+ intfdata = usb_get_serial_data(serial);
- dbg("%s", __func__);
+ if (port->interrupt_in_urb) {
+ err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (err) {
+ dev_err(&port->dev, "%s: submit int urb failed: %d\n",
+ __func__, err);
+ }
+ }
/* Start reading from the IN endpoint */
for (i = 0; i < N_IN_URB; i++) {
@@ -327,67 +388,85 @@ int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port)
continue;
err = usb_submit_urb(urb, GFP_KERNEL);
if (err) {
- dbg("%s: submit urb %d failed (%d) %d",
- __func__, i, err, urb->transfer_buffer_length);
+ dev_err(&port->dev,
+ "%s: submit read urb %d failed: %d\n",
+ __func__, i, err);
}
}
- if (intfdata->send_setup)
- intfdata->send_setup(port);
-
- serial->interface->needs_remote_wakeup = 1;
spin_lock_irq(&intfdata->susp_lock);
- portdata->opened = 1;
+ if (++intfdata->open_ports == 1)
+ serial->interface->needs_remote_wakeup = 1;
spin_unlock_irq(&intfdata->susp_lock);
+ /* this balances a get in the generic USB serial code */
usb_autopm_put_interface(serial->interface);
return 0;
}
EXPORT_SYMBOL(usb_wwan_open);
+static void unbusy_queued_urb(struct urb *urb,
+ struct usb_wwan_port_private *portdata)
+{
+ int i;
+
+ for (i = 0; i < N_OUT_URB; i++) {
+ if (urb == portdata->out_urbs[i]) {
+ clear_bit(i, &portdata->out_busy);
+ break;
+ }
+ }
+}
+
void usb_wwan_close(struct usb_serial_port *port)
{
int i;
struct usb_serial *serial = port->serial;
struct usb_wwan_port_private *portdata;
- struct usb_wwan_intf_private *intfdata = port->serial->private;
+ struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
+ struct urb *urb;
- dbg("%s", __func__);
portdata = usb_get_serial_port_data(port);
- if (serial->dev) {
- /* Stop reading/writing urbs */
- spin_lock_irq(&intfdata->susp_lock);
- portdata->opened = 0;
- spin_unlock_irq(&intfdata->susp_lock);
-
- for (i = 0; i < N_IN_URB; i++)
- usb_kill_urb(portdata->in_urbs[i]);
- for (i = 0; i < N_OUT_URB; i++)
- usb_kill_urb(portdata->out_urbs[i]);
- usb_autopm_get_interface(serial->interface);
+ /*
+ * Need to take susp_lock to make sure port is not already being
+ * resumed, but no need to hold it due to ASYNC_INITIALIZED.
+ */
+ spin_lock_irq(&intfdata->susp_lock);
+ if (--intfdata->open_ports == 0)
serial->interface->needs_remote_wakeup = 0;
+ spin_unlock_irq(&intfdata->susp_lock);
+
+ for (;;) {
+ urb = usb_get_from_anchor(&portdata->delayed);
+ if (!urb)
+ break;
+ unbusy_queued_urb(urb, portdata);
+ usb_autopm_put_interface_async(serial->interface);
}
+
+ for (i = 0; i < N_IN_URB; i++)
+ usb_kill_urb(portdata->in_urbs[i]);
+ for (i = 0; i < N_OUT_URB; i++)
+ usb_kill_urb(portdata->out_urbs[i]);
+ usb_kill_urb(port->interrupt_in_urb);
+
+ usb_autopm_get_interface_no_resume(serial->interface);
}
EXPORT_SYMBOL(usb_wwan_close);
-/* Helper functions used by usb_wwan_setup_urbs */
-static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,
+static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
+ int endpoint,
int dir, void *ctx, char *buf, int len,
void (*callback) (struct urb *))
{
+ struct usb_serial *serial = port->serial;
struct urb *urb;
- if (endpoint == -1)
- return NULL; /* endpoint not needed */
-
urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
- if (urb == NULL) {
- dbg("%s: alloc for endpoint %d failed.", __func__, endpoint);
+ if (!urb)
return NULL;
- }
- /* Fill URB using supplied data. */
usb_fill_bulk_urb(urb, serial->dev,
usb_sndbulkpipe(serial->dev, endpoint) | dir,
buf, len, callback, ctx);
@@ -395,270 +474,222 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,
return urb;
}
-/* Setup urbs */
-static void usb_wwan_setup_urbs(struct usb_serial *serial)
+int usb_wwan_port_probe(struct usb_serial_port *port)
{
- int i, j;
- struct usb_serial_port *port;
struct usb_wwan_port_private *portdata;
+ struct urb *urb;
+ u8 *buffer;
+ int i;
- dbg("%s", __func__);
+ if (!port->bulk_in_size || !port->bulk_out_size)
+ return -ENODEV;
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- portdata = usb_get_serial_port_data(port);
+ portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+ if (!portdata)
+ return -ENOMEM;
- /* Do indat endpoints first */
- for (j = 0; j < N_IN_URB; ++j) {
- portdata->in_urbs[j] = usb_wwan_setup_urb(serial,
- port->
- bulk_in_endpointAddress,
- USB_DIR_IN,
- port,
- portdata->
- in_buffer[j],
- IN_BUFLEN,
- usb_wwan_indat_callback);
- }
+ init_usb_anchor(&portdata->delayed);
- /* outdat endpoints */
- for (j = 0; j < N_OUT_URB; ++j) {
- portdata->out_urbs[j] = usb_wwan_setup_urb(serial,
- port->
- bulk_out_endpointAddress,
- USB_DIR_OUT,
- port,
- portdata->
- out_buffer
- [j],
- OUT_BUFLEN,
- usb_wwan_outdat_callback);
- }
+ for (i = 0; i < N_IN_URB; i++) {
+ buffer = (u8 *)__get_free_page(GFP_KERNEL);
+ if (!buffer)
+ goto bail_out_error;
+ portdata->in_buffer[i] = buffer;
+
+ urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress,
+ USB_DIR_IN, port,
+ buffer, IN_BUFLEN,
+ usb_wwan_indat_callback);
+ portdata->in_urbs[i] = urb;
}
-}
-int usb_wwan_startup(struct usb_serial *serial)
-{
- int i, j, err;
- struct usb_serial_port *port;
- struct usb_wwan_port_private *portdata;
- u8 *buffer;
-
- dbg("%s", __func__);
-
- /* Now setup per port private data */
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
- if (!portdata) {
- dbg("%s: kmalloc for usb_wwan_port_private (%d) failed!.",
- __func__, i);
- return 1;
- }
- init_usb_anchor(&portdata->delayed);
-
- for (j = 0; j < N_IN_URB; j++) {
- buffer = (u8 *) __get_free_page(GFP_KERNEL);
- if (!buffer)
- goto bail_out_error;
- portdata->in_buffer[j] = buffer;
- }
-
- for (j = 0; j < N_OUT_URB; j++) {
- buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
- if (!buffer)
- goto bail_out_error2;
- portdata->out_buffer[j] = buffer;
- }
+ for (i = 0; i < N_OUT_URB; i++) {
+ buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
+ if (!buffer)
+ goto bail_out_error2;
+ portdata->out_buffer[i] = buffer;
+
+ urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress,
+ USB_DIR_OUT, port,
+ buffer, OUT_BUFLEN,
+ usb_wwan_outdat_callback);
+ portdata->out_urbs[i] = urb;
+ }
- usb_set_serial_port_data(port, portdata);
+ usb_set_serial_port_data(port, portdata);
- if (!port->interrupt_in_urb)
- continue;
- err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
- if (err)
- dbg("%s: submit irq_in urb failed %d", __func__, err);
- }
- usb_wwan_setup_urbs(serial);
return 0;
bail_out_error2:
- for (j = 0; j < N_OUT_URB; j++)
- kfree(portdata->out_buffer[j]);
+ for (i = 0; i < N_OUT_URB; i++) {
+ usb_free_urb(portdata->out_urbs[i]);
+ kfree(portdata->out_buffer[i]);
+ }
bail_out_error:
- for (j = 0; j < N_IN_URB; j++)
- if (portdata->in_buffer[j])
- free_page((unsigned long)portdata->in_buffer[j]);
+ for (i = 0; i < N_IN_URB; i++) {
+ usb_free_urb(portdata->in_urbs[i]);
+ free_page((unsigned long)portdata->in_buffer[i]);
+ }
kfree(portdata);
- return 1;
+
+ return -ENOMEM;
}
-EXPORT_SYMBOL(usb_wwan_startup);
+EXPORT_SYMBOL_GPL(usb_wwan_port_probe);
-static void stop_read_write_urbs(struct usb_serial *serial)
+int usb_wwan_port_remove(struct usb_serial_port *port)
{
- int i, j;
- struct usb_serial_port *port;
+ int i;
struct usb_wwan_port_private *portdata;
- /* Stop reading/writing urbs */
- for (i = 0; i < serial->num_ports; ++i) {
- port = serial->port[i];
- portdata = usb_get_serial_port_data(port);
- for (j = 0; j < N_IN_URB; j++)
- usb_kill_urb(portdata->in_urbs[j]);
- for (j = 0; j < N_OUT_URB; j++)
- usb_kill_urb(portdata->out_urbs[j]);
+ portdata = usb_get_serial_port_data(port);
+ usb_set_serial_port_data(port, NULL);
+
+ for (i = 0; i < N_IN_URB; i++) {
+ usb_free_urb(portdata->in_urbs[i]);
+ free_page((unsigned long)portdata->in_buffer[i]);
+ }
+ for (i = 0; i < N_OUT_URB; i++) {
+ usb_free_urb(portdata->out_urbs[i]);
+ kfree(portdata->out_buffer[i]);
}
-}
-void usb_wwan_disconnect(struct usb_serial *serial)
-{
- dbg("%s", __func__);
+ kfree(portdata);
- stop_read_write_urbs(serial);
+ return 0;
}
-EXPORT_SYMBOL(usb_wwan_disconnect);
+EXPORT_SYMBOL(usb_wwan_port_remove);
-void usb_wwan_release(struct usb_serial *serial)
+#ifdef CONFIG_PM
+static void stop_urbs(struct usb_serial *serial)
{
int i, j;
struct usb_serial_port *port;
struct usb_wwan_port_private *portdata;
- dbg("%s", __func__);
-
- /* Now free them */
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
portdata = usb_get_serial_port_data(port);
-
- for (j = 0; j < N_IN_URB; j++) {
- usb_free_urb(portdata->in_urbs[j]);
- free_page((unsigned long)
- portdata->in_buffer[j]);
- portdata->in_urbs[j] = NULL;
- }
- for (j = 0; j < N_OUT_URB; j++) {
- usb_free_urb(portdata->out_urbs[j]);
- kfree(portdata->out_buffer[j]);
- portdata->out_urbs[j] = NULL;
- }
- }
-
- /* Now free per port private data */
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- kfree(usb_get_serial_port_data(port));
+ if (!portdata)
+ continue;
+ for (j = 0; j < N_IN_URB; j++)
+ usb_kill_urb(portdata->in_urbs[j]);
+ for (j = 0; j < N_OUT_URB; j++)
+ usb_kill_urb(portdata->out_urbs[j]);
+ usb_kill_urb(port->interrupt_in_urb);
}
}
-EXPORT_SYMBOL(usb_wwan_release);
-#ifdef CONFIG_PM
int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message)
{
- struct usb_wwan_intf_private *intfdata = serial->private;
- int b;
+ struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
- dbg("%s entered", __func__);
-
- if (message.event & PM_EVENT_AUTO) {
- spin_lock_irq(&intfdata->susp_lock);
- b = intfdata->in_flight;
- spin_unlock_irq(&intfdata->susp_lock);
-
- if (b)
+ spin_lock_irq(&intfdata->susp_lock);
+ if (PMSG_IS_AUTO(message)) {
+ if (intfdata->in_flight) {
+ spin_unlock_irq(&intfdata->susp_lock);
return -EBUSY;
+ }
}
-
- spin_lock_irq(&intfdata->susp_lock);
intfdata->suspended = 1;
spin_unlock_irq(&intfdata->susp_lock);
- stop_read_write_urbs(serial);
+
+ stop_urbs(serial);
return 0;
}
EXPORT_SYMBOL(usb_wwan_suspend);
-static void play_delayed(struct usb_serial_port *port)
+/* Caller must hold susp_lock. */
+static int usb_wwan_submit_delayed_urbs(struct usb_serial_port *port)
{
- struct usb_wwan_intf_private *data;
+ struct usb_serial *serial = port->serial;
+ struct usb_wwan_intf_private *data = usb_get_serial_data(serial);
struct usb_wwan_port_private *portdata;
struct urb *urb;
+ int err_count = 0;
int err;
portdata = usb_get_serial_port_data(port);
- data = port->serial->private;
- while ((urb = usb_get_from_anchor(&portdata->delayed))) {
+
+ for (;;) {
+ urb = usb_get_from_anchor(&portdata->delayed);
+ if (!urb)
+ break;
+
err = usb_submit_urb(urb, GFP_ATOMIC);
- if (!err)
- data->in_flight++;
+ if (err) {
+ dev_err(&port->dev, "%s: submit urb failed: %d\n",
+ __func__, err);
+ err_count++;
+ unbusy_queued_urb(urb, portdata);
+ usb_autopm_put_interface_async(serial->interface);
+ continue;
+ }
+ data->in_flight++;
}
+
+ if (err_count)
+ return -EIO;
+
+ return 0;
}
int usb_wwan_resume(struct usb_serial *serial)
{
int i, j;
struct usb_serial_port *port;
- struct usb_wwan_intf_private *intfdata = serial->private;
+ struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
struct usb_wwan_port_private *portdata;
struct urb *urb;
- int err = 0;
+ int err;
+ int err_count = 0;
- dbg("%s entered", __func__);
- /* get the interrupt URBs resubmitted unconditionally */
+ spin_lock_irq(&intfdata->susp_lock);
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
- if (!port->interrupt_in_urb) {
- dbg("%s: No interrupt URB for port %d", __func__, i);
+
+ if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
continue;
- }
- err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
- dbg("Submitted interrupt URB for port %d (result %d)", i, err);
- if (err < 0) {
- err("%s: Error %d for interrupt URB of port%d",
- __func__, err, i);
- goto err_out;
- }
- }
- for (i = 0; i < serial->num_ports; i++) {
- /* walk all ports */
- port = serial->port[i];
portdata = usb_get_serial_port_data(port);
- /* skip closed ports */
- spin_lock_irq(&intfdata->susp_lock);
- if (!portdata->opened) {
- spin_unlock_irq(&intfdata->susp_lock);
- continue;
+ if (port->interrupt_in_urb) {
+ err = usb_submit_urb(port->interrupt_in_urb,
+ GFP_ATOMIC);
+ if (err) {
+ dev_err(&port->dev,
+ "%s: submit int urb failed: %d\n",
+ __func__, err);
+ err_count++;
+ }
}
+ err = usb_wwan_submit_delayed_urbs(port);
+ if (err)
+ err_count++;
+
for (j = 0; j < N_IN_URB; j++) {
urb = portdata->in_urbs[j];
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err < 0) {
- err("%s: Error %d for bulk URB %d",
- __func__, err, i);
- spin_unlock_irq(&intfdata->susp_lock);
- goto err_out;
+ dev_err(&port->dev,
+ "%s: submit read urb %d failed: %d\n",
+ __func__, i, err);
+ err_count++;
}
}
- play_delayed(port);
- spin_unlock_irq(&intfdata->susp_lock);
}
- spin_lock_irq(&intfdata->susp_lock);
intfdata->suspended = 0;
spin_unlock_irq(&intfdata->susp_lock);
-err_out:
- return err;
+
+ if (err_count)
+ return -EIO;
+
+ return 0;
}
EXPORT_SYMBOL(usb_wwan_resume);
#endif
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug messages");
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 15a5d89b7f3..bf2bd40e5f2 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -16,7 +16,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -27,6 +26,7 @@
#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
+#include <linux/usb/cdc.h>
#include "visor.h"
/*
@@ -50,12 +50,7 @@ static int palm_os_3_probe(struct usb_serial *serial,
static int palm_os_4_probe(struct usb_serial *serial,
const struct usb_device_id *id);
-/* Parameters that may be passed into the module. */
-static int debug;
-static __u16 vendor;
-static __u16 product;
-
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID),
.driver_info = (kernel_ulong_t)&palm_os_3_probe },
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID),
@@ -114,23 +109,21 @@ static struct usb_device_id id_table [] = {
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
- { }, /* optional parameter entry */
{ } /* Terminating entry */
};
-static struct usb_device_id clie_id_5_table [] = {
+static const struct usb_device_id clie_id_5_table[] = {
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
- { }, /* optional parameter entry */
{ } /* Terminating entry */
};
-static struct usb_device_id clie_id_3_5_table [] = {
+static const struct usb_device_id clie_id_3_5_table[] = {
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) },
{ } /* Terminating entry */
};
-static struct usb_device_id id_table_combined [] = {
+static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID) },
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID) },
@@ -161,20 +154,11 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) },
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID) },
{ USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID) },
- { }, /* optional parameter entry */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver visor_driver = {
- .name = "visor",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
- .no_dynamic_id = 1,
-};
-
/* All of the device info needed for the Handspring Visor,
and Palm 4.0 devices */
static struct usb_serial_driver handspring_device = {
@@ -183,7 +167,6 @@ static struct usb_serial_driver handspring_device = {
.name = "visor",
},
.description = "Handspring Visor / Palm OS",
- .usb_driver = &visor_driver,
.id_table = id_table,
.num_ports = 2,
.bulk_out_size = 256,
@@ -204,7 +187,6 @@ static struct usb_serial_driver clie_5_device = {
.name = "clie_5",
},
.description = "Sony Clie 5.0",
- .usb_driver = &visor_driver,
.id_table = clie_id_5_table,
.num_ports = 2,
.bulk_out_size = 256,
@@ -225,7 +207,6 @@ static struct usb_serial_driver clie_3_5_device = {
.name = "clie_3.5",
},
.description = "Sony Clie 3.5",
- .usb_driver = &visor_driver,
.id_table = clie_id_3_5_table,
.num_ports = 1,
.bulk_out_size = 256,
@@ -236,6 +217,10 @@ static struct usb_serial_driver clie_3_5_device = {
.attach = clie_3_5_startup,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &handspring_device, &clie_5_device, &clie_3_5_device, NULL
+};
+
/******************************************************************************
* Handspring Visor specific driver functions
******************************************************************************/
@@ -243,8 +228,6 @@ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port)
{
int result = 0;
- dbg("%s - port %d", __func__, port->number);
-
if (!port->read_urb) {
/* this is needed for some brain dead Sony devices */
dev_err(&port->dev, "Device lied about number of ports, please use a lower one.\n");
@@ -257,7 +240,7 @@ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port)
goto exit;
if (port->interrupt_in_urb) {
- dbg("%s - adding interrupt input for treo", __func__);
+ dev_dbg(&port->dev, "adding interrupt input for treo\n");
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result)
dev_err(&port->dev,
@@ -273,26 +256,18 @@ static void visor_close(struct usb_serial_port *port)
{
unsigned char *transfer_buffer;
- dbg("%s - port %d", __func__, port->number);
-
- /* shutdown our urbs */
usb_serial_generic_close(port);
usb_kill_urb(port->interrupt_in_urb);
- mutex_lock(&port->serial->disc_mutex);
- if (!port->serial->disconnected) {
- /* Try to send shutdown message, unless the device is gone */
- transfer_buffer = kmalloc(0x12, GFP_KERNEL);
- if (transfer_buffer) {
- usb_control_msg(port->serial->dev,
+ transfer_buffer = kmalloc(0x12, GFP_KERNEL);
+ if (!transfer_buffer)
+ return;
+ usb_control_msg(port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0),
VISOR_CLOSE_NOTIFICATION, 0xc2,
0x0000, 0x0000,
transfer_buffer, 0x12, 300);
- kfree(transfer_buffer);
- }
- }
- mutex_unlock(&port->serial->disc_mutex);
+ kfree(transfer_buffer);
}
static void visor_read_int_callback(struct urb *urb)
@@ -309,12 +284,12 @@ static void visor_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
goto exit;
}
@@ -325,8 +300,8 @@ static void visor_read_int_callback(struct urb *urb)
* Rumor has it this endpoint is used to notify when data
* is ready to be read from the bulk ones.
*/
- usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, urb->transfer_buffer);
+ usb_serial_debug_data(&port->dev, __func__, urb->actual_length,
+ urb->transfer_buffer);
exit:
result = usb_submit_urb(urb, GFP_ATOMIC);
@@ -347,14 +322,9 @@ static int palm_os_3_probe(struct usb_serial *serial,
int i;
int num_ports = 0;
- dbg("%s", __func__);
-
transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL);
- if (!transfer_buffer) {
- dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
- sizeof(*connection_info));
+ if (!transfer_buffer)
return -ENOMEM;
- }
/* send a get connection info request */
retval = usb_control_msg(serial->dev,
@@ -444,14 +414,9 @@ static int palm_os_4_probe(struct usb_serial *serial,
unsigned char *transfer_buffer;
int retval;
- dbg("%s", __func__);
-
transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL);
- if (!transfer_buffer) {
- dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
- sizeof(*connection_info));
+ if (!transfer_buffer)
return -ENOMEM;
- }
retval = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
@@ -462,8 +427,7 @@ static int palm_os_4_probe(struct usb_serial *serial,
dev_err(dev, "%s - error %d getting connection info\n",
__func__, retval);
else
- usb_serial_debug_data(debug, &serial->dev->dev, __func__,
- retval, transfer_buffer);
+ usb_serial_debug_data(dev, __func__, retval, transfer_buffer);
kfree(transfer_buffer);
return 0;
@@ -477,7 +441,16 @@ static int visor_probe(struct usb_serial *serial,
int (*startup)(struct usb_serial *serial,
const struct usb_device_id *id);
- dbg("%s", __func__);
+ /*
+ * some Samsung Android phones in modem mode have the same ID
+ * as SPH-I500, but they are ACM devices, so dont bind to them
+ */
+ if (id->idVendor == SAMSUNG_VENDOR_ID &&
+ id->idProduct == SAMSUNG_SPH_I500_ID &&
+ serial->dev->descriptor.bDeviceClass == USB_CLASS_COMM &&
+ serial->dev->descriptor.bDeviceSubClass ==
+ USB_CDC_SUBCLASS_ACM)
+ return -ENODEV;
if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
dev_err(&serial->dev->dev, "active config #%d != 1 ??\n",
@@ -509,8 +482,6 @@ static int clie_3_5_startup(struct usb_serial *serial)
int result;
u8 *data;
- dbg("%s", __func__);
-
data = kmalloc(1, GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -573,8 +544,6 @@ static int treo_attach(struct usb_serial *serial)
(serial->num_interrupt_in == 0))
return 0;
- dbg("%s", __func__);
-
/*
* It appears that Treos and Kyoceras want to use the
* 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
@@ -584,10 +553,19 @@ static int treo_attach(struct usb_serial *serial)
*/
#define COPY_PORT(dest, src) \
do { \
+ int i; \
+ \
+ for (i = 0; i < ARRAY_SIZE(src->read_urbs); ++i) { \
+ dest->read_urbs[i] = src->read_urbs[i]; \
+ dest->read_urbs[i]->context = dest; \
+ dest->bulk_in_buffers[i] = src->bulk_in_buffers[i]; \
+ } \
dest->read_urb = src->read_urb; \
dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;\
dest->bulk_in_buffer = src->bulk_in_buffer; \
+ dest->bulk_in_size = src->bulk_in_size; \
dest->interrupt_in_urb = src->interrupt_in_urb; \
+ dest->interrupt_in_urb->context = dest; \
dest->interrupt_in_endpointAddress = \
src->interrupt_in_endpointAddress;\
dest->interrupt_in_buffer = src->interrupt_in_buffer; \
@@ -610,8 +588,6 @@ static int clie_5_attach(struct usb_serial *serial)
unsigned int pipe;
int j;
- dbg("%s", __func__);
-
/* TH55 registers 2 ports.
Communication in from the UX50/TH55 uses bulk_in_endpointAddress
from port 0. Communication out to the UX50/TH55 uses
@@ -636,90 +612,8 @@ static int clie_5_attach(struct usb_serial *serial)
return 0;
}
-static int __init visor_init(void)
-{
- int i, retval;
- /* Only if parameters were passed to us */
- if (vendor > 0 && product > 0) {
- struct usb_device_id usb_dev_temp[] = {
- {
- USB_DEVICE(vendor, product),
- .driver_info =
- (kernel_ulong_t) &palm_os_4_probe
- }
- };
-
- /* Find the last entry in id_table */
- for (i = 0;; i++) {
- if (id_table[i].idVendor == 0) {
- id_table[i] = usb_dev_temp[0];
- break;
- }
- }
- /* Find the last entry in id_table_combined */
- for (i = 0;; i++) {
- if (id_table_combined[i].idVendor == 0) {
- id_table_combined[i] = usb_dev_temp[0];
- break;
- }
- }
- printk(KERN_INFO KBUILD_MODNAME
- ": Untested USB device specified at time of module insertion\n");
- printk(KERN_INFO KBUILD_MODNAME
- ": Warning: This is not guaranteed to work\n");
- printk(KERN_INFO KBUILD_MODNAME
- ": Using a newer kernel is preferred to this method\n");
- printk(KERN_INFO KBUILD_MODNAME
- ": Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x\n",
- vendor, product);
- }
- retval = usb_serial_register(&handspring_device);
- if (retval)
- goto failed_handspring_register;
- retval = usb_serial_register(&clie_3_5_device);
- if (retval)
- goto failed_clie_3_5_register;
- retval = usb_serial_register(&clie_5_device);
- if (retval)
- goto failed_clie_5_register;
- retval = usb_register(&visor_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
-
- return 0;
-failed_usb_register:
- usb_serial_deregister(&clie_5_device);
-failed_clie_5_register:
- usb_serial_deregister(&clie_3_5_device);
-failed_clie_3_5_register:
- usb_serial_deregister(&handspring_device);
-failed_handspring_register:
- return retval;
-}
-
-
-static void __exit visor_exit (void)
-{
- usb_deregister(&visor_driver);
- usb_serial_deregister(&handspring_device);
- usb_serial_deregister(&clie_3_5_device);
- usb_serial_deregister(&clie_5_device);
-}
-
-
-module_init(visor_init);
-module_exit(visor_exit);
+module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled 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");
-
diff --git a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h
index 88db4d06aef..4c456dd69ce 100644
--- a/drivers/usb/serial/visor.h
+++ b/drivers/usb/serial/visor.h
@@ -136,7 +136,7 @@ struct visor_connection_info {
* connections.end_point_info is non-zero. If value is 0, then
* connections.port contains the endpoint number, which is the same for in
* and out.
- * @port_function_id: contains the creator id of the applicaton that opened
+ * @port_function_id: contains the creator id of the application that opened
* this connection.
* @port: contains the in/out endpoint number. Is 0 if in and out endpoint
* numbers are different.
diff --git a/drivers/usb/serial/vivopay-serial.c b/drivers/usb/serial/vivopay-serial.c
deleted file mode 100644
index f719d00972f..00000000000
--- a/drivers/usb/serial/vivopay-serial.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2001-2005 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2009 Outpost Embedded, LLC
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-
-
-#define DRIVER_VERSION "v1.0"
-#define DRIVER_DESC "ViVOpay USB Serial Driver"
-
-#define VIVOPAY_VENDOR_ID 0x1d5f
-
-
-static struct usb_device_id id_table [] = {
- /* ViVOpay 8800 */
- { USB_DEVICE(VIVOPAY_VENDOR_ID, 0x1004) },
- { },
-};
-
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static struct usb_driver vivopay_serial_driver = {
- .name = "vivopay-serial",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
-static struct usb_serial_driver vivopay_serial_device = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "vivopay-serial",
- },
- .id_table = id_table,
- .usb_driver = &vivopay_serial_driver,
- .num_ports = 1,
-};
-
-static int __init vivopay_serial_init(void)
-{
- int retval;
- retval = usb_serial_register(&vivopay_serial_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&vivopay_serial_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&vivopay_serial_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit vivopay_serial_exit(void)
-{
- usb_deregister(&vivopay_serial_driver);
- usb_serial_deregister(&vivopay_serial_device);
-}
-
-module_init(vivopay_serial_init);
-module_exit(vivopay_serial_exit);
-
-MODULE_AUTHOR("Forest Bond <forest.bond@outpostembedded.com>");
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 3f9ac88d588..e62f2dff8b7 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -14,62 +14,10 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this
* driver
- *
- * (10/09/2002) Stuart MacDonald (stuartm@connecttech.com)
- * Upgrade to full working driver
- *
- * (05/30/2001) gkh
- * switched from using spinlock to a semaphore, which fixes lots of
- * problems.
- *
- * (04/08/2001) gb
- * Identify version on module load.
- *
- * 2001_Mar_19 gkh
- * Fixed MOD_INC and MOD_DEC logic, the ability to open a port more
- * than once, and the got the proper usb_device_id table entries so
- * the driver works again.
- *
- * (11/01/2000) Adam J. Richter
- * usb_device_id table support
- *
- * (10/05/2000) gkh
- * Fixed bug with urb->dev not being set properly, now that the usb
- * core needs it.
- *
- * (10/03/2000) smd
- * firmware is improved to guard against crap sent to device
- * firmware now replies CMD_FAILURE on bad things
- * read_callback fix you provided for private info struct
- * command_finished now indicates success or fail
- * setup_port struct now packed to avoid gcc padding
- * firmware uses 1 based port numbering, driver now handles that
- *
- * (09/11/2000) gkh
- * Removed DEBUG #ifdefs with call to usb_serial_debug_data
- *
- * (07/19/2000) gkh
- * Added module_init and module_exit functions to handle the fact that this
- * driver is a loadable module now.
- * Fixed bug with port->minor that was found by Al Borchers
- *
- * (07/04/2000) gkh
- * Added support for port settings. Baud rate can now be changed. Line
- * signals are not transferred to and from the tty layer yet, but things
- * seem to be working well now.
- *
- * (05/04/2000) gkh
- * First cut at open and close commands. Data can flow through the ports at
- * default speeds now.
- *
- * (03/26/2000) gkh
- * Split driver up into device specific pieces.
- *
*/
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -83,12 +31,9 @@
#include <linux/serial_reg.h>
#include <linux/serial.h>
#include <linux/usb/serial.h>
-#include <linux/firmware.h>
-#include <linux/ihex.h>
+#include <linux/usb/ezusb.h>
#include "whiteheat.h" /* WhiteHEAT specific commands */
-static int debug;
-
#ifndef CMSPAR
#define CMSPAR 0
#endif
@@ -96,7 +41,6 @@ static int debug;
/*
* Version Information
*/
-#define DRIVER_VERSION "v2.0"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Stuart MacDonald <stuartm@connecttech.com>"
#define DRIVER_DESC "USB ConnectTech WhiteHEAT driver"
@@ -129,13 +73,6 @@ static const struct usb_device_id id_table_combined[] = {
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver whiteheat_driver = {
- .name = "whiteheat",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
- .no_dynamic_id = 1,
-};
/* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */
static int whiteheat_firmware_download(struct usb_serial *serial,
@@ -145,26 +82,19 @@ static int whiteheat_firmware_attach(struct usb_serial *serial);
/* function prototypes for the Connect Tech WhiteHEAT serial converter */
static int whiteheat_attach(struct usb_serial *serial);
static void whiteheat_release(struct usb_serial *serial);
+static int whiteheat_port_probe(struct usb_serial_port *port);
+static int whiteheat_port_remove(struct usb_serial_port *port);
static int whiteheat_open(struct tty_struct *tty,
struct usb_serial_port *port);
static void whiteheat_close(struct usb_serial_port *port);
-static int whiteheat_write(struct tty_struct *tty,
- struct usb_serial_port *port,
- const unsigned char *buf, int count);
-static int whiteheat_write_room(struct tty_struct *tty);
-static int whiteheat_ioctl(struct tty_struct *tty, struct file *file,
+static int whiteheat_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
static void whiteheat_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
-static int whiteheat_tiocmget(struct tty_struct *tty, struct file *file);
-static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file,
+static int whiteheat_tiocmget(struct tty_struct *tty);
+static int whiteheat_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
static void whiteheat_break_ctl(struct tty_struct *tty, int break_state);
-static int whiteheat_chars_in_buffer(struct tty_struct *tty);
-static void whiteheat_throttle(struct tty_struct *tty);
-static void whiteheat_unthrottle(struct tty_struct *tty);
-static void whiteheat_read_callback(struct urb *urb);
-static void whiteheat_write_callback(struct urb *urb);
static struct usb_serial_driver whiteheat_fake_device = {
.driver = {
@@ -172,7 +102,6 @@ static struct usb_serial_driver whiteheat_fake_device = {
.name = "whiteheatnofirm",
},
.description = "Connect Tech - WhiteHEAT - (prerenumeration)",
- .usb_driver = &whiteheat_driver,
.id_table = id_table_prerenumeration,
.num_ports = 1,
.probe = whiteheat_firmware_download,
@@ -185,27 +114,26 @@ static struct usb_serial_driver whiteheat_device = {
.name = "whiteheat",
},
.description = "Connect Tech - WhiteHEAT",
- .usb_driver = &whiteheat_driver,
.id_table = id_table_std,
.num_ports = 4,
.attach = whiteheat_attach,
.release = whiteheat_release,
+ .port_probe = whiteheat_port_probe,
+ .port_remove = whiteheat_port_remove,
.open = whiteheat_open,
.close = whiteheat_close,
- .write = whiteheat_write,
- .write_room = whiteheat_write_room,
.ioctl = whiteheat_ioctl,
.set_termios = whiteheat_set_termios,
.break_ctl = whiteheat_break_ctl,
.tiocmget = whiteheat_tiocmget,
.tiocmset = whiteheat_tiocmset,
- .chars_in_buffer = whiteheat_chars_in_buffer,
- .throttle = whiteheat_throttle,
- .unthrottle = whiteheat_unthrottle,
- .read_bulk_callback = whiteheat_read_callback,
- .write_bulk_callback = whiteheat_write_callback,
+ .throttle = usb_serial_generic_throttle,
+ .unthrottle = usb_serial_generic_unthrottle,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &whiteheat_fake_device, &whiteheat_device, NULL
+};
struct whiteheat_command_private {
struct mutex mutex;
@@ -217,29 +145,8 @@ struct whiteheat_command_private {
__u8 result_buffer[64];
};
-
-#define THROTTLED 0x01
-#define ACTUALLY_THROTTLED 0x02
-
-static int urb_pool_size = 8;
-
-struct whiteheat_urb_wrap {
- struct list_head list;
- struct urb *urb;
-};
-
struct whiteheat_private {
- spinlock_t lock;
- __u8 flags;
__u8 mcr; /* FIXME: no locking on mcr */
- struct list_head rx_urbs_free;
- struct list_head rx_urbs_submitted;
- struct list_head rx_urb_q;
- struct work_struct rx_work;
- struct usb_serial_port *port;
- struct list_head tx_urbs_free;
- struct list_head tx_urbs_submitted;
- struct mutex deathwarrant;
};
@@ -249,12 +156,6 @@ static void stop_command_port(struct usb_serial *serial);
static void command_port_write_callback(struct urb *urb);
static void command_port_read_callback(struct urb *urb);
-static int start_port_read(struct usb_serial_port *port);
-static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb,
- struct list_head *head);
-static struct list_head *list_first(struct list_head *head);
-static void rx_data_softint(struct work_struct *work);
-
static int firm_send_command(struct usb_serial_port *port, __u8 command,
__u8 *data, __u8 datasize);
static int firm_open(struct usb_serial_port *port);
@@ -294,86 +195,15 @@ static int firm_report_tx_done(struct usb_serial_port *port);
static int whiteheat_firmware_download(struct usb_serial *serial,
const struct usb_device_id *id)
{
- int response, ret = -ENOENT;
- const struct firmware *loader_fw = NULL, *firmware_fw = NULL;
- const struct ihex_binrec *record;
-
- dbg("%s", __func__);
+ int response;
- if (request_ihex_firmware(&firmware_fw, "whiteheat.fw",
- &serial->dev->dev)) {
- dev_err(&serial->dev->dev,
- "%s - request \"whiteheat.fw\" failed\n", __func__);
- goto out;
+ response = ezusb_fx1_ihex_firmware_download(serial->dev, "whiteheat_loader.fw");
+ if (response >= 0) {
+ response = ezusb_fx1_ihex_firmware_download(serial->dev, "whiteheat.fw");
+ if (response >= 0)
+ return 0;
}
- if (request_ihex_firmware(&loader_fw, "whiteheat_loader.fw",
- &serial->dev->dev)) {
- dev_err(&serial->dev->dev,
- "%s - request \"whiteheat_loader.fw\" failed\n",
- __func__);
- goto out;
- }
- ret = 0;
- response = ezusb_set_reset (serial, 1);
-
- record = (const struct ihex_binrec *)loader_fw->data;
- while (record) {
- response = ezusb_writememory (serial, be32_to_cpu(record->addr),
- (unsigned char *)record->data,
- be16_to_cpu(record->len), 0xa0);
- if (response < 0) {
- dev_err(&serial->dev->dev, "%s - ezusb_writememory "
- "failed for loader (%d %04X %p %d)\n",
- __func__, response, be32_to_cpu(record->addr),
- record->data, be16_to_cpu(record->len));
- break;
- }
- record = ihex_next_binrec(record);
- }
-
- response = ezusb_set_reset(serial, 0);
-
- record = (const struct ihex_binrec *)firmware_fw->data;
- while (record && be32_to_cpu(record->addr) < 0x1b40)
- record = ihex_next_binrec(record);
- while (record) {
- response = ezusb_writememory (serial, be32_to_cpu(record->addr),
- (unsigned char *)record->data,
- be16_to_cpu(record->len), 0xa3);
- if (response < 0) {
- dev_err(&serial->dev->dev, "%s - ezusb_writememory "
- "failed for first firmware step "
- "(%d %04X %p %d)\n", __func__, response,
- be32_to_cpu(record->addr), record->data,
- be16_to_cpu(record->len));
- break;
- }
- ++record;
- }
-
- response = ezusb_set_reset(serial, 1);
-
- record = (const struct ihex_binrec *)firmware_fw->data;
- while (record && be32_to_cpu(record->addr) < 0x1b40) {
- response = ezusb_writememory (serial, be32_to_cpu(record->addr),
- (unsigned char *)record->data,
- be16_to_cpu(record->len), 0xa0);
- if (response < 0) {
- dev_err(&serial->dev->dev, "%s - ezusb_writememory "
- "failed for second firmware step "
- "(%d %04X %p %d)\n", __func__, response,
- be32_to_cpu(record->addr), record->data,
- be16_to_cpu(record->len));
- break;
- }
- ++record;
- }
- ret = 0;
- response = ezusb_set_reset (serial, 0);
- out:
- release_firmware(loader_fw);
- release_firmware(firmware_fw);
- return ret;
+ return -ENOENT;
}
@@ -391,20 +221,12 @@ static int whiteheat_attach(struct usb_serial *serial)
{
struct usb_serial_port *command_port;
struct whiteheat_command_private *command_info;
- struct usb_serial_port *port;
- struct whiteheat_private *info;
struct whiteheat_hw_info *hw_info;
int pipe;
int ret;
int alen;
__u8 *command;
__u8 *result;
- int i;
- int j;
- struct urb *urb;
- int buf_size;
- struct whiteheat_urb_wrap *wrap;
- struct list_head *tmp;
command_port = serial->port[COMMAND_PORT];
@@ -459,99 +281,14 @@ static int whiteheat_attach(struct usb_serial *serial)
hw_info = (struct whiteheat_hw_info *)&result[1];
- dev_info(&serial->dev->dev, "%s: Driver %s: Firmware v%d.%02d\n",
- serial->type->description, DRIVER_VERSION,
+ dev_info(&serial->dev->dev, "%s: Firmware v%d.%02d\n",
+ serial->type->description,
hw_info->sw_major_rev, hw_info->sw_minor_rev);
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
-
- info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
- if (info == NULL) {
- dev_err(&port->dev,
- "%s: Out of memory for port structures\n",
- serial->type->description);
- goto no_private;
- }
-
- spin_lock_init(&info->lock);
- mutex_init(&info->deathwarrant);
- info->flags = 0;
- info->mcr = 0;
- INIT_WORK(&info->rx_work, rx_data_softint);
- info->port = port;
-
- INIT_LIST_HEAD(&info->rx_urbs_free);
- INIT_LIST_HEAD(&info->rx_urbs_submitted);
- INIT_LIST_HEAD(&info->rx_urb_q);
- INIT_LIST_HEAD(&info->tx_urbs_free);
- INIT_LIST_HEAD(&info->tx_urbs_submitted);
-
- for (j = 0; j < urb_pool_size; j++) {
- urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb) {
- dev_err(&port->dev, "No free urbs available\n");
- goto no_rx_urb;
- }
- buf_size = port->read_urb->transfer_buffer_length;
- urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL);
- if (!urb->transfer_buffer) {
- dev_err(&port->dev,
- "Couldn't allocate urb buffer\n");
- goto no_rx_buf;
- }
- wrap = kmalloc(sizeof(*wrap), GFP_KERNEL);
- if (!wrap) {
- dev_err(&port->dev,
- "Couldn't allocate urb wrapper\n");
- goto no_rx_wrap;
- }
- usb_fill_bulk_urb(urb, serial->dev,
- usb_rcvbulkpipe(serial->dev,
- port->bulk_in_endpointAddress),
- urb->transfer_buffer, buf_size,
- whiteheat_read_callback, port);
- wrap->urb = urb;
- list_add(&wrap->list, &info->rx_urbs_free);
-
- urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb) {
- dev_err(&port->dev, "No free urbs available\n");
- goto no_tx_urb;
- }
- buf_size = port->write_urb->transfer_buffer_length;
- urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL);
- if (!urb->transfer_buffer) {
- dev_err(&port->dev,
- "Couldn't allocate urb buffer\n");
- goto no_tx_buf;
- }
- wrap = kmalloc(sizeof(*wrap), GFP_KERNEL);
- if (!wrap) {
- dev_err(&port->dev,
- "Couldn't allocate urb wrapper\n");
- goto no_tx_wrap;
- }
- usb_fill_bulk_urb(urb, serial->dev,
- usb_sndbulkpipe(serial->dev,
- port->bulk_out_endpointAddress),
- urb->transfer_buffer, buf_size,
- whiteheat_write_callback, port);
- wrap->urb = urb;
- list_add(&wrap->list, &info->tx_urbs_free);
- }
-
- usb_set_serial_port_data(port, info);
- }
-
command_info = kmalloc(sizeof(struct whiteheat_command_private),
GFP_KERNEL);
- if (command_info == NULL) {
- dev_err(&serial->dev->dev,
- "%s: Out of memory for port structures\n",
- serial->type->description);
+ if (!command_info)
goto no_command_private;
- }
mutex_init(&command_info->mutex);
command_info->port_running = 0;
@@ -576,39 +313,10 @@ no_firmware:
"%s: please contact support@connecttech.com\n",
serial->type->description);
kfree(result);
+ kfree(command);
return -ENODEV;
no_command_private:
- for (i = serial->num_ports - 1; i >= 0; i--) {
- port = serial->port[i];
- info = usb_get_serial_port_data(port);
- for (j = urb_pool_size - 1; j >= 0; j--) {
- tmp = list_first(&info->tx_urbs_free);
- list_del(tmp);
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- kfree(wrap);
-no_tx_wrap:
- kfree(urb->transfer_buffer);
-no_tx_buf:
- usb_free_urb(urb);
-no_tx_urb:
- tmp = list_first(&info->rx_urbs_free);
- list_del(tmp);
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- kfree(wrap);
-no_rx_wrap:
- kfree(urb->transfer_buffer);
-no_rx_buf:
- usb_free_urb(urb);
-no_rx_urb:
- ;
- }
- kfree(info);
-no_private:
- ;
- }
kfree(result);
no_result_buffer:
kfree(command);
@@ -616,60 +324,46 @@ no_command_buffer:
return -ENOMEM;
}
-
static void whiteheat_release(struct usb_serial *serial)
{
struct usb_serial_port *command_port;
- struct usb_serial_port *port;
- struct whiteheat_private *info;
- struct whiteheat_urb_wrap *wrap;
- struct urb *urb;
- struct list_head *tmp;
- struct list_head *tmp2;
- int i;
-
- dbg("%s", __func__);
/* free up our private data for our command port */
command_port = serial->port[COMMAND_PORT];
kfree(usb_get_serial_port_data(command_port));
+}
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- info = usb_get_serial_port_data(port);
- list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) {
- list_del(tmp);
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- kfree(wrap);
- kfree(urb->transfer_buffer);
- usb_free_urb(urb);
- }
- list_for_each_safe(tmp, tmp2, &info->tx_urbs_free) {
- list_del(tmp);
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- kfree(wrap);
- kfree(urb->transfer_buffer);
- usb_free_urb(urb);
- }
- kfree(info);
- }
+static int whiteheat_port_probe(struct usb_serial_port *port)
+{
+ struct whiteheat_private *info;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ usb_set_serial_port_data(port, info);
+
+ return 0;
}
-static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
+static int whiteheat_port_remove(struct usb_serial_port *port)
{
- int retval = 0;
+ struct whiteheat_private *info;
+
+ info = usb_get_serial_port_data(port);
+ kfree(info);
+
+ return 0;
+}
- dbg("%s - port %d", __func__, port->number);
+static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
+{
+ int retval;
retval = start_command_port(port->serial);
if (retval)
goto exit;
- if (tty)
- tty->low_latency = 1;
-
/* send an open port command */
retval = firm_open(port);
if (retval) {
@@ -691,156 +385,33 @@ static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
usb_clear_halt(port->serial->dev, port->read_urb->pipe);
usb_clear_halt(port->serial->dev, port->write_urb->pipe);
- /* Start reading from the device */
- retval = start_port_read(port);
+ retval = usb_serial_generic_open(tty, port);
if (retval) {
- dev_err(&port->dev,
- "%s - failed submitting read urb, error %d\n",
- __func__, retval);
firm_close(port);
stop_command_port(port->serial);
goto exit;
}
-
exit:
- dbg("%s - exit, retval = %d", __func__, retval);
return retval;
}
static void whiteheat_close(struct usb_serial_port *port)
{
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- struct whiteheat_urb_wrap *wrap;
- struct urb *urb;
- struct list_head *tmp;
- struct list_head *tmp2;
-
- dbg("%s - port %d", __func__, port->number);
-
firm_report_tx_done(port);
firm_close(port);
- /* shutdown our bulk reads and writes */
- mutex_lock(&info->deathwarrant);
- spin_lock_irq(&info->lock);
- list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- list_del(tmp);
- spin_unlock_irq(&info->lock);
- usb_kill_urb(urb);
- spin_lock_irq(&info->lock);
- list_add(tmp, &info->rx_urbs_free);
- }
- list_for_each_safe(tmp, tmp2, &info->rx_urb_q)
- list_move(tmp, &info->rx_urbs_free);
- list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) {
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- list_del(tmp);
- spin_unlock_irq(&info->lock);
- usb_kill_urb(urb);
- spin_lock_irq(&info->lock);
- list_add(tmp, &info->tx_urbs_free);
- }
- spin_unlock_irq(&info->lock);
- mutex_unlock(&info->deathwarrant);
- stop_command_port(port->serial);
-}
-
-
-static int whiteheat_write(struct tty_struct *tty,
- struct usb_serial_port *port, const unsigned char *buf, int count)
-{
- struct usb_serial *serial = port->serial;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- struct whiteheat_urb_wrap *wrap;
- struct urb *urb;
- int result;
- int bytes;
- int sent = 0;
- unsigned long flags;
- struct list_head *tmp;
-
- dbg("%s - port %d", __func__, port->number);
+ usb_serial_generic_close(port);
- if (count == 0) {
- dbg("%s - write request of 0 bytes", __func__);
- return (0);
- }
-
- while (count) {
- spin_lock_irqsave(&info->lock, flags);
- if (list_empty(&info->tx_urbs_free)) {
- spin_unlock_irqrestore(&info->lock, flags);
- break;
- }
- tmp = list_first(&info->tx_urbs_free);
- list_del(tmp);
- spin_unlock_irqrestore(&info->lock, flags);
-
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- bytes = (count > port->bulk_out_size) ?
- port->bulk_out_size : count;
- memcpy(urb->transfer_buffer, buf + sent, bytes);
-
- usb_serial_debug_data(debug, &port->dev,
- __func__, bytes, urb->transfer_buffer);
-
- urb->dev = serial->dev;
- urb->transfer_buffer_length = bytes;
- result = usb_submit_urb(urb, GFP_ATOMIC);
- if (result) {
- dev_err(&port->dev,
- "%s - failed submitting write urb, error %d\n",
- __func__, result);
- sent = result;
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->tx_urbs_free);
- spin_unlock_irqrestore(&info->lock, flags);
- break;
- } else {
- sent += bytes;
- count -= bytes;
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->tx_urbs_submitted);
- spin_unlock_irqrestore(&info->lock, flags);
- }
- }
-
- return sent;
-}
-
-static int whiteheat_write_room(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- struct list_head *tmp;
- int room = 0;
- unsigned long flags;
-
- dbg("%s - port %d", __func__, port->number);
-
- spin_lock_irqsave(&info->lock, flags);
- list_for_each(tmp, &info->tx_urbs_free)
- room++;
- spin_unlock_irqrestore(&info->lock, flags);
- room *= port->bulk_out_size;
-
- dbg("%s - returns %d", __func__, room);
- return (room);
+ stop_command_port(port->serial);
}
-static int whiteheat_tiocmget(struct tty_struct *tty, struct file *file)
+static int whiteheat_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
unsigned int modem_signals = 0;
- dbg("%s - port %d", __func__, port->number);
-
firm_get_dtr_rts(port);
if (info->mcr & UART_MCR_DTR)
modem_signals |= TIOCM_DTR;
@@ -850,14 +421,12 @@ static int whiteheat_tiocmget(struct tty_struct *tty, struct file *file)
return modem_signals;
}
-static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file,
+static int whiteheat_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
-
if (set & TIOCM_RTS)
info->mcr |= UART_MCR_RTS;
if (set & TIOCM_DTR)
@@ -874,23 +443,21 @@ static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file,
}
-static int whiteheat_ioctl(struct tty_struct *tty, struct file *file,
+static int whiteheat_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
struct serial_struct serstruct;
void __user *user_arg = (void __user *)arg;
- dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
-
switch (cmd) {
case TIOCGSERIAL:
memset(&serstruct, 0, sizeof(serstruct));
serstruct.type = PORT_16654;
- serstruct.line = port->serial->minor;
- serstruct.port = port->number;
+ serstruct.line = port->minor;
+ serstruct.port = port->port_number;
serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
- serstruct.xmit_fifo_size = port->bulk_out_size;
+ serstruct.xmit_fifo_size = kfifo_size(&port->write_fifo);
serstruct.custom_divisor = 0;
serstruct.baud_base = 460800;
serstruct.close_delay = CLOSING_DELAY;
@@ -920,60 +487,6 @@ static void whiteheat_break_ctl(struct tty_struct *tty, int break_state)
}
-static int whiteheat_chars_in_buffer(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- struct list_head *tmp;
- struct whiteheat_urb_wrap *wrap;
- int chars = 0;
- unsigned long flags;
-
- dbg("%s - port %d", __func__, port->number);
-
- spin_lock_irqsave(&info->lock, flags);
- list_for_each(tmp, &info->tx_urbs_submitted) {
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- chars += wrap->urb->transfer_buffer_length;
- }
- spin_unlock_irqrestore(&info->lock, flags);
-
- dbg("%s - returns %d", __func__, chars);
- return chars;
-}
-
-
-static void whiteheat_throttle(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
-
- dbg("%s - port %d", __func__, port->number);
-
- spin_lock_irq(&info->lock);
- info->flags |= THROTTLED;
- spin_unlock_irq(&info->lock);
-}
-
-
-static void whiteheat_unthrottle(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- int actually_throttled;
-
- dbg("%s - port %d", __func__, port->number);
-
- spin_lock_irq(&info->lock);
- actually_throttled = info->flags & ACTUALLY_THROTTLED;
- info->flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
- spin_unlock_irq(&info->lock);
-
- if (actually_throttled)
- rx_data_softint(&info->rx_work);
-}
-
-
/*****************************************************************************
* Connect Tech's White Heat callback routines
*****************************************************************************/
@@ -981,10 +494,8 @@ static void command_port_write_callback(struct urb *urb)
{
int status = urb->status;
- dbg("%s", __func__);
-
if (status) {
- dbg("nonzero urb status: %d", status);
+ dev_dbg(&urb->dev->dev, "nonzero urb status: %d\n", status);
return;
}
}
@@ -998,23 +509,20 @@ static void command_port_read_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int result;
- dbg("%s", __func__);
-
command_info = usb_get_serial_port_data(command_port);
if (!command_info) {
- dbg("%s - command_info is NULL, exiting.", __func__);
+ dev_dbg(&urb->dev->dev, "%s - command_info is NULL, exiting.\n", __func__);
return;
}
if (status) {
- dbg("%s - nonzero urb status: %d", __func__, status);
+ dev_dbg(&urb->dev->dev, "%s - nonzero urb status: %d\n", __func__, status);
if (status != -ENOENT)
command_info->command_finished = WHITEHEAT_CMD_FAILURE;
wake_up(&command_info->wait_command);
return;
}
- usb_serial_debug_data(debug, &command_port->dev,
- __func__, urb->actual_length, data);
+ usb_serial_debug_data(&command_port->dev, __func__, urb->actual_length, data);
if (data[0] == WHITEHEAT_CMD_COMPLETE) {
command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
@@ -1025,98 +533,23 @@ static void command_port_read_callback(struct urb *urb)
} else if (data[0] == WHITEHEAT_EVENT) {
/* These are unsolicited reports from the firmware, hence no
waiting command to wakeup */
- dbg("%s - event received", __func__);
+ dev_dbg(&urb->dev->dev, "%s - event received\n", __func__);
} else if (data[0] == WHITEHEAT_GET_DTR_RTS) {
memcpy(command_info->result_buffer, &data[1],
urb->actual_length - 1);
command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
wake_up(&command_info->wait_command);
} else
- dbg("%s - bad reply from firmware", __func__);
+ dev_dbg(&urb->dev->dev, "%s - bad reply from firmware\n", __func__);
/* Continue trying to always read */
- command_port->read_urb->dev = command_port->serial->dev;
result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC);
if (result)
- dbg("%s - failed resubmitting read urb, error %d",
+ dev_dbg(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n",
__func__, result);
}
-static void whiteheat_read_callback(struct urb *urb)
-{
- struct usb_serial_port *port = urb->context;
- struct whiteheat_urb_wrap *wrap;
- unsigned char *data = urb->transfer_buffer;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- int status = urb->status;
-
- dbg("%s - port %d", __func__, port->number);
-
- spin_lock(&info->lock);
- wrap = urb_to_wrap(urb, &info->rx_urbs_submitted);
- if (!wrap) {
- spin_unlock(&info->lock);
- dev_err(&port->dev, "%s - Not my urb!\n", __func__);
- return;
- }
- list_del(&wrap->list);
- spin_unlock(&info->lock);
-
- if (status) {
- dbg("%s - nonzero read bulk status received: %d",
- __func__, status);
- spin_lock(&info->lock);
- list_add(&wrap->list, &info->rx_urbs_free);
- spin_unlock(&info->lock);
- return;
- }
-
- usb_serial_debug_data(debug, &port->dev,
- __func__, urb->actual_length, data);
-
- spin_lock(&info->lock);
- list_add_tail(&wrap->list, &info->rx_urb_q);
- if (info->flags & THROTTLED) {
- info->flags |= ACTUALLY_THROTTLED;
- spin_unlock(&info->lock);
- return;
- }
- spin_unlock(&info->lock);
-
- schedule_work(&info->rx_work);
-}
-
-
-static void whiteheat_write_callback(struct urb *urb)
-{
- struct usb_serial_port *port = urb->context;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- struct whiteheat_urb_wrap *wrap;
- int status = urb->status;
-
- dbg("%s - port %d", __func__, port->number);
-
- spin_lock(&info->lock);
- wrap = urb_to_wrap(urb, &info->tx_urbs_submitted);
- if (!wrap) {
- spin_unlock(&info->lock);
- dev_err(&port->dev, "%s - Not my urb!\n", __func__);
- return;
- }
- list_move(&wrap->list, &info->tx_urbs_free);
- spin_unlock(&info->lock);
-
- if (status) {
- dbg("%s - nonzero write bulk status received: %d",
- __func__, status);
- return;
- }
-
- usb_serial_port_softint(port);
-}
-
-
/*****************************************************************************
* Connect Tech's White Heat firmware interface
*****************************************************************************/
@@ -1126,11 +559,12 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command,
struct usb_serial_port *command_port;
struct whiteheat_command_private *command_info;
struct whiteheat_private *info;
+ struct device *dev = &port->dev;
__u8 *transfer_buffer;
int retval = 0;
int t;
- dbg("%s - command %d", __func__, command);
+ dev_dbg(dev, "%s - command %d\n", __func__, command);
command_port = port->serial->port[COMMAND_PORT];
command_info = usb_get_serial_port_data(command_port);
@@ -1141,10 +575,9 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command,
transfer_buffer[0] = command;
memcpy(&transfer_buffer[1], data, datasize);
command_port->write_urb->transfer_buffer_length = datasize + 1;
- command_port->write_urb->dev = port->serial->dev;
retval = usb_submit_urb(command_port->write_urb, GFP_NOIO);
if (retval) {
- dbg("%s - submit urb failed", __func__);
+ dev_dbg(dev, "%s - submit urb failed\n", __func__);
goto exit;
}
@@ -1155,19 +588,19 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command,
usb_kill_urb(command_port->write_urb);
if (command_info->command_finished == false) {
- dbg("%s - command timed out.", __func__);
+ dev_dbg(dev, "%s - command timed out.\n", __func__);
retval = -ETIMEDOUT;
goto exit;
}
if (command_info->command_finished == WHITEHEAT_CMD_FAILURE) {
- dbg("%s - command failed.", __func__);
+ dev_dbg(dev, "%s - command failed.\n", __func__);
retval = -EIO;
goto exit;
}
if (command_info->command_finished == WHITEHEAT_CMD_COMPLETE) {
- dbg("%s - command completed.", __func__);
+ dev_dbg(dev, "%s - command completed.\n", __func__);
switch (command) {
case WHITEHEAT_GET_DTR_RTS:
info = usb_get_serial_port_data(port);
@@ -1186,7 +619,7 @@ static int firm_open(struct usb_serial_port *port)
{
struct whiteheat_simple open_command;
- open_command.port = port->number - port->serial->minor + 1;
+ open_command.port = port->port_number + 1;
return firm_send_command(port, WHITEHEAT_OPEN,
(__u8 *)&open_command, sizeof(open_command));
}
@@ -1196,7 +629,7 @@ static int firm_close(struct usb_serial_port *port)
{
struct whiteheat_simple close_command;
- close_command.port = port->number - port->serial->minor + 1;
+ close_command.port = port->port_number + 1;
return firm_send_command(port, WHITEHEAT_CLOSE,
(__u8 *)&close_command, sizeof(close_command));
}
@@ -1205,10 +638,11 @@ static int firm_close(struct usb_serial_port *port)
static void firm_setup_port(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
+ struct device *dev = &port->dev;
struct whiteheat_port_settings port_settings;
- unsigned int cflag = tty->termios->c_cflag;
+ unsigned int cflag = tty->termios.c_cflag;
- port_settings.port = port->number + 1;
+ port_settings.port = port->port_number + 1;
/* get the byte size */
switch (cflag & CSIZE) {
@@ -1218,7 +652,7 @@ static void firm_setup_port(struct tty_struct *tty)
default:
case CS8: port_settings.bits = 8; break;
}
- dbg("%s - data bits = %d", __func__, port_settings.bits);
+ dev_dbg(dev, "%s - data bits = %d\n", __func__, port_settings.bits);
/* determine the parity */
if (cflag & PARENB)
@@ -1234,14 +668,14 @@ static void firm_setup_port(struct tty_struct *tty)
port_settings.parity = WHITEHEAT_PAR_EVEN;
else
port_settings.parity = WHITEHEAT_PAR_NONE;
- dbg("%s - parity = %c", __func__, port_settings.parity);
+ dev_dbg(dev, "%s - parity = %c\n", __func__, port_settings.parity);
/* figure out the stop bits requested */
if (cflag & CSTOPB)
port_settings.stop = 2;
else
port_settings.stop = 1;
- dbg("%s - stop bits = %d", __func__, port_settings.stop);
+ dev_dbg(dev, "%s - stop bits = %d\n", __func__, port_settings.stop);
/* figure out the flow control settings */
if (cflag & CRTSCTS)
@@ -1249,7 +683,7 @@ static void firm_setup_port(struct tty_struct *tty)
WHITEHEAT_HFLOW_RTS);
else
port_settings.hflow = WHITEHEAT_HFLOW_NONE;
- dbg("%s - hardware flow control = %s %s %s %s", __func__,
+ dev_dbg(dev, "%s - hardware flow control = %s %s %s %s\n", __func__,
(port_settings.hflow & WHITEHEAT_HFLOW_CTS) ? "CTS" : "",
(port_settings.hflow & WHITEHEAT_HFLOW_RTS) ? "RTS" : "",
(port_settings.hflow & WHITEHEAT_HFLOW_DSR) ? "DSR" : "",
@@ -1260,16 +694,15 @@ static void firm_setup_port(struct tty_struct *tty)
port_settings.sflow = WHITEHEAT_SFLOW_RXTX;
else
port_settings.sflow = WHITEHEAT_SFLOW_NONE;
- dbg("%s - software flow control = %c", __func__, port_settings.sflow);
+ dev_dbg(dev, "%s - software flow control = %c\n", __func__, port_settings.sflow);
port_settings.xon = START_CHAR(tty);
port_settings.xoff = STOP_CHAR(tty);
- dbg("%s - XON = %2x, XOFF = %2x",
- __func__, port_settings.xon, port_settings.xoff);
+ dev_dbg(dev, "%s - XON = %2x, XOFF = %2x\n", __func__, port_settings.xon, port_settings.xoff);
/* get the baud rate wanted */
port_settings.baud = tty_get_baud_rate(tty);
- dbg("%s - baud rate = %d", __func__, port_settings.baud);
+ dev_dbg(dev, "%s - baud rate = %d\n", __func__, port_settings.baud);
/* fixme: should set validated settings */
tty_encode_baud_rate(tty, port_settings.baud, port_settings.baud);
@@ -1286,7 +719,7 @@ static int firm_set_rts(struct usb_serial_port *port, __u8 onoff)
{
struct whiteheat_set_rdb rts_command;
- rts_command.port = port->number - port->serial->minor + 1;
+ rts_command.port = port->port_number + 1;
rts_command.state = onoff;
return firm_send_command(port, WHITEHEAT_SET_RTS,
(__u8 *)&rts_command, sizeof(rts_command));
@@ -1297,7 +730,7 @@ static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff)
{
struct whiteheat_set_rdb dtr_command;
- dtr_command.port = port->number - port->serial->minor + 1;
+ dtr_command.port = port->port_number + 1;
dtr_command.state = onoff;
return firm_send_command(port, WHITEHEAT_SET_DTR,
(__u8 *)&dtr_command, sizeof(dtr_command));
@@ -1308,7 +741,7 @@ static int firm_set_break(struct usb_serial_port *port, __u8 onoff)
{
struct whiteheat_set_rdb break_command;
- break_command.port = port->number - port->serial->minor + 1;
+ break_command.port = port->port_number + 1;
break_command.state = onoff;
return firm_send_command(port, WHITEHEAT_SET_BREAK,
(__u8 *)&break_command, sizeof(break_command));
@@ -1319,7 +752,7 @@ static int firm_purge(struct usb_serial_port *port, __u8 rxtx)
{
struct whiteheat_purge purge_command;
- purge_command.port = port->number - port->serial->minor + 1;
+ purge_command.port = port->port_number + 1;
purge_command.what = rxtx;
return firm_send_command(port, WHITEHEAT_PURGE,
(__u8 *)&purge_command, sizeof(purge_command));
@@ -1330,7 +763,7 @@ static int firm_get_dtr_rts(struct usb_serial_port *port)
{
struct whiteheat_simple get_dr_command;
- get_dr_command.port = port->number - port->serial->minor + 1;
+ get_dr_command.port = port->port_number + 1;
return firm_send_command(port, WHITEHEAT_GET_DTR_RTS,
(__u8 *)&get_dr_command, sizeof(get_dr_command));
}
@@ -1340,7 +773,7 @@ static int firm_report_tx_done(struct usb_serial_port *port)
{
struct whiteheat_simple close_command;
- close_command.port = port->number - port->serial->minor + 1;
+ close_command.port = port->port_number + 1;
return firm_send_command(port, WHITEHEAT_REPORT_TX_DONE,
(__u8 *)&close_command, sizeof(close_command));
}
@@ -1362,7 +795,6 @@ static int start_command_port(struct usb_serial *serial)
/* Work around HCD bugs */
usb_clear_halt(serial->dev, command_port->read_urb->pipe);
- command_port->read_urb->dev = serial->dev;
retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL);
if (retval) {
dev_err(&serial->dev->dev,
@@ -1393,163 +825,7 @@ static void stop_command_port(struct usb_serial *serial)
mutex_unlock(&command_info->mutex);
}
-
-static int start_port_read(struct usb_serial_port *port)
-{
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- struct whiteheat_urb_wrap *wrap;
- struct urb *urb;
- int retval = 0;
- unsigned long flags;
- struct list_head *tmp;
- struct list_head *tmp2;
-
- spin_lock_irqsave(&info->lock, flags);
-
- list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) {
- list_del(tmp);
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- urb->dev = port->serial->dev;
- spin_unlock_irqrestore(&info->lock, flags);
- retval = usb_submit_urb(urb, GFP_KERNEL);
- if (retval) {
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->rx_urbs_free);
- list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- list_del(tmp);
- spin_unlock_irqrestore(&info->lock, flags);
- usb_kill_urb(urb);
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->rx_urbs_free);
- }
- break;
- }
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->rx_urbs_submitted);
- }
-
- spin_unlock_irqrestore(&info->lock, flags);
-
- return retval;
-}
-
-
-static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb,
- struct list_head *head)
-{
- struct whiteheat_urb_wrap *wrap;
- struct list_head *tmp;
-
- list_for_each(tmp, head) {
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- if (wrap->urb == urb)
- return wrap;
- }
-
- return NULL;
-}
-
-
-static struct list_head *list_first(struct list_head *head)
-{
- return head->next;
-}
-
-
-static void rx_data_softint(struct work_struct *work)
-{
- struct whiteheat_private *info =
- container_of(work, struct whiteheat_private, rx_work);
- struct usb_serial_port *port = info->port;
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- struct whiteheat_urb_wrap *wrap;
- struct urb *urb;
- unsigned long flags;
- struct list_head *tmp;
- struct list_head *tmp2;
- int result;
- int sent = 0;
-
- spin_lock_irqsave(&info->lock, flags);
- if (info->flags & THROTTLED) {
- spin_unlock_irqrestore(&info->lock, flags);
- goto out;
- }
-
- list_for_each_safe(tmp, tmp2, &info->rx_urb_q) {
- list_del(tmp);
- spin_unlock_irqrestore(&info->lock, flags);
-
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
-
- if (tty && urb->actual_length)
- sent += tty_insert_flip_string(tty,
- urb->transfer_buffer, urb->actual_length);
-
- urb->dev = port->serial->dev;
- result = usb_submit_urb(urb, GFP_ATOMIC);
- if (result) {
- dev_err(&port->dev,
- "%s - failed resubmitting read urb, error %d\n",
- __func__, result);
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->rx_urbs_free);
- continue;
- }
-
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->rx_urbs_submitted);
- }
- spin_unlock_irqrestore(&info->lock, flags);
-
- if (sent)
- tty_flip_buffer_push(tty);
-out:
- tty_kref_put(tty);
-}
-
-
-/*****************************************************************************
- * Connect Tech's White Heat module functions
- *****************************************************************************/
-static int __init whiteheat_init(void)
-{
- int retval;
- retval = usb_serial_register(&whiteheat_fake_device);
- if (retval)
- goto failed_fake_register;
- retval = usb_serial_register(&whiteheat_device);
- if (retval)
- goto failed_device_register;
- retval = usb_register(&whiteheat_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&whiteheat_device);
-failed_device_register:
- usb_serial_deregister(&whiteheat_fake_device);
-failed_fake_register:
- return retval;
-}
-
-
-static void __exit whiteheat_exit(void)
-{
- usb_deregister(&whiteheat_driver);
- usb_serial_deregister(&whiteheat_fake_device);
- usb_serial_deregister(&whiteheat_device);
-}
-
-
-module_init(whiteheat_init);
-module_exit(whiteheat_exit);
+module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
@@ -1557,9 +833,3 @@ MODULE_LICENSE("GPL");
MODULE_FIRMWARE("whiteheat.fw");
MODULE_FIRMWARE("whiteheat_loader.fw");
-
-module_param(urb_pool_size, int, 0);
-MODULE_PARM_DESC(urb_pool_size, "Number of urbs to use for buffering");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/wishbone-serial.c b/drivers/usb/serial/wishbone-serial.c
new file mode 100644
index 00000000000..4fed4a0bd70
--- /dev/null
+++ b/drivers/usb/serial/wishbone-serial.c
@@ -0,0 +1,94 @@
+/*
+ * USB Wishbone-Serial adapter driver
+ *
+ * Copyright (C) 2013 Wesley W. Terpstra <w.terpstra@gsi.de>
+ * Copyright (C) 2013 GSI Helmholtz Centre for Heavy Ion Research GmbH
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <linux/uaccess.h>
+
+#define GSI_VENDOR_OPENCLOSE 0xB0
+
+static const struct usb_device_id id_table[] = {
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1D50, 0x6062, 0xFF, 0xFF, 0xFF) },
+ { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/*
+ * Etherbone must be told that a new stream has begun before data arrives.
+ * This is necessary to restart the negotiation of Wishbone bus parameters.
+ * Similarly, when the stream ends, Etherbone must be told so that the cycle
+ * line can be driven low in the case that userspace failed to do so.
+ */
+static int usb_gsi_openclose(struct usb_serial_port *port, int value)
+{
+ struct usb_device *dev = port->serial->dev;
+
+ return usb_control_msg(
+ dev,
+ usb_sndctrlpipe(dev, 0), /* Send to EP0OUT */
+ GSI_VENDOR_OPENCLOSE,
+ USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
+ value, /* wValue = device is open(1) or closed(0) */
+ port->serial->interface->cur_altsetting->desc.bInterfaceNumber,
+ NULL, 0, /* There is no data stage */
+ 5000); /* Timeout till operation fails */
+}
+
+static int wishbone_serial_open(struct tty_struct *tty,
+ struct usb_serial_port *port)
+{
+ int retval;
+
+ retval = usb_gsi_openclose(port, 1);
+ if (retval) {
+ dev_err(&port->serial->dev->dev,
+ "Could not mark device as open (%d)\n",
+ retval);
+ return retval;
+ }
+
+ retval = usb_serial_generic_open(tty, port);
+ if (retval)
+ usb_gsi_openclose(port, 0);
+
+ return retval;
+}
+
+static void wishbone_serial_close(struct usb_serial_port *port)
+{
+ usb_serial_generic_close(port);
+ usb_gsi_openclose(port, 0);
+}
+
+static struct usb_serial_driver wishbone_serial_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "wishbone_serial",
+ },
+ .id_table = id_table,
+ .num_ports = 1,
+ .open = &wishbone_serial_open,
+ .close = &wishbone_serial_close,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+ &wishbone_serial_device, NULL
+};
+
+module_usb_serial_driver(serial_drivers, id_table);
+
+MODULE_AUTHOR("Wesley W. Terpstra <w.terpstra@gsi.de>");
+MODULE_DESCRIPTION("USB Wishbone-Serial adapter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/xsens_mt.c b/drivers/usb/serial/xsens_mt.c
new file mode 100644
index 00000000000..4841fb57400
--- /dev/null
+++ b/drivers/usb/serial/xsens_mt.c
@@ -0,0 +1,85 @@
+/*
+ * Xsens MT USB driver
+ *
+ * Copyright (C) 2013 Xsens <info@xsens.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <linux/uaccess.h>
+
+#define XSENS_VID 0x2639
+
+#define MTi_10_IMU_PID 0x0001
+#define MTi_20_VRU_PID 0x0002
+#define MTi_30_AHRS_PID 0x0003
+
+#define MTi_100_IMU_PID 0x0011
+#define MTi_200_VRU_PID 0x0012
+#define MTi_300_AHRS_PID 0x0013
+
+#define MTi_G_700_GPS_INS_PID 0x0017
+
+static const struct usb_device_id id_table[] = {
+ { USB_DEVICE(XSENS_VID, MTi_10_IMU_PID) },
+ { USB_DEVICE(XSENS_VID, MTi_20_VRU_PID) },
+ { USB_DEVICE(XSENS_VID, MTi_30_AHRS_PID) },
+
+ { USB_DEVICE(XSENS_VID, MTi_100_IMU_PID) },
+ { USB_DEVICE(XSENS_VID, MTi_200_VRU_PID) },
+ { USB_DEVICE(XSENS_VID, MTi_300_AHRS_PID) },
+
+ { USB_DEVICE(XSENS_VID, MTi_G_700_GPS_INS_PID) },
+ { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static int has_required_endpoints(const struct usb_host_interface *interface)
+{
+ __u8 i;
+ int has_bulk_in = 0;
+ int has_bulk_out = 0;
+
+ for (i = 0; i < interface->desc.bNumEndpoints; ++i) {
+ if (usb_endpoint_is_bulk_in(&interface->endpoint[i].desc))
+ has_bulk_in = 1;
+ else if (usb_endpoint_is_bulk_out(&interface->endpoint[i].desc))
+ has_bulk_out = 1;
+ }
+
+ return has_bulk_in && has_bulk_out;
+}
+
+static int xsens_mt_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
+{
+ if (!has_required_endpoints(serial->interface->cur_altsetting))
+ return -ENODEV;
+ return 0;
+}
+
+static struct usb_serial_driver xsens_mt_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "xsens_mt",
+ },
+ .id_table = id_table,
+ .num_ports = 1,
+
+ .probe = xsens_mt_probe,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+ &xsens_mt_device, NULL
+};
+
+module_usb_serial_driver(serial_drivers, id_table);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/zio.c b/drivers/usb/serial/zio.c
deleted file mode 100644
index f5796727883..00000000000
--- a/drivers/usb/serial/zio.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * ZIO Motherboard USB driver
- *
- * Copyright (C) 2010 Zilogic Systems <code@zilogic.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-#include <linux/uaccess.h>
-
-static const struct usb_device_id id_table[] = {
- { USB_DEVICE(0x1CBE, 0x0103) },
- { },
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static struct usb_driver zio_driver = {
- .name = "zio",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
-static struct usb_serial_driver zio_device = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "zio",
- },
- .id_table = id_table,
- .usb_driver = &zio_driver,
- .num_ports = 1,
-};
-
-static int __init zio_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&zio_device);
- if (retval)
- return retval;
- retval = usb_register(&zio_driver);
- if (retval)
- usb_serial_deregister(&zio_device);
- return retval;
-}
-
-static void __exit zio_exit(void)
-{
- usb_deregister(&zio_driver);
- usb_serial_deregister(&zio_device);
-}
-
-module_init(zio_init);
-module_exit(zio_exit);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/zte_ev.c b/drivers/usb/serial/zte_ev.c
new file mode 100644
index 00000000000..e40ab739c4a
--- /dev/null
+++ b/drivers/usb/serial/zte_ev.c
@@ -0,0 +1,317 @@
+/*
+ * ZTE_EV USB serial driver
+ *
+ * Copyright (C) 2012 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+ * Copyright (C) 2012 Linux Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This driver is based on code found in a ZTE_ENV patch that modified
+ * the usb-serial generic driver. Comments were left in that I think
+ * show the commands used to talk to the device, but I am not sure.
+ */
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <linux/uaccess.h>
+
+#define MAX_SETUP_DATA_SIZE 32
+
+static void debug_data(struct device *dev, const char *function, int len,
+ const unsigned char *data, int result)
+{
+ dev_dbg(dev, "result = %d\n", result);
+ if (result == len)
+ dev_dbg(dev, "%s - length = %d, data = %*ph\n", function,
+ len, len, data);
+}
+
+static int zte_ev_usb_serial_open(struct tty_struct *tty,
+ struct usb_serial_port *port)
+{
+ struct usb_device *udev = port->serial->dev;
+ struct device *dev = &port->dev;
+ int result = 0;
+ int len;
+ unsigned char *buf;
+
+ buf = kmalloc(MAX_SETUP_DATA_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* send 1st ctl cmd(CTL 21 22 01 00 00 00 00 00) */
+ len = 0;
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x22, 0x21,
+ 0x0001, 0x0000, NULL, len,
+ USB_CTRL_GET_TIMEOUT);
+ dev_dbg(dev, "result = %d\n", result);
+
+ /* send 2st cmd and receive data */
+ /*
+ * 16.0 CTL a1 21 00 00 00 00 07 00 CLASS 25.1.0(5)
+ * 16.0 DI 00 96 00 00 00 00 08
+ */
+ len = 0x0007;
+ result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ 0x21, 0xa1,
+ 0x0000, 0x0000, buf, len,
+ USB_CTRL_GET_TIMEOUT);
+ debug_data(dev, __func__, len, buf, result);
+
+ /* send 3rd cmd */
+ /*
+ * 16.0 CTL 21 20 00 00 00 00 07 00 CLASS 30.1.0
+ * 16.0 DO 80 25 00 00 00 00 08 .%..... 30.2.0
+ */
+ len = 0x0007;
+ buf[0] = 0x80;
+ buf[1] = 0x25;
+ buf[2] = 0x00;
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+ buf[5] = 0x00;
+ buf[6] = 0x08;
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x20, 0x21,
+ 0x0000, 0x0000, buf, len,
+ USB_CTRL_GET_TIMEOUT);
+ debug_data(dev, __func__, len, buf, result);
+
+ /* send 4th cmd */
+ /*
+ * 16.0 CTL 21 22 03 00 00 00 00 00
+ */
+ len = 0;
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x22, 0x21,
+ 0x0003, 0x0000, NULL, len,
+ USB_CTRL_GET_TIMEOUT);
+ dev_dbg(dev, "result = %d\n", result);
+
+ /* send 5th cmd */
+ /*
+ * 16.0 CTL a1 21 00 00 00 00 07 00 CLASS 33.1.0
+ * 16.0 DI 80 25 00 00 00 00 08
+ */
+ len = 0x0007;
+ result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ 0x21, 0xa1,
+ 0x0000, 0x0000, buf, len,
+ USB_CTRL_GET_TIMEOUT);
+ debug_data(dev, __func__, len, buf, result);
+
+ /* send 6th cmd */
+ /*
+ * 16.0 CTL 21 20 00 00 00 00 07 00 CLASS 34.1.0
+ * 16.0 DO 80 25 00 00 00 00 08
+ */
+ len = 0x0007;
+ buf[0] = 0x80;
+ buf[1] = 0x25;
+ buf[2] = 0x00;
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+ buf[5] = 0x00;
+ buf[6] = 0x08;
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x20, 0x21,
+ 0x0000, 0x0000, buf, len,
+ USB_CTRL_GET_TIMEOUT);
+ debug_data(dev, __func__, len, buf, result);
+ kfree(buf);
+
+ return usb_serial_generic_open(tty, port);
+}
+
+/*
+ * CTL 21 22 02 00 00 00 00 00 CLASS 338.1.0
+ *
+ * 16.1 DI a1 20 00 00 00 00 02 00 02 00 . ........ 340.1.0
+ * 16.0 CTL 21 22 03 00 00 00 00 00 CLASS 341.1.0
+ *
+ * 16.0 CTL a1 21 00 00 00 00 07 00 CLASS 346.1.0(3)
+ * 16.0 DI 00 08 07 00 00 00 08 ....... 346.2.0
+ *
+ * 16.0 CTL 21 20 00 00 00 00 07 00 CLASS 349.1.0
+ * 16.0 DO 00 c2 01 00 00 00 08 ....... 349.2.0
+ *
+ * 16.0 CTL 21 22 03 00 00 00 00 00 CLASS 350.1.0(2)
+ *
+ * 16.0 CTL a1 21 00 00 00 00 07 00 CLASS 352.1.0
+ * 16.0 DI 00 c2 01 00 00 00 08 ....... 352.2.0
+ *
+ * 16.1 DI a1 20 00 00 00 00 02 00 02 00 . ........ 353.1.0
+ *
+ * 16.0 CTL 21 20 00 00 00 00 07 00 CLASS 354.1.0
+ * 16.0 DO 00 c2 01 00 00 00 08 ....... 354.2.0
+ *
+ * 16.0 CTL 21 22 03 00 00 00 00 00
+*/
+
+static void zte_ev_usb_serial_close(struct usb_serial_port *port)
+{
+ struct usb_device *udev = port->serial->dev;
+ struct device *dev = &port->dev;
+ int result = 0;
+ int len;
+ unsigned char *buf;
+
+ buf = kmalloc(MAX_SETUP_DATA_SIZE, GFP_KERNEL);
+ if (!buf)
+ return;
+
+ /* send 1st ctl cmd(CTL 21 22 02 00 00 00 00 00) */
+ len = 0;
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x22, 0x21,
+ 0x0002, 0x0000, NULL, len,
+ USB_CTRL_GET_TIMEOUT);
+ dev_dbg(dev, "result = %d\n", result);
+
+ /* send 2st ctl cmd(CTL 21 22 03 00 00 00 00 00 ) */
+ len = 0;
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x22, 0x21,
+ 0x0003, 0x0000, NULL, len,
+ USB_CTRL_GET_TIMEOUT);
+ dev_dbg(dev, "result = %d\n", result);
+
+ /* send 3st cmd and recieve data */
+ /*
+ * 16.0 CTL a1 21 00 00 00 00 07 00 CLASS 25.1.0(5)
+ * 16.0 DI 00 08 07 00 00 00 08
+ */
+ len = 0x0007;
+ result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ 0x21, 0xa1,
+ 0x0000, 0x0000, buf, len,
+ USB_CTRL_GET_TIMEOUT);
+ debug_data(dev, __func__, len, buf, result);
+
+ /* send 4th cmd */
+ /*
+ * 16.0 CTL 21 20 00 00 00 00 07 00 CLASS 30.1.0
+ * 16.0 DO 00 c2 01 00 00 00 08 .%..... 30.2.0
+ */
+ len = 0x0007;
+ buf[0] = 0x00;
+ buf[1] = 0xc2;
+ buf[2] = 0x01;
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+ buf[5] = 0x00;
+ buf[6] = 0x08;
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x20, 0x21,
+ 0x0000, 0x0000, buf, len,
+ USB_CTRL_GET_TIMEOUT);
+ debug_data(dev, __func__, len, buf, result);
+
+ /* send 5th cmd */
+ /*
+ * 16.0 CTL 21 22 03 00 00 00 00 00
+ */
+ len = 0;
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x22, 0x21,
+ 0x0003, 0x0000, NULL, len,
+ USB_CTRL_GET_TIMEOUT);
+ dev_dbg(dev, "result = %d\n", result);
+
+ /* send 6th cmd */
+ /*
+ * 16.0 CTL a1 21 00 00 00 00 07 00 CLASS 33.1.0
+ * 16.0 DI 00 c2 01 00 00 00 08
+ */
+ len = 0x0007;
+ result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ 0x21, 0xa1,
+ 0x0000, 0x0000, buf, len,
+ USB_CTRL_GET_TIMEOUT);
+ debug_data(dev, __func__, len, buf, result);
+
+ /* send 7th cmd */
+ /*
+ * 16.0 CTL 21 20 00 00 00 00 07 00 CLASS 354.1.0
+ * 16.0 DO 00 c2 01 00 00 00 08 ....... 354.2.0
+ */
+ len = 0x0007;
+ buf[0] = 0x00;
+ buf[1] = 0xc2;
+ buf[2] = 0x01;
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+ buf[5] = 0x00;
+ buf[6] = 0x08;
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x20, 0x21,
+ 0x0000, 0x0000, buf, len,
+ USB_CTRL_GET_TIMEOUT);
+ debug_data(dev, __func__, len, buf, result);
+
+ /* send 8th cmd */
+ /*
+ * 16.0 CTL 21 22 03 00 00 00 00 00
+ */
+ len = 0;
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x22, 0x21,
+ 0x0003, 0x0000, NULL, len,
+ USB_CTRL_GET_TIMEOUT);
+ dev_dbg(dev, "result = %d\n", result);
+
+ kfree(buf);
+
+ usb_serial_generic_close(port);
+}
+
+static const struct usb_device_id id_table[] = {
+ /* AC8710, AC8710T */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffff, 0xff, 0xff, 0xff) },
+ /* AC8700 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfffe, 0xff, 0xff, 0xff) },
+ /* MG880 */
+ { USB_DEVICE(0x19d2, 0xfffd) },
+ { USB_DEVICE(0x19d2, 0xfffc) },
+ { USB_DEVICE(0x19d2, 0xfffb) },
+ /* AC8710_V3 */
+ { USB_DEVICE(0x19d2, 0xfff6) },
+ { USB_DEVICE(0x19d2, 0xfff7) },
+ { USB_DEVICE(0x19d2, 0xfff8) },
+ { USB_DEVICE(0x19d2, 0xfff9) },
+ { USB_DEVICE(0x19d2, 0xffee) },
+ /* AC2716, MC2716 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffed, 0xff, 0xff, 0xff) },
+ /* AD3812 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffeb, 0xff, 0xff, 0xff) },
+ { USB_DEVICE(0x19d2, 0xffec) },
+ { USB_DEVICE(0x05C6, 0x3197) },
+ { USB_DEVICE(0x05C6, 0x6000) },
+ { USB_DEVICE(0x05C6, 0x9008) },
+ { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_serial_driver zio_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "zte_ev",
+ },
+ .id_table = id_table,
+ .num_ports = 1,
+ .open = zte_ev_usb_serial_open,
+ .close = zte_ev_usb_serial_close,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+ &zio_device, NULL
+};
+
+module_usb_serial_driver(serial_drivers, id_table);
+MODULE_LICENSE("GPL v2");