// 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 (pberger@brimson.com)
* Al Borchers (borchers@steinerpoint.com)
*/
#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/workqueue.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 "Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>"
#define DRIVER_DESC "Digi AccelePort USB-2/USB-4 Serial Converter driver"
/* 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 8
/* 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 64
/* retry timeout while sleeping */
#define DIGI_RETRY_TIMEOUT (HZ/10)
/* 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 (5*HZ)
/* AccelePort USB Defines */
/* ids */
#define DIGI_VENDOR_ID 0x05c5
#define DIGI_2_ID 0x0002 /* USB-2 */
#define DIGI_4_ID 0x0004 /* USB-4 */
/* 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 0 /* INB, OOB */
#define DIGI_CMD_SET_WORD_SIZE 1 /* INB, OOB */
#define DIGI_CMD_SET_PARITY 2 /* INB, OOB */
#define DIGI_CMD_SET_STOP_BITS 3 /* INB, OOB */
#define DIGI_CMD_SET_INPUT_FLOW_CONTROL 4 /* INB, OOB */
#define DIGI_CMD_SET_OUTPUT_FLOW_CONTROL 5 /* INB, OOB */
#define DIGI_CMD_SET_DTR_SIGNAL 6 /* INB, OOB */
#define DIGI_CMD_SET_RTS_SIGNAL 7 /* INB, OOB */
#define DIGI_CMD_READ_INPUT_SIGNALS 8 /* OOB */
#define DIGI_CMD_IFLUSH_FIFO 9 /* OOB */
#define DIGI_CMD_RECEIVE_ENABLE 10 /* INB, OOB */
#define DIGI_CMD_BREAK_CONTROL 11 /* INB, OOB */
#define DIGI_CMD_LOCAL_LOOPBACK 12 /* INB, OOB */
#define DIGI_CMD_TRANSMIT_IDLE 13 /* INB, OOB */
#define DIGI_CMD_READ_UART_REGISTER 14 /* OOB */
#define DIGI_CMD_WRITE_UART_REGISTER 15 /* INB, OOB */
#define DIGI_CMD_AND_UART_REGISTER 16 /* INB, OOB */
#define DIGI_CMD_OR_UART_REGISTER 17 /* INB, OOB */
#define DIGI_CMD_SEND_DATA 18 /* INB */
#define DIGI_CMD_RECEIVE_DATA 19 /* INB */
#define DIGI_CMD_RECEIVE_DISABLE 20 /* INB */
#define DIGI_CMD_GET_PORT_TYPE 21 /* OOB */
/* baud rates */
#define DIGI_BAUD_50 0
#define DIGI_BAUD_75 1
#define DIGI_BAUD_110 2
#define DIGI_BAUD_150 3
#define DIGI_BAUD_200 4
#define DIGI_BAUD_300 5
#define DIGI_BAUD_600 6
#define DIGI_BAUD_1200 7
#define DIGI_BAUD_1800 8
#define DIGI_BAUD_2400 9
#define DIGI_BAUD_4800 10
#define DIGI_BAUD_7200 11
#define DIGI_BAUD_9600 12
#define DIGI_BAUD_14400 13
#define DIGI_BAUD_19200 14
#define DIGI_BAUD_28800 15
#define DIGI_BAUD_38400 16
#define DIGI_BAUD_57600 17
#define DIGI_BAUD_76800 18
#define DIGI_BAUD_115200 19
#define DIGI_BAUD_153600 20
#define DIGI_BAUD_230400 21
#define DIGI_BAUD_460800 22
/* arguments */
#define DIGI_WORD_SIZE_5 0
#define DIGI_WORD_SIZE_6 1
#define DIGI_WORD_SIZE_7 2
#define DIGI_WORD_SIZE_8 3
#define DIGI_PARITY_NONE 0
#define DIGI_PARITY_ODD 1
#define DIGI_PARITY_EVEN 2
#define DIGI_PARITY_MARK 3
#define DIGI_PARITY_SPACE 4
#define DIGI_STOP_BITS_1 0
#define DIGI_STOP_BITS_2 1
#define DIGI_INPUT_FLOW_CONTROL_XON_XOFF 1
#define DIGI_INPUT_FLOW_CONTROL_RTS 2
#define DIGI_INPUT_FLOW_CONTROL_DTR 4
#define DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF 1
#define DIGI_OUTPUT_FLOW_CONTROL_CTS 2
#define DIGI_OUTPUT_FLOW_CONTROL_DSR 4
#define DIGI_DTR_INACTIVE 0
#define DIGI_DTR_ACTIVE 1
#define DIGI_DTR_INPUT_FLOW_CONTROL 2
#define DIGI_RTS_INACTIVE 0
#define DIGI_RTS_ACTIVE 1
#define DIGI_RTS_INPUT_FLOW_CONTROL 2
#define DIGI_RTS_TOGGLE 3
#define DIGI_FLUSH_TX 1
#define DIGI_FLUSH_RX 2
#define DIGI_RESUME_TX 4 /* clears xoff condition */
#define DIGI_TRANSMIT_NOT_IDLE 0
#define DIGI_TRANSMIT_IDLE 1
#define DIGI_DISABLE 0
#define DIGI_ENABLE 1
#define DIGI_DEASSERT 0
#define DIGI_ASSERT 1
/* in band status codes */
#define DIGI_OVERRUN_ERROR 4
#define DIGI_PARITY_ERROR 8
#define DIGI_FRAMING_ERROR 16
#define DIGI_BREAK_ERROR 32
/* out of band status */
#define DIGI_NO_ERROR 0
#define DIGI_BAD_FIRST_PARAMETER 1
#define DIGI_BAD_SECOND_PARAMETER 2
#define DIGI_INVALID_LINE 3
#define DIGI_INVALID_OPCODE 4
/* input signals */
#define DIGI_READ_INPUT_SIGNALS_SLOT 1
#define DIGI_READ_INPUT_SIGNALS_ERR 2
#define DIGI_READ_INPUT_SIGNALS_BUSY 4
#define DIGI_READ_INPUT_SIGNALS_PE 8
#define DIGI_READ_INPUT_SIGNALS_CTS 16
#define DIGI_READ_INPUT_SIGNALS_DSR 32
#define DIGI_READ_INPUT_SIGNALS_RI 64
#define DIGI_READ_INPUT_SIGNALS_DCD 128
/* Structures */
struct digi_serial {
spinlock_t ds_serial_lock;
struct usb_serial_port *ds_oob_port; /* out-of-band port */
int ds_oob_port_num; /* index of out-of-band port */
int ds_device_started;
};
struct digi_port {
spinlock_t dp_port_lock;
int dp_port_num;
int dp_out_buf_len;
unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE];
int dp_write_urb_in_use;
unsigned int dp_modem_signals;
int dp_transmit_idle;
wait_queue_head_t dp_transmit_idle_wait;
int dp_throttled;
int dp_throttle_restart;
wait_queue_head_t dp_flush_wait;
wait_queue_head_t dp_close_wait; /* wait queue for close */
struct work_struct dp_wakeup_work;
struct usb_serial_port *dp_port;
};
/* Local Function Declarations */
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);
static int digi_write_inb_command(struct usb_serial_port *port,
unsigned char *buf, int count, unsigned long timeout);
static i
|