cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

belkin_sa.c (13830B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Belkin USB Serial Adapter Driver
      4 *
      5 *  Copyright (C) 2000		William Greathouse (wgreathouse@smva.com)
      6 *  Copyright (C) 2000-2001	Greg Kroah-Hartman (greg@kroah.com)
      7 *  Copyright (C) 2010		Johan Hovold (jhovold@gmail.com)
      8 *
      9 *  This program is largely derived from work by the linux-usb group
     10 *  and associated source files.  Please see the usb/serial files for
     11 *  individual credits and copyrights.
     12 *
     13 * See Documentation/usb/usb-serial.rst for more information on using this
     14 * driver
     15 *
     16 * TODO:
     17 * -- Add true modem control line query capability.  Currently we track the
     18 *    states reported by the interrupt and the states we request.
     19 * -- Add support for flush commands
     20 */
     21
     22#include <linux/kernel.h>
     23#include <linux/errno.h>
     24#include <linux/slab.h>
     25#include <linux/tty.h>
     26#include <linux/tty_driver.h>
     27#include <linux/tty_flip.h>
     28#include <linux/module.h>
     29#include <linux/spinlock.h>
     30#include <linux/uaccess.h>
     31#include <linux/usb.h>
     32#include <linux/usb/serial.h>
     33#include "belkin_sa.h"
     34
     35#define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>"
     36#define DRIVER_DESC "USB Belkin Serial converter driver"
     37
     38/* function prototypes for a Belkin USB Serial Adapter F5U103 */
     39static int belkin_sa_port_probe(struct usb_serial_port *port);
     40static void belkin_sa_port_remove(struct usb_serial_port *port);
     41static int  belkin_sa_open(struct tty_struct *tty,
     42			struct usb_serial_port *port);
     43static void belkin_sa_close(struct usb_serial_port *port);
     44static void belkin_sa_read_int_callback(struct urb *urb);
     45static void belkin_sa_process_read_urb(struct urb *urb);
     46static void belkin_sa_set_termios(struct tty_struct *tty,
     47			struct usb_serial_port *port, struct ktermios * old);
     48static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state);
     49static int  belkin_sa_tiocmget(struct tty_struct *tty);
     50static int  belkin_sa_tiocmset(struct tty_struct *tty,
     51					unsigned int set, unsigned int clear);
     52
     53
     54static const struct usb_device_id id_table[] = {
     55	{ USB_DEVICE(BELKIN_SA_VID, BELKIN_SA_PID) },
     56	{ USB_DEVICE(BELKIN_OLD_VID, BELKIN_OLD_PID) },
     57	{ USB_DEVICE(PERACOM_VID, PERACOM_PID) },
     58	{ USB_DEVICE(GOHUBS_VID, GOHUBS_PID) },
     59	{ USB_DEVICE(GOHUBS_VID, HANDYLINK_PID) },
     60	{ USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) },
     61	{ }	/* Terminating entry */
     62};
     63MODULE_DEVICE_TABLE(usb, id_table);
     64
     65/* All of the device info needed for the serial converters */
     66static struct usb_serial_driver belkin_device = {
     67	.driver = {
     68		.owner =	THIS_MODULE,
     69		.name =		"belkin",
     70	},
     71	.description =		"Belkin / Peracom / GoHubs USB Serial Adapter",
     72	.id_table =		id_table,
     73	.num_ports =		1,
     74	.open =			belkin_sa_open,
     75	.close =		belkin_sa_close,
     76	.read_int_callback =	belkin_sa_read_int_callback,
     77	.process_read_urb =	belkin_sa_process_read_urb,
     78	.set_termios =		belkin_sa_set_termios,
     79	.break_ctl =		belkin_sa_break_ctl,
     80	.tiocmget =		belkin_sa_tiocmget,
     81	.tiocmset =		belkin_sa_tiocmset,
     82	.port_probe =		belkin_sa_port_probe,
     83	.port_remove =		belkin_sa_port_remove,
     84};
     85
     86static struct usb_serial_driver * const serial_drivers[] = {
     87	&belkin_device, NULL
     88};
     89
     90struct belkin_sa_private {
     91	spinlock_t		lock;
     92	unsigned long		control_state;
     93	unsigned char		last_lsr;
     94	unsigned char		last_msr;
     95	int			bad_flow_control;
     96};
     97
     98
     99/*
    100 * ***************************************************************************
    101 * Belkin USB Serial Adapter F5U103 specific driver functions
    102 * ***************************************************************************
    103 */
    104
    105#define WDR_TIMEOUT 5000 /* default urb timeout */
    106
    107/* assumes that struct usb_serial *serial is available */
    108#define BSA_USB_CMD(c, v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \
    109					    (c), BELKIN_SA_SET_REQUEST_TYPE, \
    110					    (v), 0, NULL, 0, WDR_TIMEOUT)
    111
    112static int belkin_sa_port_probe(struct usb_serial_port *port)
    113{
    114	struct usb_device *dev = port->serial->dev;
    115	struct belkin_sa_private *priv;
    116
    117	priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL);
    118	if (!priv)
    119		return -ENOMEM;
    120
    121	spin_lock_init(&priv->lock);
    122	priv->control_state = 0;
    123	priv->last_lsr = 0;
    124	priv->last_msr = 0;
    125	/* see comments at top of file */
    126	priv->bad_flow_control =
    127		(le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0;
    128	dev_info(&dev->dev, "bcdDevice: %04x, bfc: %d\n",
    129					le16_to_cpu(dev->descriptor.bcdDevice),
    130					priv->bad_flow_control);
    131
    132	usb_set_serial_port_data(port, priv);
    133
    134	return 0;
    135}
    136
    137static void belkin_sa_port_remove(struct usb_serial_port *port)
    138{
    139	struct belkin_sa_private *priv;
    140
    141	priv = usb_get_serial_port_data(port);
    142	kfree(priv);
    143}
    144
    145static int belkin_sa_open(struct tty_struct *tty,
    146					struct usb_serial_port *port)
    147{
    148	int retval;
    149
    150	retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
    151	if (retval) {
    152		dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
    153		return retval;
    154	}
    155
    156	retval = usb_serial_generic_open(tty, port);
    157	if (retval)
    158		usb_kill_urb(port->interrupt_in_urb);
    159
    160	return retval;
    161}
    162
    163static void belkin_sa_close(struct usb_serial_port *port)
    164{
    165	usb_serial_generic_close(port);
    166	usb_kill_urb(port->interrupt_in_urb);
    167}
    168
    169static void belkin_sa_read_int_callback(struct urb *urb)
    170{
    171	struct usb_serial_port *port = urb->context;
    172	struct belkin_sa_private *priv;
    173	unsigned char *data = urb->transfer_buffer;
    174	int retval;
    175	int status = urb->status;
    176	unsigned long flags;
    177
    178	switch (status) {
    179	case 0:
    180		/* success */
    181		break;
    182	case -ECONNRESET:
    183	case -ENOENT:
    184	case -ESHUTDOWN:
    185		/* this urb is terminated, clean up */
    186		dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
    187			__func__, status);
    188		return;
    189	default:
    190		dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
    191			__func__, status);
    192		goto exit;
    193	}
    194
    195	usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
    196
    197	/* Handle known interrupt data */
    198	/* ignore data[0] and data[1] */
    199
    200	priv = usb_get_serial_port_data(port);
    201	spin_lock_irqsave(&priv->lock, flags);
    202	priv->last_msr = data[BELKIN_SA_MSR_INDEX];
    203
    204	/* Record Control Line states */
    205	if (priv->last_msr & BELKIN_SA_MSR_DSR)
    206		priv->control_state |= TIOCM_DSR;
    207	else
    208		priv->control_state &= ~TIOCM_DSR;
    209
    210	if (priv->last_msr & BELKIN_SA_MSR_CTS)
    211		priv->control_state |= TIOCM_CTS;
    212	else
    213		priv->control_state &= ~TIOCM_CTS;
    214
    215	if (priv->last_msr & BELKIN_SA_MSR_RI)
    216		priv->control_state |= TIOCM_RI;
    217	else
    218		priv->control_state &= ~TIOCM_RI;
    219
    220	if (priv->last_msr & BELKIN_SA_MSR_CD)
    221		priv->control_state |= TIOCM_CD;
    222	else
    223		priv->control_state &= ~TIOCM_CD;
    224
    225	priv->last_lsr = data[BELKIN_SA_LSR_INDEX];
    226	spin_unlock_irqrestore(&priv->lock, flags);
    227exit:
    228	retval = usb_submit_urb(urb, GFP_ATOMIC);
    229	if (retval)
    230		dev_err(&port->dev, "%s - usb_submit_urb failed with "
    231			"result %d\n", __func__, retval);
    232}
    233
    234static void belkin_sa_process_read_urb(struct urb *urb)
    235{
    236	struct usb_serial_port *port = urb->context;
    237	struct belkin_sa_private *priv = usb_get_serial_port_data(port);
    238	unsigned char *data = urb->transfer_buffer;
    239	unsigned long flags;
    240	unsigned char status;
    241	char tty_flag;
    242
    243	/* Update line status */
    244	tty_flag = TTY_NORMAL;
    245
    246	spin_lock_irqsave(&priv->lock, flags);
    247	status = priv->last_lsr;
    248	priv->last_lsr &= ~BELKIN_SA_LSR_ERR;
    249	spin_unlock_irqrestore(&priv->lock, flags);
    250
    251	if (!urb->actual_length)
    252		return;
    253
    254	if (status & BELKIN_SA_LSR_ERR) {
    255		/* Break takes precedence over parity, which takes precedence
    256		 * over framing errors. */
    257		if (status & BELKIN_SA_LSR_BI)
    258			tty_flag = TTY_BREAK;
    259		else if (status & BELKIN_SA_LSR_PE)
    260			tty_flag = TTY_PARITY;
    261		else if (status & BELKIN_SA_LSR_FE)
    262			tty_flag = TTY_FRAME;
    263		dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
    264
    265		/* Overrun is special, not associated with a char. */
    266		if (status & BELKIN_SA_LSR_OE)
    267			tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
    268	}
    269
    270	tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag,
    271							urb->actual_length);
    272	tty_flip_buffer_push(&port->port);
    273}
    274
    275static void belkin_sa_set_termios(struct tty_struct *tty,
    276		struct usb_serial_port *port, struct ktermios *old_termios)
    277{
    278	struct usb_serial *serial = port->serial;
    279	struct belkin_sa_private *priv = usb_get_serial_port_data(port);
    280	unsigned int iflag;
    281	unsigned int cflag;
    282	unsigned int old_iflag = 0;
    283	unsigned int old_cflag = 0;
    284	__u16 urb_value = 0; /* Will hold the new flags */
    285	unsigned long flags;
    286	unsigned long control_state;
    287	int bad_flow_control;
    288	speed_t baud;
    289	struct ktermios *termios = &tty->termios;
    290
    291	iflag = termios->c_iflag;
    292	cflag = termios->c_cflag;
    293
    294	termios->c_cflag &= ~CMSPAR;
    295
    296	/* get a local copy of the current port settings */
    297	spin_lock_irqsave(&priv->lock, flags);
    298	control_state = priv->control_state;
    299	bad_flow_control = priv->bad_flow_control;
    300	spin_unlock_irqrestore(&priv->lock, flags);
    301
    302	old_iflag = old_termios->c_iflag;
    303	old_cflag = old_termios->c_cflag;
    304
    305	/* Set the baud rate */
    306	if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
    307		/* reassert DTR and (maybe) RTS on transition from B0 */
    308		if ((old_cflag & CBAUD) == B0) {
    309			control_state |= (TIOCM_DTR|TIOCM_RTS);
    310			if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0)
    311				dev_err(&port->dev, "Set DTR error\n");
    312			/* don't set RTS if using hardware flow control */
    313			if (!(old_cflag & CRTSCTS))
    314				if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST
    315								, 1) < 0)
    316					dev_err(&port->dev, "Set RTS error\n");
    317		}
    318	}
    319
    320	baud = tty_get_baud_rate(tty);
    321	if (baud) {
    322		urb_value = BELKIN_SA_BAUD(baud);
    323		/* Clip to maximum speed */
    324		if (urb_value == 0)
    325			urb_value = 1;
    326		/* Turn it back into a resulting real baud rate */
    327		baud = BELKIN_SA_BAUD(urb_value);
    328
    329		/* Report the actual baud rate back to the caller */
    330		tty_encode_baud_rate(tty, baud, baud);
    331		if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
    332			dev_err(&port->dev, "Set baudrate error\n");
    333	} else {
    334		/* Disable flow control */
    335		if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST,
    336						BELKIN_SA_FLOW_NONE) < 0)
    337			dev_err(&port->dev, "Disable flowcontrol error\n");
    338		/* Drop RTS and DTR */
    339		control_state &= ~(TIOCM_DTR | TIOCM_RTS);
    340		if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0)
    341			dev_err(&port->dev, "DTR LOW error\n");
    342		if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0)
    343			dev_err(&port->dev, "RTS LOW error\n");
    344	}
    345
    346	/* set the parity */
    347	if ((cflag ^ old_cflag) & (PARENB | PARODD)) {
    348		if (cflag & PARENB)
    349			urb_value = (cflag & PARODD) ?  BELKIN_SA_PARITY_ODD
    350						: BELKIN_SA_PARITY_EVEN;
    351		else
    352			urb_value = BELKIN_SA_PARITY_NONE;
    353		if (BSA_USB_CMD(BELKIN_SA_SET_PARITY_REQUEST, urb_value) < 0)
    354			dev_err(&port->dev, "Set parity error\n");
    355	}
    356
    357	/* set the number of data bits */
    358	if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
    359		urb_value = BELKIN_SA_DATA_BITS(tty_get_char_size(cflag));
    360		if (BSA_USB_CMD(BELKIN_SA_SET_DATA_BITS_REQUEST, urb_value) < 0)
    361			dev_err(&port->dev, "Set data bits error\n");
    362	}
    363
    364	/* set the number of stop bits */
    365	if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
    366		urb_value = (cflag & CSTOPB) ? BELKIN_SA_STOP_BITS(2)
    367						: BELKIN_SA_STOP_BITS(1);
    368		if (BSA_USB_CMD(BELKIN_SA_SET_STOP_BITS_REQUEST,
    369							urb_value) < 0)
    370			dev_err(&port->dev, "Set stop bits error\n");
    371	}
    372
    373	/* Set flow control */
    374	if (((iflag ^ old_iflag) & (IXOFF | IXON)) ||
    375		((cflag ^ old_cflag) & CRTSCTS)) {
    376		urb_value = 0;
    377		if ((iflag & IXOFF) || (iflag & IXON))
    378			urb_value |= (BELKIN_SA_FLOW_OXON | BELKIN_SA_FLOW_IXON);
    379		else
    380			urb_value &= ~(BELKIN_SA_FLOW_OXON | BELKIN_SA_FLOW_IXON);
    381
    382		if (cflag & CRTSCTS)
    383			urb_value |=  (BELKIN_SA_FLOW_OCTS | BELKIN_SA_FLOW_IRTS);
    384		else
    385			urb_value &= ~(BELKIN_SA_FLOW_OCTS | BELKIN_SA_FLOW_IRTS);
    386
    387		if (bad_flow_control)
    388			urb_value &= ~(BELKIN_SA_FLOW_IRTS);
    389
    390		if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, urb_value) < 0)
    391			dev_err(&port->dev, "Set flow control error\n");
    392	}
    393
    394	/* save off the modified port settings */
    395	spin_lock_irqsave(&priv->lock, flags);
    396	priv->control_state = control_state;
    397	spin_unlock_irqrestore(&priv->lock, flags);
    398}
    399
    400static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state)
    401{
    402	struct usb_serial_port *port = tty->driver_data;
    403	struct usb_serial *serial = port->serial;
    404
    405	if (BSA_USB_CMD(BELKIN_SA_SET_BREAK_REQUEST, break_state ? 1 : 0) < 0)
    406		dev_err(&port->dev, "Set break_ctl %d\n", break_state);
    407}
    408
    409static int belkin_sa_tiocmget(struct tty_struct *tty)
    410{
    411	struct usb_serial_port *port = tty->driver_data;
    412	struct belkin_sa_private *priv = usb_get_serial_port_data(port);
    413	unsigned long control_state;
    414	unsigned long flags;
    415
    416	spin_lock_irqsave(&priv->lock, flags);
    417	control_state = priv->control_state;
    418	spin_unlock_irqrestore(&priv->lock, flags);
    419
    420	return control_state;
    421}
    422
    423static int belkin_sa_tiocmset(struct tty_struct *tty,
    424			       unsigned int set, unsigned int clear)
    425{
    426	struct usb_serial_port *port = tty->driver_data;
    427	struct usb_serial *serial = port->serial;
    428	struct belkin_sa_private *priv = usb_get_serial_port_data(port);
    429	unsigned long control_state;
    430	unsigned long flags;
    431	int retval;
    432	int rts = 0;
    433	int dtr = 0;
    434
    435	spin_lock_irqsave(&priv->lock, flags);
    436	control_state = priv->control_state;
    437
    438	if (set & TIOCM_RTS) {
    439		control_state |= TIOCM_RTS;
    440		rts = 1;
    441	}
    442	if (set & TIOCM_DTR) {
    443		control_state |= TIOCM_DTR;
    444		dtr = 1;
    445	}
    446	if (clear & TIOCM_RTS) {
    447		control_state &= ~TIOCM_RTS;
    448		rts = 0;
    449	}
    450	if (clear & TIOCM_DTR) {
    451		control_state &= ~TIOCM_DTR;
    452		dtr = 0;
    453	}
    454
    455	priv->control_state = control_state;
    456	spin_unlock_irqrestore(&priv->lock, flags);
    457
    458	retval = BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, rts);
    459	if (retval < 0) {
    460		dev_err(&port->dev, "Set RTS error %d\n", retval);
    461		goto exit;
    462	}
    463
    464	retval = BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, dtr);
    465	if (retval < 0) {
    466		dev_err(&port->dev, "Set DTR error %d\n", retval);
    467		goto exit;
    468	}
    469exit:
    470	return retval;
    471}
    472
    473module_usb_serial_driver(serial_drivers, id_table);
    474
    475MODULE_AUTHOR(DRIVER_AUTHOR);
    476MODULE_DESCRIPTION(DRIVER_DESC);
    477MODULE_LICENSE("GPL");