linux/drivers/usb/serial/digi_acceleport.c

// SPDX-License-Identifier: GPL-2.0+
/*
*  Digi AccelePort USB-4 and USB-2 Serial Converters
*
*  Copyright 2000 by Digi International
*
*  Shamelessly based on Brian Warner's keyspan_pda.c and Greg Kroah-Hartman's
*  usb-serial driver.
*
*  Peter Berger ([email protected])
*  Al Borchers ([email protected])
*/

#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/module.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/wait.h>
#include <linux/sched/signal.h>
#include <linux/usb/serial.h>

/* Defines */

#define DRIVER_AUTHOR
#define DRIVER_DESC

/* port output buffer length -- must be <= transfer buffer length - 2 */
/* so we can be sure to send the full buffer in one urb */
#define DIGI_OUT_BUF_SIZE

/* port input buffer length -- must be >= transfer buffer length - 3 */
/* so we can be sure to hold at least one full buffer from one urb */
#define DIGI_IN_BUF_SIZE

/* retry timeout while sleeping */
#define DIGI_RETRY_TIMEOUT

/* timeout while waiting for tty output to drain in close */
/* this delay is used twice in close, so the total delay could */
/* be twice this value */
#define DIGI_CLOSE_TIMEOUT


/* AccelePort USB Defines */

/* ids */
#define DIGI_VENDOR_ID
#define DIGI_2_ID
#define DIGI_4_ID

/* commands
 * "INB": can be used on the in-band endpoint
 * "OOB": can be used on the out-of-band endpoint
 */
#define DIGI_CMD_SET_BAUD_RATE
#define DIGI_CMD_SET_WORD_SIZE
#define DIGI_CMD_SET_PARITY
#define DIGI_CMD_SET_STOP_BITS
#define DIGI_CMD_SET_INPUT_FLOW_CONTROL
#define DIGI_CMD_SET_OUTPUT_FLOW_CONTROL
#define DIGI_CMD_SET_DTR_SIGNAL
#define DIGI_CMD_SET_RTS_SIGNAL
#define DIGI_CMD_READ_INPUT_SIGNALS
#define DIGI_CMD_IFLUSH_FIFO
#define DIGI_CMD_RECEIVE_ENABLE
#define DIGI_CMD_BREAK_CONTROL
#define DIGI_CMD_LOCAL_LOOPBACK
#define DIGI_CMD_TRANSMIT_IDLE
#define DIGI_CMD_READ_UART_REGISTER
#define DIGI_CMD_WRITE_UART_REGISTER
#define DIGI_CMD_AND_UART_REGISTER
#define DIGI_CMD_OR_UART_REGISTER
#define DIGI_CMD_SEND_DATA
#define DIGI_CMD_RECEIVE_DATA
#define DIGI_CMD_RECEIVE_DISABLE
#define DIGI_CMD_GET_PORT_TYPE

/* baud rates */
#define DIGI_BAUD_50
#define DIGI_BAUD_75
#define DIGI_BAUD_110
#define DIGI_BAUD_150
#define DIGI_BAUD_200
#define DIGI_BAUD_300
#define DIGI_BAUD_600
#define DIGI_BAUD_1200
#define DIGI_BAUD_1800
#define DIGI_BAUD_2400
#define DIGI_BAUD_4800
#define DIGI_BAUD_7200
#define DIGI_BAUD_9600
#define DIGI_BAUD_14400
#define DIGI_BAUD_19200
#define DIGI_BAUD_28800
#define DIGI_BAUD_38400
#define DIGI_BAUD_57600
#define DIGI_BAUD_76800
#define DIGI_BAUD_115200
#define DIGI_BAUD_153600
#define DIGI_BAUD_230400
#define DIGI_BAUD_460800

/* arguments */
#define DIGI_WORD_SIZE_5
#define DIGI_WORD_SIZE_6
#define DIGI_WORD_SIZE_7
#define DIGI_WORD_SIZE_8

#define DIGI_PARITY_NONE
#define DIGI_PARITY_ODD
#define DIGI_PARITY_EVEN
#define DIGI_PARITY_MARK
#define DIGI_PARITY_SPACE

