0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include <linux/kernel.h>
0035 #include <linux/errno.h>
0036 #include <linux/slab.h>
0037 #include <linux/tty.h>
0038 #include <linux/tty_driver.h>
0039 #include <linux/tty_flip.h>
0040 #include <linux/module.h>
0041 #include <linux/uaccess.h>
0042 #include <asm/unaligned.h>
0043 #include <linux/usb.h>
0044 #include <linux/usb/serial.h>
0045 #include "kl5kusb105.h"
0046
0047 #define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>, Johan Hovold <jhovold@gmail.com>"
0048 #define DRIVER_DESC "KLSI KL5KUSB105 chipset USB->Serial Converter driver"
0049
0050
0051
0052
0053
0054 static int klsi_105_port_probe(struct usb_serial_port *port);
0055 static void klsi_105_port_remove(struct usb_serial_port *port);
0056 static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port);
0057 static void klsi_105_close(struct usb_serial_port *port);
0058 static void klsi_105_set_termios(struct tty_struct *tty,
0059 struct usb_serial_port *port, struct ktermios *old);
0060 static int klsi_105_tiocmget(struct tty_struct *tty);
0061 static void klsi_105_process_read_urb(struct urb *urb);
0062 static int klsi_105_prepare_write_buffer(struct usb_serial_port *port,
0063 void *dest, size_t size);
0064
0065
0066
0067
0068 static const struct usb_device_id id_table[] = {
0069 { USB_DEVICE(PALMCONNECT_VID, PALMCONNECT_PID) },
0070 { }
0071 };
0072
0073 MODULE_DEVICE_TABLE(usb, id_table);
0074
0075 static struct usb_serial_driver kl5kusb105d_device = {
0076 .driver = {
0077 .owner = THIS_MODULE,
0078 .name = "kl5kusb105d",
0079 },
0080 .description = "KL5KUSB105D / PalmConnect",
0081 .id_table = id_table,
0082 .num_ports = 1,
0083 .bulk_out_size = 64,
0084 .open = klsi_105_open,
0085 .close = klsi_105_close,
0086 .set_termios = klsi_105_set_termios,
0087 .tiocmget = klsi_105_tiocmget,
0088 .port_probe = klsi_105_port_probe,
0089 .port_remove = klsi_105_port_remove,
0090 .throttle = usb_serial_generic_throttle,
0091 .unthrottle = usb_serial_generic_unthrottle,
0092 .process_read_urb = klsi_105_process_read_urb,
0093 .prepare_write_buffer = klsi_105_prepare_write_buffer,
0094 };
0095
0096 static struct usb_serial_driver * const serial_drivers[] = {
0097 &kl5kusb105d_device, NULL
0098 };
0099
0100 struct klsi_105_port_settings {
0101 u8 pktlen;
0102 u8 baudrate;
0103 u8 databits;
0104 u8 unknown1;
0105 u8 unknown2;
0106 };
0107
0108 struct klsi_105_private {
0109 struct klsi_105_port_settings cfg;
0110 unsigned long line_state;
0111 spinlock_t lock;
0112 };
0113
0114
0115
0116
0117
0118
0119
0120 #define KLSI_TIMEOUT 5000
0121
0122 static int klsi_105_chg_port_settings(struct usb_serial_port *port,
0123 struct klsi_105_port_settings *settings)
0124 {
0125 int rc;
0126
0127 rc = usb_control_msg_send(port->serial->dev,
0128 0,
0129 KL5KUSB105A_SIO_SET_DATA,
0130 USB_TYPE_VENDOR | USB_DIR_OUT |
0131 USB_RECIP_INTERFACE,
0132 0,
0133 0,
0134 settings,
0135 sizeof(struct klsi_105_port_settings),
0136 KLSI_TIMEOUT,
0137 GFP_KERNEL);
0138 if (rc)
0139 dev_err(&port->dev,
0140 "Change port settings failed (error = %d)\n", rc);
0141
0142 dev_dbg(&port->dev,
0143 "pktlen %u, baudrate 0x%02x, databits %u, u1 %u, u2 %u\n",
0144 settings->pktlen, settings->baudrate, settings->databits,
0145 settings->unknown1, settings->unknown2);
0146
0147 return rc;
0148 }
0149
0150
0151
0152
0153
0154 static int klsi_105_get_line_state(struct usb_serial_port *port,
0155 unsigned long *state)
0156 {
0157 u16 status;
0158 int rc;
0159
0160 rc = usb_control_msg_recv(port->serial->dev, 0,
0161 KL5KUSB105A_SIO_POLL,
0162 USB_TYPE_VENDOR | USB_DIR_IN,
0163 0,
0164 0,
0165 &status, sizeof(status),
0166 10000,
0167 GFP_KERNEL);
0168 if (rc) {
0169 dev_err(&port->dev, "reading line status failed: %d\n", rc);
0170 return rc;
0171 }
0172
0173 le16_to_cpus(&status);
0174
0175 dev_dbg(&port->dev, "read status %04x\n", status);
0176
0177 *state = ((status & KL5KUSB105A_DSR) ? TIOCM_DSR : 0) |
0178 ((status & KL5KUSB105A_CTS) ? TIOCM_CTS : 0);
0179
0180 return 0;
0181 }
0182
0183
0184
0185
0186
0187
0188 static int klsi_105_port_probe(struct usb_serial_port *port)
0189 {
0190 struct klsi_105_private *priv;
0191
0192 priv = kmalloc(sizeof(*priv), GFP_KERNEL);
0193 if (!priv)
0194 return -ENOMEM;
0195
0196
0197 priv->cfg.pktlen = 5;
0198 priv->cfg.baudrate = kl5kusb105a_sio_b9600;
0199 priv->cfg.databits = kl5kusb105a_dtb_8;
0200 priv->cfg.unknown1 = 0;
0201 priv->cfg.unknown2 = 1;
0202
0203 priv->line_state = 0;
0204
0205 spin_lock_init(&priv->lock);
0206
0207 usb_set_serial_port_data(port, priv);
0208
0209 return 0;
0210 }
0211
0212 static void klsi_105_port_remove(struct usb_serial_port *port)
0213 {
0214 struct klsi_105_private *priv;
0215
0216 priv = usb_get_serial_port_data(port);
0217 kfree(priv);
0218 }
0219
0220 static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
0221 {
0222 struct klsi_105_private *priv = usb_get_serial_port_data(port);
0223 int retval = 0;
0224 int rc;
0225 unsigned long line_state;
0226 struct klsi_105_port_settings cfg;
0227 unsigned long flags;
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237 cfg.pktlen = 5;
0238 cfg.baudrate = kl5kusb105a_sio_b9600;
0239 cfg.databits = kl5kusb105a_dtb_8;
0240 cfg.unknown1 = 0;
0241 cfg.unknown2 = 1;
0242 klsi_105_chg_port_settings(port, &cfg);
0243
0244 spin_lock_irqsave(&priv->lock, flags);
0245 priv->cfg.pktlen = cfg.pktlen;
0246 priv->cfg.baudrate = cfg.baudrate;
0247 priv->cfg.databits = cfg.databits;
0248 priv->cfg.unknown1 = cfg.unknown1;
0249 priv->cfg.unknown2 = cfg.unknown2;
0250 spin_unlock_irqrestore(&priv->lock, flags);
0251
0252
0253 rc = usb_serial_generic_open(tty, port);
0254 if (rc)
0255 return rc;
0256
0257 rc = usb_control_msg(port->serial->dev,
0258 usb_sndctrlpipe(port->serial->dev, 0),
0259 KL5KUSB105A_SIO_CONFIGURE,
0260 USB_TYPE_VENDOR|USB_DIR_OUT|USB_RECIP_INTERFACE,
0261 KL5KUSB105A_SIO_CONFIGURE_READ_ON,
0262 0,
0263 NULL,
0264 0,
0265 KLSI_TIMEOUT);
0266 if (rc < 0) {
0267 dev_err(&port->dev, "Enabling read failed (error = %d)\n", rc);
0268 retval = rc;
0269 goto err_generic_close;
0270 } else
0271 dev_dbg(&port->dev, "%s - enabled reading\n", __func__);
0272
0273 rc = klsi_105_get_line_state(port, &line_state);
0274 if (rc < 0) {
0275 retval = rc;
0276 goto err_disable_read;
0277 }
0278
0279 spin_lock_irqsave(&priv->lock, flags);
0280 priv->line_state = line_state;
0281 spin_unlock_irqrestore(&priv->lock, flags);
0282 dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__,
0283 line_state);
0284
0285 return 0;
0286
0287 err_disable_read:
0288 usb_control_msg(port->serial->dev,
0289 usb_sndctrlpipe(port->serial->dev, 0),
0290 KL5KUSB105A_SIO_CONFIGURE,
0291 USB_TYPE_VENDOR | USB_DIR_OUT,
0292 KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
0293 0,
0294 NULL, 0,
0295 KLSI_TIMEOUT);
0296 err_generic_close:
0297 usb_serial_generic_close(port);
0298
0299 return retval;
0300 }
0301
0302 static void klsi_105_close(struct usb_serial_port *port)
0303 {
0304 int rc;
0305
0306
0307 rc = usb_control_msg(port->serial->dev,
0308 usb_sndctrlpipe(port->serial->dev, 0),
0309 KL5KUSB105A_SIO_CONFIGURE,
0310 USB_TYPE_VENDOR | USB_DIR_OUT,
0311 KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
0312 0,
0313 NULL, 0,
0314 KLSI_TIMEOUT);
0315 if (rc < 0)
0316 dev_err(&port->dev, "failed to disable read: %d\n", rc);
0317
0318
0319 usb_serial_generic_close(port);
0320 }
0321
0322
0323
0324
0325
0326 #define KLSI_HDR_LEN 2
0327 static int klsi_105_prepare_write_buffer(struct usb_serial_port *port,
0328 void *dest, size_t size)
0329 {
0330 unsigned char *buf = dest;
0331 int count;
0332
0333 count = kfifo_out_locked(&port->write_fifo, buf + KLSI_HDR_LEN, size,
0334 &port->lock);
0335 put_unaligned_le16(count, buf);
0336
0337 return count + KLSI_HDR_LEN;
0338 }
0339
0340
0341
0342 static void klsi_105_process_read_urb(struct urb *urb)
0343 {
0344 struct usb_serial_port *port = urb->context;
0345 unsigned char *data = urb->transfer_buffer;
0346 unsigned len;
0347
0348
0349 if (!urb->actual_length)
0350 return;
0351
0352 if (urb->actual_length <= KLSI_HDR_LEN) {
0353 dev_dbg(&port->dev, "%s - malformed packet\n", __func__);
0354 return;
0355 }
0356
0357 len = get_unaligned_le16(data);
0358 if (len > urb->actual_length - KLSI_HDR_LEN) {
0359 dev_dbg(&port->dev, "%s - packet length mismatch\n", __func__);
0360 len = urb->actual_length - KLSI_HDR_LEN;
0361 }
0362
0363 tty_insert_flip_string(&port->port, data + KLSI_HDR_LEN, len);
0364 tty_flip_buffer_push(&port->port);
0365 }
0366
0367 static void klsi_105_set_termios(struct tty_struct *tty,
0368 struct usb_serial_port *port,
0369 struct ktermios *old_termios)
0370 {
0371 struct klsi_105_private *priv = usb_get_serial_port_data(port);
0372 struct device *dev = &port->dev;
0373 unsigned int iflag = tty->termios.c_iflag;
0374 unsigned int old_iflag = old_termios->c_iflag;
0375 unsigned int cflag = tty->termios.c_cflag;
0376 unsigned int old_cflag = old_termios->c_cflag;
0377 struct klsi_105_port_settings *cfg;
0378 unsigned long flags;
0379 speed_t baud;
0380
0381 cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
0382 if (!cfg)
0383 return;
0384
0385
0386 spin_lock_irqsave(&priv->lock, flags);
0387
0388
0389
0390
0391 baud = tty_get_baud_rate(tty);
0392
0393 switch (baud) {
0394 case 0:
0395 break;
0396 case 1200:
0397 priv->cfg.baudrate = kl5kusb105a_sio_b1200;
0398 break;
0399 case 2400:
0400 priv->cfg.baudrate = kl5kusb105a_sio_b2400;
0401 break;
0402 case 4800:
0403 priv->cfg.baudrate = kl5kusb105a_sio_b4800;
0404 break;
0405 case 9600:
0406 priv->cfg.baudrate = kl5kusb105a_sio_b9600;
0407 break;
0408 case 19200:
0409 priv->cfg.baudrate = kl5kusb105a_sio_b19200;
0410 break;
0411 case 38400:
0412 priv->cfg.baudrate = kl5kusb105a_sio_b38400;
0413 break;
0414 case 57600:
0415 priv->cfg.baudrate = kl5kusb105a_sio_b57600;
0416 break;
0417 case 115200:
0418 priv->cfg.baudrate = kl5kusb105a_sio_b115200;
0419 break;
0420 default:
0421 dev_dbg(dev, "unsupported baudrate, using 9600\n");
0422 priv->cfg.baudrate = kl5kusb105a_sio_b9600;
0423 baud = 9600;
0424 break;
0425 }
0426
0427
0428
0429
0430
0431
0432
0433
0434 tty_encode_baud_rate(tty, baud, baud);
0435
0436 if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
0437
0438 switch (cflag & CSIZE) {
0439 case CS5:
0440 dev_dbg(dev, "%s - 5 bits/byte not supported\n", __func__);
0441 spin_unlock_irqrestore(&priv->lock, flags);
0442 goto err;
0443 case CS6:
0444 dev_dbg(dev, "%s - 6 bits/byte not supported\n", __func__);
0445 spin_unlock_irqrestore(&priv->lock, flags);
0446 goto err;
0447 case CS7:
0448 priv->cfg.databits = kl5kusb105a_dtb_7;
0449 break;
0450 case CS8:
0451 priv->cfg.databits = kl5kusb105a_dtb_8;
0452 break;
0453 default:
0454 dev_err(dev, "CSIZE was not CS5-CS8, using default of 8\n");
0455 priv->cfg.databits = kl5kusb105a_dtb_8;
0456 break;
0457 }
0458 }
0459
0460
0461
0462
0463 if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
0464 || (cflag & CSTOPB) != (old_cflag & CSTOPB)) {
0465
0466 tty->termios.c_cflag &= ~(PARENB|PARODD|CSTOPB);
0467 }
0468
0469
0470
0471
0472 if ((iflag & IXOFF) != (old_iflag & IXOFF)
0473 || (iflag & IXON) != (old_iflag & IXON)
0474 || (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
0475
0476 tty->termios.c_cflag &= ~CRTSCTS;
0477 }
0478 memcpy(cfg, &priv->cfg, sizeof(*cfg));
0479 spin_unlock_irqrestore(&priv->lock, flags);
0480
0481
0482 klsi_105_chg_port_settings(port, cfg);
0483 err:
0484 kfree(cfg);
0485 }
0486
0487 static int klsi_105_tiocmget(struct tty_struct *tty)
0488 {
0489 struct usb_serial_port *port = tty->driver_data;
0490 struct klsi_105_private *priv = usb_get_serial_port_data(port);
0491 unsigned long flags;
0492 int rc;
0493 unsigned long line_state;
0494
0495 rc = klsi_105_get_line_state(port, &line_state);
0496 if (rc < 0) {
0497 dev_err(&port->dev,
0498 "Reading line control failed (error = %d)\n", rc);
0499
0500 return rc;
0501 }
0502
0503 spin_lock_irqsave(&priv->lock, flags);
0504 priv->line_state = line_state;
0505 spin_unlock_irqrestore(&priv->lock, flags);
0506 dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__, line_state);
0507 return (int)line_state;
0508 }
0509
0510 module_usb_serial_driver(serial_drivers, id_table);
0511
0512 MODULE_AUTHOR(DRIVER_AUTHOR);
0513 MODULE_DESCRIPTION(DRIVER_DESC);
0514 MODULE_LICENSE("GPL");