Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
U
USB Relay Box 1
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
USB Relay Box 1
Commits
9da7e1fb
Commit
9da7e1fb
authored
Aug 09, 2019
by
Dimitris Lampridis
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[sw] update driver to latest Linux kernel upstream source (b678c56). It now includes GPIO support.
parent
2c2988f8
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1295 additions
and
423 deletions
+1295
-423
.gitignore
sw/cp210x-driver/.gitignore
+4
-0
cp210x.c
sw/cp210x-driver/cp210x.c
+1291
-423
No files found.
sw/cp210x-driver/.gitignore
0 → 100644
View file @
9da7e1fb
*
!.gitignore
!cp210x.c
!Makefile
sw/cp210x-driver/cp210x.c
View file @
9da7e1fb
// SPDX-License-Identifier: GPL-2.0
/*
* Silicon Laboratories CP210x USB to RS232 serial adaptor driver
*
* Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk)
*
* 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.
*
* Support to set flow control line levels using TIOCMGET and TIOCMSET
* thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow
* control thanks to Munir Nassar nassarmu@real-time.com
...
...
@@ -23,11 +20,10 @@
#include <linux/usb.h>
#include <linux/uaccess.h>
#include <linux/usb/serial.h>
#include <linux/gpio/driver.h>
#include <linux/bitops.h>
#include <linux/mutex.h>
/*
* Version Information
*/
#define DRIVER_VERSION "v0.09"
#define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver"
/*
...
...
@@ -35,40 +31,43 @@
*/
static
int
cp210x_open
(
struct
tty_struct
*
tty
,
struct
usb_serial_port
*
);
static
void
cp210x_close
(
struct
usb_serial_port
*
);
static
int
cp210x_ioctl
(
struct
tty_struct
*
tty
,
unsigned
int
cmd
,
unsigned
long
arg
);
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
in
t
*
cflagp
,
unsigned
int
*
baudp
);
tcflag_
t
*
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
bool
cp210x_tx_empty
(
struct
usb_serial_port
*
port
);
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
int
cp210x_attach
(
struct
usb_serial
*
);
static
void
cp210x_disconnect
(
struct
usb_serial
*
);
static
void
cp210x_release
(
struct
usb_serial
*
);
static
int
cp210x_port_probe
(
struct
usb_serial_port
*
);
static
int
cp210x_port_remove
(
struct
usb_serial_port
*
);
static
void
cp210x_dtr_rts
(
struct
usb_serial_port
*
p
,
int
on
);
static
bool
debug
;
static
const
struct
usb_device_id
id_table
[]
=
{
{
USB_DEVICE
(
0x045B
,
0x0053
)
},
/* Renesas RX610 RX-Stick */
{
USB_DEVICE
(
0x0471
,
0x066A
)
},
/* AKTAKOM ACE-1001 cable */
{
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
(
0x0908
,
0x01FF
)
},
/* Siemens RUGGEDCOM USB Serial Console */
{
USB_DEVICE
(
0x0B00
,
0x3070
)
},
/* Ingenico 3070 */
{
USB_DEVICE
(
0x0BED
,
0x1100
)
},
/* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */
{
USB_DEVICE
(
0x0BED
,
0x1101
)
},
/* MEI series 2000 Combo Acceptor */
{
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,9 +80,11 @@ static const struct usb_device_id id_table[] = {
{
USB_DEVICE
(
0x10C4
,
0x804E
)
},
/* Software Bisque Paramount ME build-in converter */
{
USB_DEVICE
(
0x10C4
,
0x8053
)
},
/* Enfora EDG1228 */
{
USB_DEVICE
(
0x10C4
,
0x8054
)
},
/* Enfora GSM2228 */
{
USB_DEVICE
(
0x10C4
,
0x8056
)
},
/* Lorenz Messtechnik devices */
{
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 */
...
...
@@ -92,8 +93,13 @@ static const struct usb_device_id id_table[] = {
{
USB_DEVICE
(
0x10C4
,
0x813F
)
},
/* Tams Master Easy Control */
{
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
,
0x817C
)
},
/* CESINEL MEDCAL N Power Quality Monitor */
{
USB_DEVICE
(
0x10C4
,
0x817D
)
},
/* CESINEL MEDCAL NT Power Quality Monitor */
{
USB_DEVICE
(
0x10C4
,
0x817E
)
},
/* CESINEL MEDCAL S Power Quality Monitor */
{
USB_DEVICE
(
0x10C4
,
0x818B
)
},
/* AVIT Research USB to TTL */
{
USB_DEVICE
(
0x10C4
,
0x819F
)
},
/* MJS USB Toslink Switcher */
{
USB_DEVICE
(
0x10C4
,
0x81A6
)
},
/* ThinkOptics WavIt */
...
...
@@ -101,6 +107,7 @@ static const struct usb_device_id id_table[] = {
{
USB_DEVICE
(
0x10C4
,
0x81AC
)
},
/* MSD Dash Hawk */
{
USB_DEVICE
(
0x10C4
,
0x81AD
)
},
/* INSYS USB Modem */
{
USB_DEVICE
(
0x10C4
,
0x81C8
)
},
/* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
{
USB_DEVICE
(
0x10C4
,
0x81D7
)
},
/* IAI Corp. RCB-CV-USB USB to RS485 Adaptor */
{
USB_DEVICE
(
0x10C4
,
0x81E2
)
},
/* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
{
USB_DEVICE
(
0x10C4
,
0x81E7
)
},
/* Aerocomm Radio */
{
USB_DEVICE
(
0x10C4
,
0x81E8
)
},
/* Zephyr Bioharness */
...
...
@@ -108,7 +115,12 @@ static const struct usb_device_id id_table[] = {
{
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 demonstration module */
{
USB_DEVICE
(
0x10C4
,
0x8281
)
},
/* Nanotec Plug & Drive */
{
USB_DEVICE
(
0x10C4
,
0x8293
)
},
/* Telegesis ETRX2USB */
{
USB_DEVICE
(
0x10C4
,
0x82EF
)
},
/* CESINEL FALCO 6105 AC Power Supply */
{
USB_DEVICE
(
0x10C4
,
0x82F1
)
},
/* CESINEL MEDCAL EFD Earth Fault Detector */
{
USB_DEVICE
(
0x10C4
,
0x82F2
)
},
/* CESINEL MEDCAL ST Network Analyzer */
{
USB_DEVICE
(
0x10C4
,
0x82F4
)
},
/* Starizona MicroTouch */
{
USB_DEVICE
(
0x10C4
,
0x82F9
)
},
/* Procyon AVS */
{
USB_DEVICE
(
0x10C4
,
0x8341
)
},
/* Siemens MC35PU GPRS Modem */
{
USB_DEVICE
(
0x10C4
,
0x8382
)
},
/* Cygnal Integrated Products, Inc. */
...
...
@@ -117,25 +129,59 @@ static const struct usb_device_id id_table[] = {
{
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
,
0x8470
)
},
/* Juniper Networks BX Series System Console */
{
USB_DEVICE
(
0x10C4
,
0x8477
)
},
/* Balluff RFID */
{
USB_DEVICE
(
0x10C4
,
0x84B6
)
},
/* Starizona Hyperion */
{
USB_DEVICE
(
0x10C4
,
0x851E
)
},
/* CESINEL MEDCAL PT Network Analyzer */
{
USB_DEVICE
(
0x10C4
,
0x85A7
)
},
/* LifeScan OneTouch Verio IQ */
{
USB_DEVICE
(
0x10C4
,
0x85B8
)
},
/* CESINEL ReCon T Energy Logger */
{
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
,
0x8856
)
},
/* CEL EM357 ZigBee USB Stick - LR */
{
USB_DEVICE
(
0x10C4
,
0x8857
)
},
/* CEL EM357 ZigBee USB Stick */
{
USB_DEVICE
(
0x10C4
,
0x88A4
)
},
/* MMB Networks ZigBee USB Device */
{
USB_DEVICE
(
0x10C4
,
0x88A5
)
},
/* Planet Innovation Ingeni ZigBee USB Device */
{
USB_DEVICE
(
0x10C4
,
0x88FB
)
},
/* CESINEL MEDCAL STII Network Analyzer */
{
USB_DEVICE
(
0x10C4
,
0x8938
)
},
/* CESINEL MEDCAL S II Network Analyzer */
{
USB_DEVICE
(
0x10C4
,
0x8946
)
},
/* Ketra N1 Wireless Interface */
{
USB_DEVICE
(
0x10C4
,
0x8962
)
},
/* Brim Brothers charging dock */
{
USB_DEVICE
(
0x10C4
,
0x8977
)
},
/* CEL MeshWorks DevKit Device */
{
USB_DEVICE
(
0x10C4
,
0x8998
)
},
/* KCF Technologies PRN */
{
USB_DEVICE
(
0x10C4
,
0x89A4
)
},
/* CESINEL FTBC Flexible Thyristor Bridge Controller */
{
USB_DEVICE
(
0x10C4
,
0x89FB
)
},
/* Qivicon ZigBee USB Radio Stick */
{
USB_DEVICE
(
0x10C4
,
0x8A2A
)
},
/* HubZ dual ZigBee and Z-Wave dongle */
{
USB_DEVICE
(
0x10C4
,
0x8A5E
)
},
/* CEL EM3588 ZigBee USB Stick Long Range */
{
USB_DEVICE
(
0x10C4
,
0x8B34
)
},
/* Qivicon ZigBee USB Radio Stick */
{
USB_DEVICE
(
0x10C4
,
0xEA60
)
},
/* Silicon Labs factory default */
{
USB_DEVICE
(
0x10C4
,
0xEA61
)
},
/* Silicon Labs factory default */
{
USB_DEVICE
(
0x10C4
,
0xEA63
)
},
/* Silicon Labs Windows Update (CP2101-4/CP2102N) */
{
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
,
0xEA7A
)
},
/* Silicon Labs Windows Update (CP2105) */
{
USB_DEVICE
(
0x10C4
,
0xEA7B
)
},
/* Silicon Labs Windows Update (CP2108) */
{
USB_DEVICE
(
0x10C4
,
0xF001
)
},
/* Elan Digital Systems USBscope50 */
{
USB_DEVICE
(
0x10C4
,
0xF002
)
},
/* Elan Digital Systems USBwave12 */
{
USB_DEVICE
(
0x10C4
,
0xF003
)
},
/* Elan Digital Systems USBpulse100 */
{
USB_DEVICE
(
0x10C4
,
0xF004
)
},
/* Elan Digital Systems USBcount50 */
{
USB_DEVICE
(
0x10C5
,
0xEA61
)
},
/* Silicon Labs MobiData GPRS USB Modem */
{
USB_DEVICE
(
0x10CE
,
0xEA6A
)
},
/* Silicon Labs MobiData GPRS USB Modem 100EU */
{
USB_DEVICE
(
0x12B8
,
0xEC60
)
},
/* Link G4 ECU */
{
USB_DEVICE
(
0x12B8
,
0xEC62
)
},
/* Link G4+ ECU */
{
USB_DEVICE
(
0x13AD
,
0x9999
)
},
/* Baltech card reader */
{
USB_DEVICE
(
0x1555
,
0x0004
)
},
/* Owen AC4 USB-RS485 Converter */
{
USB_DEVICE
(
0x155A
,
0x1006
)
},
/* ELDAT Easywave RX09 */
{
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
(
0x16C0
,
0x09B0
)
},
/* Lunatico Seletek */
{
USB_DEVICE
(
0x16C0
,
0x09B1
)
},
/* Lunatico Seletek */
{
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 */
...
...
@@ -146,46 +192,92 @@ static const struct usb_device_id id_table[] = {
{
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
(
0x18EF
,
0xE025
)
},
/* ELV Marble Sound Board 1 */
{
USB_DEVICE
(
0x18EF
,
0xE030
)
},
/* ELV ALC 8xxx Battery Charger */
{
USB_DEVICE
(
0x18EF
,
0xE032
)
},
/* ELV TFD500 Data Logger */
{
USB_DEVICE
(
0x1901
,
0x0190
)
},
/* GE B850 CP2105 Recorder interface */
{
USB_DEVICE
(
0x1901
,
0x0193
)
},
/* GE B650 CP2104 PMC interface */
{
USB_DEVICE
(
0x1901
,
0x0194
)
},
/* GE Healthcare Remote Alarm Box */
{
USB_DEVICE
(
0x1901
,
0x0195
)
},
/* GE B850/B650/B450 CP2104 DP UART interface */
{
USB_DEVICE
(
0x1901
,
0x0196
)
},
/* GE B850 CP2105 DP UART interface */
{
USB_DEVICE
(
0x19CF
,
0x3000
)
},
/* Parrot NMEA GPS Flight Recorder */
{
USB_DEVICE
(
0x1ADB
,
0x0001
)
},
/* Schweitzer Engineering C662 Cable */
{
USB_DEVICE
(
0x1B1C
,
0x1C00
)
},
/* Corsair USB Dongle */
{
USB_DEVICE
(
0x1BA4
,
0x0002
)
},
/* Silicon Labs 358x factory default */
{
USB_DEVICE
(
0x1BE3
,
0x07A6
)
},
/* WAGO 750-923 USB Service Cable */
{
USB_DEVICE
(
0x1D6F
,
0x0010
)
},
/* Seluxit ApS RF Dongle */
{
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
(
0x2626
,
0xEA60
)
},
/* Aruba Networks 7xxx USB Serial Console */
{
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
(
0x3923
,
0x7A0B
)
},
/* National Instruments USB Serial Console */
{
USB_DEVICE
(
0x413C
,
0x9500
)
},
/* DW700 GPS USB interface */
{
}
/* Terminating Entry */
};
MODULE_DEVICE_TABLE
(
usb
,
id_table
);
struct
cp210x_port_private
{
__u8
bInterfaceNumber
;
__u8
bPartNumber
;
struct
cp210x_serial_private
{
#ifdef CONFIG_GPIOLIB
struct
gpio_chip
gc
;
bool
gpio_registered
;
u8
gpio_pushpull
;
u8
gpio_altfunc
;
u8
gpio_input
;
#endif
u8
partnum
;
speed_t
min_speed
;
speed_t
max_speed
;
bool
use_actual_rate
;
};
/*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_port_private
{
__u8
bInterfaceNumber
;
bool
has_swapped_line_ctl
;
};
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
,
.
bulk_out_size
=
256
,
.
open
=
cp210x_open
,
.
close
=
cp210x_close
,
.
ioctl
=
cp210x_ioctl
,
.
break_ctl
=
cp210x_break_ctl
,
.
set_termios
=
cp210x_set_termios
,
.
tiocmget
=
cp210x_tiocmget
,
.
tx_empty
=
cp210x_tx_empty
,
.
tiocmget
=
cp210x_tiocmget
,
.
tiocmset
=
cp210x_tiocmset
,
.
attach
=
cp210x_startup
,
.
release
=
cp210x_release
,
.
attach
=
cp210x_attach
,
.
disconnect
=
cp210x_disconnect
,
.
release
=
cp210x_release
,
.
port_probe
=
cp210x_port_probe
,
.
port_remove
=
cp210x_port_remove
,
.
dtr_rts
=
cp210x_dtr_rts
};
...
...
@@ -193,19 +285,6 @@ static struct usb_serial_driver * const serial_drivers[] = {
&
cp210x_device
,
NULL
};
/* Part number definitions */
#define CP2101_PARTNUM 0x01
#define CP2102_PARTNUM 0x02
#define CP2103_PARTNUM 0x03
#define CP2104_PARTNUM 0x04
#define CP2105_PARTNUM 0x05
#define CP2108_PARTNUM 0x08
/* IOCTLs */
#define IOCTL_GPIOGET 0x8000
#define IOCTL_GPIOSET 0x8001
/* Config request types */
#define REQTYPE_HOST_TO_INTERFACE 0x41
#define REQTYPE_INTERFACE_TO_HOST 0xc1
...
...
@@ -245,11 +324,6 @@ static struct usb_serial_driver * const serial_drivers[] = {
#define UART_ENABLE 0x0001
#define UART_DISABLE 0x0000
/* CP210X_VENDOR_SPECIFIC */
#define CP210X_WRITE_LATCH 0x37E1
#define CP210X_READ_LATCH 0x00C2
#define CP210X_GET_PARTNUM 0x370B
/* CP210X_(SET|GET)_BAUDDIV */
#define BAUD_RATE_GEN_FREQ 0x384000
...
...
@@ -287,155 +361,454 @@ static struct usb_serial_driver * const serial_drivers[] = {
#define CONTROL_WRITE_DTR 0x0100
#define CONTROL_WRITE_RTS 0x0200
/* CP210X_VENDOR_SPECIFIC values */
#define CP210X_READ_2NCONFIG 0x000E
#define CP210X_READ_LATCH 0x00C2
#define CP210X_GET_PARTNUM 0x370B
#define CP210X_GET_PORTCONFIG 0x370C
#define CP210X_GET_DEVICEMODE 0x3711
#define CP210X_WRITE_LATCH 0x37E1
/* Part number definitions */
#define CP210X_PARTNUM_CP2101 0x01
#define CP210X_PARTNUM_CP2102 0x02
#define CP210X_PARTNUM_CP2103 0x03
#define CP210X_PARTNUM_CP2104 0x04
#define CP210X_PARTNUM_CP2105 0x05
#define CP210X_PARTNUM_CP2108 0x08
#define CP210X_PARTNUM_CP2102N_QFN28 0x20
#define CP210X_PARTNUM_CP2102N_QFN24 0x21
#define CP210X_PARTNUM_CP2102N_QFN20 0x22
#define CP210X_PARTNUM_UNKNOWN 0xFF
/* CP210X_GET_COMM_STATUS returns these 0x13 bytes */
struct
cp210x_comm_status
{
__le32
ulErrors
;
__le32
ulHoldReasons
;
__le32
ulAmountInInQueue
;
__le32
ulAmountInOutQueue
;
u8
bEofReceived
;
u8
bWaitForImmediate
;
u8
bReserved
;
}
__packed
;
/*
* CP210X_PURGE - 16 bits passed in wValue of USB request.
* SiLabs app note AN571 gives a strange description of the 4 bits:
* bit 0 or bit 2 clears the transmit queue and 1 or 3 receive.
* writing 1 to all, however, purges cp2108 well enough to avoid the hang.
*/
#define PURGE_ALL 0x000f
/* CP210X_GET_FLOW/CP210X_SET_FLOW read/write these 0x10 bytes */
struct
cp210x_flow_ctl
{
__le32
ulControlHandshake
;
__le32
ulFlowReplace
;
__le32
ulXonLimit
;
__le32
ulXoffLimit
;
}
__packed
;
/* cp210x_flow_ctl::ulControlHandshake */
#define CP210X_SERIAL_DTR_MASK GENMASK(1, 0)
#define CP210X_SERIAL_DTR_SHIFT(_mode) (_mode)
#define CP210X_SERIAL_CTS_HANDSHAKE BIT(3)
#define CP210X_SERIAL_DSR_HANDSHAKE BIT(4)
#define CP210X_SERIAL_DCD_HANDSHAKE BIT(5)
#define CP210X_SERIAL_DSR_SENSITIVITY BIT(6)
/* values for cp210x_flow_ctl::ulControlHandshake::CP210X_SERIAL_DTR_MASK */
#define CP210X_SERIAL_DTR_INACTIVE 0
#define CP210X_SERIAL_DTR_ACTIVE 1
#define CP210X_SERIAL_DTR_FLOW_CTL 2
/* cp210x_flow_ctl::ulFlowReplace */
#define CP210X_SERIAL_AUTO_TRANSMIT BIT(0)
#define CP210X_SERIAL_AUTO_RECEIVE BIT(1)
#define CP210X_SERIAL_ERROR_CHAR BIT(2)
#define CP210X_SERIAL_NULL_STRIPPING BIT(3)
#define CP210X_SERIAL_BREAK_CHAR BIT(4)
#define CP210X_SERIAL_RTS_MASK GENMASK(7, 6)
#define CP210X_SERIAL_RTS_SHIFT(_mode) (_mode << 6)
#define CP210X_SERIAL_XOFF_CONTINUE BIT(31)
/* values for cp210x_flow_ctl::ulFlowReplace::CP210X_SERIAL_RTS_MASK */
#define CP210X_SERIAL_RTS_INACTIVE 0
#define CP210X_SERIAL_RTS_ACTIVE 1
#define CP210X_SERIAL_RTS_FLOW_CTL 2
/* CP210X_VENDOR_SPECIFIC, CP210X_GET_DEVICEMODE call reads these 0x2 bytes. */
struct
cp210x_pin_mode
{
u8
eci
;
u8
sci
;
}
__packed
;
#define CP210X_PIN_MODE_MODEM 0
#define CP210X_PIN_MODE_GPIO BIT(0)
/*
* cp210x_get_config
* Reads from the CP210x configuration registers
* 'size' is specified in bytes.
* 'data' is a pointer to a pre-allocated array of integers large
* enough to hold 'size' bytes (with 4 bytes to each integer)
* CP210X_VENDOR_SPECIFIC, CP210X_GET_PORTCONFIG call reads these 0xf bytes
* on a CP2105 chip. Structure needs padding due to unused/unspecified bytes.
*/
static
int
cp210x_get_config
(
struct
usb_serial_port
*
port
,
u8
requestType
,
u8
request
,
int
value
,
unsigned
int
*
data
,
int
size
)
struct
cp210x_dual_port_config
{
__le16
gpio_mode
;
u8
__pad0
[
2
];
__le16
reset_state
;
u8
__pad1
[
4
];
__le16
suspend_state
;
u8
sci_cfg
;
u8
eci_cfg
;
u8
device_cfg
;
}
__packed
;
/*
* CP210X_VENDOR_SPECIFIC, CP210X_GET_PORTCONFIG call reads these 0xd bytes
* on a CP2104 chip. Structure needs padding due to unused/unspecified bytes.
*/
struct
cp210x_single_port_config
{
__le16
gpio_mode
;
u8
__pad0
[
2
];
__le16
reset_state
;
u8
__pad1
[
4
];
__le16
suspend_state
;
u8
device_cfg
;
}
__packed
;
/* GPIO modes */
#define CP210X_SCI_GPIO_MODE_OFFSET 9
#define CP210X_SCI_GPIO_MODE_MASK GENMASK(11, 9)
#define CP210X_ECI_GPIO_MODE_OFFSET 2
#define CP210X_ECI_GPIO_MODE_MASK GENMASK(3, 2)
#define CP210X_GPIO_MODE_OFFSET 8
#define CP210X_GPIO_MODE_MASK GENMASK(11, 8)
/* CP2105 port configuration values */
#define CP2105_GPIO0_TXLED_MODE BIT(0)
#define CP2105_GPIO1_RXLED_MODE BIT(1)
#define CP2105_GPIO1_RS485_MODE BIT(2)
/* CP2104 port configuration values */
#define CP2104_GPIO0_TXLED_MODE BIT(0)
#define CP2104_GPIO1_RXLED_MODE BIT(1)
#define CP2104_GPIO2_RS485_MODE BIT(2)
/* CP2102N configuration array indices */
#define CP210X_2NCONFIG_CONFIG_VERSION_IDX 2
#define CP210X_2NCONFIG_GPIO_MODE_IDX 581
#define CP210X_2NCONFIG_GPIO_RSTLATCH_IDX 587
#define CP210X_2NCONFIG_GPIO_CONTROL_IDX 600
/* CP210X_VENDOR_SPECIFIC, CP210X_WRITE_LATCH call writes these 0x2 bytes. */
struct
cp210x_gpio_write
{
u8
mask
;
u8
state
;
}
__packed
;
/*
* Helper to get interface number when we only have struct usb_serial.
*/
static
u8
cp210x_interface_num
(
struct
usb_serial
*
serial
)
{
struct
usb_host_interface
*
cur_altsetting
;
cur_altsetting
=
serial
->
interface
->
cur_altsetting
;
return
cur_altsetting
->
desc
.
bInterfaceNumber
;
}
/*
* Reads a variable-sized block of CP210X_ registers, identified by req.
* Returns data into buf in native USB byte order.
*/
static
int
cp210x_read_reg_block
(
struct
usb_serial_port
*
port
,
u8
req
,
void
*
buf
,
int
bufsize
)
{
struct
usb_serial
*
serial
=
port
->
serial
;
struct
cp210x_port_private
*
port_priv
=
usb_get_serial_port_data
(
port
);
__le32
*
buf
;
int
result
,
i
,
length
;
/* Number of integers required to contain the array */
length
=
(((
size
-
1
)
|
3
)
+
1
)
/
4
;
void
*
dmabuf
;
int
result
;
buf
=
kcalloc
(
length
,
sizeof
(
__le32
),
GFP_KERNEL
);
if
(
!
buf
)
{
dev_err
(
&
port
->
dev
,
"%s - out of memory.
\n
"
,
__func__
);
dmabuf
=
kmalloc
(
bufsize
,
GFP_KERNEL
);
if
(
!
dmabuf
)
{
/*
* FIXME Some callers don't bother to check for error,
* at least give them consistent junk until they are fixed
*/
memset
(
buf
,
0
,
bufsize
);
return
-
ENOMEM
;
}
/* Issue the request, attempting to read 'size' bytes */
result
=
usb_control_msg
(
serial
->
dev
,
usb_rcvctrlpipe
(
serial
->
dev
,
0
),
request
,
requestType
,
value
,
port_priv
->
bInterfaceNumber
,
buf
,
size
,
300
);
/* Convert data into an array of integers */
for
(
i
=
0
;
i
<
length
;
i
++
)
data
[
i
]
=
le32_to_cpu
(
buf
[
i
]);
req
,
REQTYPE_INTERFACE_TO_HOST
,
0
,
port_priv
->
bInterfaceNumber
,
dmabuf
,
bufsize
,
USB_CTRL_SET_TIMEOUT
);
if
(
result
==
bufsize
)
{
memcpy
(
buf
,
dmabuf
,
bufsize
);
result
=
0
;
}
else
{
dev_err
(
&
port
->
dev
,
"failed get req 0x%x size %d status: %d
\n
"
,
req
,
bufsize
,
result
);
if
(
result
>=
0
)
result
=
-
EIO
;
/*
* FIXME Some callers don't bother to check for error,
* at least give them consistent junk until they are fixed
*/
memset
(
buf
,
0
,
bufsize
);
}
kfree
(
buf
);
kfree
(
dma
buf
);
if
(
result
!=
size
)
{
dbg
(
"%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
result
;
/*
* Reads any 32-bit CP210X_ register identified by req.
*/
static
int
cp210x_read_u32_reg
(
struct
usb_serial_port
*
port
,
u8
req
,
u32
*
val
)
{
__le32
le32_val
;
int
err
;
err
=
cp210x_read_reg_block
(
port
,
req
,
&
le32_val
,
sizeof
(
le32_val
));
if
(
err
)
{
/*
* FIXME Some callers don't bother to check for error,
* at least give them consistent junk until they are fixed
*/
*
val
=
0
;
return
err
;
}
*
val
=
le32_to_cpu
(
le32_val
);
return
0
;
}
/*
* Reads any 16-bit CP210X_ register identified by req.
*/
static
int
cp210x_read_u16_reg
(
struct
usb_serial_port
*
port
,
u8
req
,
u16
*
val
)
{
__le16
le16_val
;
int
err
;
err
=
cp210x_read_reg_block
(
port
,
req
,
&
le16_val
,
sizeof
(
le16_val
));
if
(
err
)
return
err
;
*
val
=
le16_to_cpu
(
le16_val
);
return
0
;
}
/*
* cp210x_set_config
* Writes to the CP210x configuration registers
* Values less than 16 bits wide are sent directly
* 'size' is specified in bytes.
* Reads any 8-bit CP210X_ register identified by req.
*/
static
int
cp210x_read_u8_reg
(
struct
usb_serial_port
*
port
,
u8
req
,
u8
*
val
)
{
return
cp210x_read_reg_block
(
port
,
req
,
val
,
sizeof
(
*
val
));
}
/*
* Reads a variable-sized vendor block of CP210X_ registers, identified by val.
* Returns data into buf in native USB byte order.
*/
static
int
cp210x_read_vendor_block
(
struct
usb_serial
*
serial
,
u8
type
,
u16
val
,
void
*
buf
,
int
bufsize
)
{
void
*
dmabuf
;
int
result
;
dmabuf
=
kmalloc
(
bufsize
,
GFP_KERNEL
);
if
(
!
dmabuf
)
return
-
ENOMEM
;
result
=
usb_control_msg
(
serial
->
dev
,
usb_rcvctrlpipe
(
serial
->
dev
,
0
),
CP210X_VENDOR_SPECIFIC
,
type
,
val
,
cp210x_interface_num
(
serial
),
dmabuf
,
bufsize
,
USB_CTRL_GET_TIMEOUT
);
if
(
result
==
bufsize
)
{
memcpy
(
buf
,
dmabuf
,
bufsize
);
result
=
0
;
}
else
{
dev_err
(
&
serial
->
interface
->
dev
,
"failed to get vendor val 0x%04x size %d: %d
\n
"
,
val
,
bufsize
,
result
);
if
(
result
>=
0
)
result
=
-
EIO
;
}
kfree
(
dmabuf
);
return
result
;
}
/*
* Writes any 16-bit CP210X_ register (req) whose value is passed
* entirely in the wValue field of the USB request.
*/
static
int
cp210x_set_config
(
struct
usb_serial_port
*
port
,
u8
requestType
,
u8
request
,
int
value
,
unsigned
int
*
data
,
int
size
)
static
int
cp210x_write_u16_reg
(
struct
usb_serial_port
*
port
,
u8
req
,
u16
val
)
{
struct
usb_serial
*
serial
=
port
->
serial
;
struct
cp210x_port_private
*
port_priv
=
usb_get_serial_port_data
(
port
);
__le32
*
buf
=
NULL
;
int
result
,
i
,
length
=
0
;
if
(
size
)
{
/* Number of integers required to contain the array */
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__
);
return
-
ENOMEM
;
}
int
result
;
/* Array of integers into bytes */
for
(
i
=
0
;
i
<
length
;
i
++
)
buf
[
i
]
=
cpu_to_le32
(
data
[
i
]);
result
=
usb_control_msg
(
serial
->
dev
,
usb_sndctrlpipe
(
serial
->
dev
,
0
),
req
,
REQTYPE_HOST_TO_INTERFACE
,
val
,
port_priv
->
bInterfaceNumber
,
NULL
,
0
,
USB_CTRL_SET_TIMEOUT
);
if
(
result
<
0
)
{
dev_err
(
&
port
->
dev
,
"failed set request 0x%x status: %d
\n
"
,
req
,
result
);
}
result
=
usb_control_msg
(
serial
->
dev
,
usb_sndctrlpipe
(
serial
->
dev
,
0
),
request
,
requestType
,
value
,
port_priv
->
bInterfaceNumber
,
buf
,
size
,
300
);
return
result
;
}
/*
* Writes a variable-sized block of CP210X_ registers, identified by req.
* Data in buf must be in native USB byte order.
*/
static
int
cp210x_write_reg_block
(
struct
usb_serial_port
*
port
,
u8
req
,
void
*
buf
,
int
bufsize
)
{
struct
usb_serial
*
serial
=
port
->
serial
;
struct
cp210x_port_private
*
port_priv
=
usb_get_serial_port_data
(
port
);
void
*
dmabuf
;
int
result
;
dmabuf
=
kmemdup
(
buf
,
bufsize
,
GFP_KERNEL
);
if
(
!
dmabuf
)
return
-
ENOMEM
;
if
(
buf
)
kfree
(
buf
);
result
=
usb_control_msg
(
serial
->
dev
,
usb_sndctrlpipe
(
serial
->
dev
,
0
),
req
,
REQTYPE_HOST_TO_INTERFACE
,
0
,
port_priv
->
bInterfaceNumber
,
dmabuf
,
bufsize
,
USB_CTRL_SET_TIMEOUT
);
if
(
result
!=
size
)
{
dbg
(
"%s - Unable to send request, "