#define DIGI_STOP_BITS_1
#define DIGI_STOP_BITS_2

#define DIGI_INPUT_FLOW_CONTROL_XON_XOFF
#define DIGI_INPUT_FLOW_CONTROL_RTS
#define DIGI_INPUT_FLOW_CONTROL_DTR

#define DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF
#define DIGI_OUTPUT_FLOW_CONTROL_CTS
#define DIGI_OUTPUT_FLOW_CONTROL_DSR

#define DIGI_DTR_INACTIVE
#define DIGI_DTR_ACTIVE
#define DIGI_DTR_INPUT_FLOW_CONTROL

#define DIGI_RTS_INACTIVE
#define DIGI_RTS_ACTIVE
#define DIGI_RTS_INPUT_FLOW_CONTROL
#define DIGI_RTS_TOGGLE

#define DIGI_FLUSH_TX
#define DIGI_FLUSH_RX
#define DIGI_RESUME_TX

#define DIGI_TRANSMIT_NOT_IDLE
#define DIGI_TRANSMIT_IDLE

#define DIGI_DISABLE
#define DIGI_ENABLE

#define DIGI_DEASSERT
#define DIGI_ASSERT

/* in band status codes */
#define DIGI_OVERRUN_ERROR
#define DIGI_PARITY_ERROR
#define DIGI_FRAMING_ERROR
#define DIGI_BREAK_ERROR

/* out of band status */
#define DIGI_NO_ERROR
#define DIGI_BAD_FIRST_PARAMETER
#define DIGI_BAD_SECOND_PARAMETER
#define DIGI_INVALID_LINE
#define DIGI_INVALID_OPCODE

/* input signals */
#define DIGI_READ_INPUT_SIGNALS_SLOT
#define DIGI_READ_INPUT_SIGNALS_ERR
#define DIGI_READ_INPUT_SIGNALS_BUSY
#define DIGI_READ_INPUT_SIGNALS_PE
#define DIGI_READ_INPUT_SIGNALS_CTS
#define DIGI_READ_INPUT_SIGNALS_DSR
#define DIGI_READ_INPUT_SIGNALS_RI
#define DIGI_READ_INPUT_SIGNALS_DCD


/* Structures */

struct digi_serial {};

struct digi_port {};


/* Local Function Declarations */

static int digi_write_oob_command(struct usb_serial_port *port,
	unsigned char *buf, int count, int interruptible);
static int digi_write_inb_command(struct usb_serial_port *port,
	unsigned char *buf, int count, unsigned long timeout);
static int digi_set_modem_signals(struct usb_serial_port *port,
	unsigned int modem_signals, int interruptible);
static int digi_transmit_idle(struct usb_serial_port *port,
	unsigned long timeout);
static void digi_rx_throttle(struct tty_struct *tty);
static void digi_rx_unthrottle(struct tty_struct *tty);
static void digi_set_termios(struct tty_struct *tty,
			     struct usb_serial_port *port,
			     const struct ktermios *old_termios);
static int digi_break_ctl(struct tty_struct *tty, int break_state);
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);
static void digi_write_bulk_callback(struct urb *urb);
static unsigned int digi_write_room(struct tty_struct *tty);
static unsigned 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 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 void 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);


static const struct usb_device_id id_table_combined[] =;

static const struct usb_device_id id_table_2[] =;

static const struct usb_device_id id_table_4[] =;

MODULE_DEVICE_TABLE(usb, id_table_combined);

/* device info needed for the Digi serial converter */

static struct usb_serial_driver digi_acceleport_2_device =;

static struct usb_serial_driver digi_acceleport_4_device =;

static struct usb_serial_driver * const serial_drivers[] =;

/* Functions */

/*
 *  Cond Wait Interruptible Timeout Irqrestore
 *
 *  Do spin_unlock_irqrestore and interruptible_sleep_on_timeout
 *  so that wake ups are not lost if they occur between the unlock
 *  and the sleep.  In other words, spin_unlock_irqrestore and
 *  interruptible_sleep_on_timeout are "atomic" with respect to
 *  wake ups.  This is used to implement condition variables.
 *
 *  interruptible_sleep_on_timeout is deprecated and has been replaced
 *  with the equivalent code.
 */

