// SPDX-License-Identifier: GPL-2.0+ /* * KLSI KL5KUSB105 chip RS232 converter driver * * Copyright (C) 2010 Johan Hovold <jhovold@gmail.com> * Copyright (C) 2001 Utz-Uwe Haus <haus@uuhaus.de> * * All information about the device was acquired using SniffUSB ans snoopUSB * on Windows98. * It was written out of frustration with the PalmConnect USB Serial adapter * sold by Palm Inc. * Neither Palm, nor their contractor (MCCI) or their supplier (KLSI) provided * information that was not already available. * * It seems that KLSI bought some silicon-design information from ScanLogic, * whose SL11R processor is at the core of the KL5KUSB chipset from KLSI. * KLSI has firmware available for their devices; it is probable that the * firmware differs from that used by KLSI in their products. If you have an * original KLSI device and can provide some information on it, I would be * most interested in adding support for it here. If you have any information * on the protocol used (or find errors in my reverse-engineered stuff), please * let me know. * * The code was only tested with a PalmConnect USB adapter; if you * are adventurous, try it with any KLSI-based device and let me know how it * breaks so that I can fix it!
*/
/* TODO: * check modem line signals * implement handshaking or decide that we do not support it
*/
/* * All of the device info needed for the KLSI converters.
*/ staticconststruct usb_device_id id_table[] = {
{ USB_DEVICE(PALMCONNECT_VID, PALMCONNECT_PID) },
{ } /* Terminating entry */
};
/* * Read line control via vendor command and return result through * the state pointer.
*/ staticint klsi_105_get_line_state(struct usb_serial_port *port, unsignedlong *state)
{
u16 status; int rc;
rc = usb_control_msg_recv(port->serial->dev, 0,
KL5KUSB105A_SIO_POLL,
USB_TYPE_VENDOR | USB_DIR_IN,
0, /* value */
0, /* index */
&status, sizeof(status),
10000,
GFP_KERNEL); if (rc) {
dev_err(&port->dev, "reading line status failed: %d\n", rc); return rc;
}
le16_to_cpus(&status);
dev_dbg(&port->dev, "read status %04x\n", status);
/* Do a defined restart: * Set up sane default baud rate and send the 'READ_ON' * vendor command. * FIXME: set modem line control (how?) * Then read the modem line control and store values in * priv->line_state.
*/
/* shutdown our bulk reads and writes */
usb_serial_generic_close(port);
}
/* We need to write a complete 64-byte data block and encode the * number actually sent in the first double-byte, LSB-order. That * leaves at most 62 bytes of payload.
*/ #define KLSI_HDR_LEN 2 staticint klsi_105_prepare_write_buffer(struct usb_serial_port *port, void *dest, size_t size)
{ unsignedchar *buf = dest; int count;
/* The data received is preceded by a length double-byte in LSB-first order.
*/ staticvoid klsi_105_process_read_urb(struct urb *urb)
{ struct usb_serial_port *port = urb->context; unsignedchar *data = urb->transfer_buffer; unsigned len;
/* empty urbs seem to happen, we ignore them */ if (!urb->actual_length) return;
switch (baud) { case 0: /* handled below */ break; case 1200:
priv->cfg.baudrate = kl5kusb105a_sio_b1200; break; case 2400:
priv->cfg.baudrate = kl5kusb105a_sio_b2400; break; case 4800:
priv->cfg.baudrate = kl5kusb105a_sio_b4800; break; case 9600:
priv->cfg.baudrate = kl5kusb105a_sio_b9600; break; case 19200:
priv->cfg.baudrate = kl5kusb105a_sio_b19200; break; case 38400:
priv->cfg.baudrate = kl5kusb105a_sio_b38400; break; case 57600:
priv->cfg.baudrate = kl5kusb105a_sio_b57600; break; case 115200:
priv->cfg.baudrate = kl5kusb105a_sio_b115200; break; default:
dev_dbg(dev, "unsupported baudrate, using 9600\n");
priv->cfg.baudrate = kl5kusb105a_sio_b9600;
baud = 9600; break;
}
/* * FIXME: implement B0 handling * * Maybe this should be simulated by sending read disable and read * enable messages?
*/
tty_encode_baud_rate(tty, baud, baud);
if ((cflag & CSIZE) != (old_cflag & CSIZE)) { /* set the number of data bits */ switch (cflag & CSIZE) { case CS5:
dev_dbg(dev, "%s - 5 bits/byte not supported\n", __func__);
spin_unlock_irqrestore(&priv->lock, flags); goto err; case CS6:
dev_dbg(dev, "%s - 6 bits/byte not supported\n", __func__);
spin_unlock_irqrestore(&priv->lock, flags); goto err; case CS7:
priv->cfg.databits = kl5kusb105a_dtb_7; break; case CS8:
priv->cfg.databits = kl5kusb105a_dtb_8; break; default:
dev_err(dev, "CSIZE was not CS5-CS8, using default of 8\n");
priv->cfg.databits = kl5kusb105a_dtb_8; break;
}
}
/* * Update line control register (LCR)
*/ if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
|| (cflag & CSTOPB) != (old_cflag & CSTOPB)) { /* Not currently supported */
tty->termios.c_cflag &= ~(PARENB|PARODD|CSTOPB);
} /* * Set flow control: well, I do not really now how to handle DTR/RTS. * Just do what we have seen with SniffUSB on Win98.
*/ if ((iflag & IXOFF) != (old_iflag & IXOFF)
|| (iflag & IXON) != (old_iflag & IXON)
|| (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { /* Not currently supported */
tty->termios.c_cflag &= ~CRTSCTS;
}
memcpy(cfg, &priv->cfg, sizeof(*cfg));
spin_unlock_irqrestore(&priv->lock, flags);
/* now commit changes to device */
klsi_105_chg_port_settings(port, cfg);
err:
kfree(cfg);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.