static long cond_wait_interruptible_timeout_irqrestore(
	wait_queue_head_t *q, long timeout,
	spinlock_t *lock, unsigned long flags)
__releases(lock)
{}

/*
 *  Digi Write OOB Command
 *
 *  Write commands on the out of band port.  Commands are 4
 *  bytes each, multiple commands can be sent at once, and
 *  no command will be split across USB packets.  Returns 0
 *  if successful, -EINTR if interrupted while sleeping and
 *  the interruptible flag is true, or a negative error
 *  returned by usb_submit_urb.
 */

static int digi_write_oob_command(struct usb_serial_port *port,
	unsigned char *buf, int count, int interruptible)
{}


/*
 *  Digi Write In Band Command
 *
 *  Write commands on the given port.  Commands are 4
 *  bytes each, multiple commands can be sent at once, and
 *  no command will be split across USB packets.  If timeout
 *  is non-zero, write in band command will return after
 *  waiting unsuccessfully for the URB status to clear for
 *  timeout ticks.  Returns 0 if successful, or a negative
 *  error returned by digi_write.
 */

static int digi_write_inb_command(struct usb_serial_port *port,
	unsigned char *buf, int count, unsigned long timeout)
{}


/*
 *  Digi Set Modem Signals
 *
 *  Sets or clears DTR and RTS on the port, according to the
 *  modem_signals argument.  Use TIOCM_DTR and TIOCM_RTS flags
 *  for the modem_signals argument.  Returns 0 if successful,
 *  -EINTR if interrupted while sleeping, or a non-zero error
 *  returned by usb_submit_urb.
 */

static int digi_set_modem_signals(struct usb_serial_port *port,
	unsigned int modem_signals, int interruptible)
{}

/*
 *  Digi Transmit Idle
 *
 *  Digi transmit idle waits, up to timeout ticks, for the transmitter
 *  to go idle.  It returns 0 if successful or a negative error.
 *
 *  There are race conditions here if more than one process is calling
 *  digi_transmit_idle on the same port at the same time.  However, this
 *  is only called from close, and only one process can be in close on a
 *  port at a time, so its ok.
 */

static int digi_transmit_idle(struct usb_serial_port *port,
	unsigned long timeout)
{}


static void digi_rx_throttle(struct tty_struct *tty)
{}


static void digi_rx_unthrottle(struct tty_struct *tty)
{}


static void digi_set_termios(struct tty_struct *tty,
			     struct usb_serial_port *port,
			     const struct ktermios *old_termios)
{}


static int digi_break_ctl(struct tty_struct *tty, int break_state)
{}


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)
{}

static void digi_write_bulk_callback(struct urb *urb)
{}

static unsigned int digi_write_room(struct tty_struct *tty)
{}

static unsigned int digi_chars_in_buffer(struct tty_struct *tty)
{}

static void digi_dtr_rts(struct usb_serial_port *port, int on)
{}

static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
{}


static void digi_close(struct usb_serial_port *port)
{}


/*
 *  Digi Startup Device
 *
 *  Starts reads on all ports.  Must be called AFTER startup, with
 *  urbs initialized.  Returns 0 if successful, non-zero error otherwise.
 */

static int digi_startup_device(struct usb_serial *serial)
{}

static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
{}

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 void digi_port_remove(struct usb_serial_port *port)
{}

static void digi_read_bulk_callback(struct urb *urb)
{}

/*
 *  Digi Read INB Callback
 *
 *  Digi Read INB Callback handles reads on the in band ports, sending
 *  the data on to the tty subsystem.  When called we know port and
 *  port->private are not NULL and port->serial has been validated.
 *  It returns 0 if successful, 1 if successful but the port is
 *  throttled, and -1 if the sanity checks failed.
 */

static int digi_read_inb_callback(struct urb *urb)
{}


/*
 *  Digi Read OOB Callback
 *
 *  Digi Read OOB Callback handles reads on the out of band port.
 *  When called we know port and port->private are not NULL and
 *  the port->serial is valid.  It returns 0 if successful, and
 *  -1 if the sanity checks failed.
 */

static int digi_read_oob_callback(struct urb *urb)
{}

module_usb_serial_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();