root/drivers/usb/serial/kl5kusb105.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. klsi_105_chg_port_settings
  2. klsi_105_status2linestate
  3. klsi_105_get_line_state
  4. klsi_105_port_probe
  5. klsi_105_port_remove
  6. klsi_105_open
  7. klsi_105_close
  8. klsi_105_prepare_write_buffer
  9. klsi_105_process_read_urb
  10. klsi_105_set_termios
  11. klsi_105_tiocmget

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * KLSI KL5KUSB105 chip RS232 converter driver
   4  *
   5  *   Copyright (C) 2010 Johan Hovold <jhovold@gmail.com>
   6  *   Copyright (C) 2001 Utz-Uwe Haus <haus@uuhaus.de>
   7  *
   8  * All information about the device was acquired using SniffUSB ans snoopUSB
   9  * on Windows98.
  10  * It was written out of frustration with the PalmConnect USB Serial adapter
  11  * sold by Palm Inc.
  12  * Neither Palm, nor their contractor (MCCI) or their supplier (KLSI) provided
  13  * information that was not already available.
  14  *
  15  * It seems that KLSI bought some silicon-design information from ScanLogic,
  16  * whose SL11R processor is at the core of the KL5KUSB chipset from KLSI.
  17  * KLSI has firmware available for their devices; it is probable that the
  18  * firmware differs from that used by KLSI in their products. If you have an
  19  * original KLSI device and can provide some information on it, I would be
  20  * most interested in adding support for it here. If you have any information
  21  * on the protocol used (or find errors in my reverse-engineered stuff), please
  22  * let me know.
  23  *
  24  * The code was only tested with a PalmConnect USB adapter; if you
  25  * are adventurous, try it with any KLSI-based device and let me know how it
  26  * breaks so that I can fix it!
  27  */
  28 
  29 /* TODO:
  30  *      check modem line signals
  31  *      implement handshaking or decide that we do not support it
  32  */
  33 
  34 #include <linux/kernel.h>
  35 #include <linux/errno.h>
  36 #include <linux/slab.h>
  37 #include <linux/tty.h>
  38 #include <linux/tty_driver.h>
  39 #include <linux/tty_flip.h>
  40 #include <linux/module.h>
  41 #include <linux/uaccess.h>
  42 #include <asm/unaligned.h>
  43 #include <linux/usb.h>
  44 #include <linux/usb/serial.h>
  45 #include "kl5kusb105.h"
  46 
  47 #define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>, Johan Hovold <jhovold@gmail.com>"
  48 #define DRIVER_DESC "KLSI KL5KUSB105 chipset USB->Serial Converter driver"
  49 
  50 
  51 /*
  52  * Function prototypes
  53  */
  54 static int klsi_105_port_probe(struct usb_serial_port *port);
  55 static int klsi_105_port_remove(struct usb_serial_port *port);
  56 static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port);
  57 static void klsi_105_close(struct usb_serial_port *port);
  58 static void klsi_105_set_termios(struct tty_struct *tty,
  59                         struct usb_serial_port *port, struct ktermios *old);
  60 static int  klsi_105_tiocmget(struct tty_struct *tty);
  61 static void klsi_105_process_read_urb(struct urb *urb);
  62 static int klsi_105_prepare_write_buffer(struct usb_serial_port *port,
  63                                                 void *dest, size_t size);
  64 
  65 /*
  66  * All of the device info needed for the KLSI converters.
  67  */
  68 static const struct usb_device_id id_table[] = {
  69         { USB_DEVICE(PALMCONNECT_VID, PALMCONNECT_PID) },
  70         { }             /* Terminating entry */
  71 };
  72 
  73 MODULE_DEVICE_TABLE(usb, id_table);
  74 
  75 static struct usb_serial_driver kl5kusb105d_device = {
  76         .driver = {
  77                 .owner =        THIS_MODULE,
  78                 .name =         "kl5kusb105d",
  79         },
  80         .description =          "KL5KUSB105D / PalmConnect",
  81         .id_table =             id_table,
  82         .num_ports =            1,
  83         .bulk_out_size =        64,
  84         .open =                 klsi_105_open,
  85         .close =                klsi_105_close,
  86         .set_termios =          klsi_105_set_termios,
  87         .tiocmget =             klsi_105_tiocmget,
  88         .port_probe =           klsi_105_port_probe,
  89         .port_remove =          klsi_105_port_remove,
  90         .throttle =             usb_serial_generic_throttle,
  91         .unthrottle =           usb_serial_generic_unthrottle,
  92         .process_read_urb =     klsi_105_process_read_urb,
  93         .prepare_write_buffer = klsi_105_prepare_write_buffer,
  94 };
  95 
  96 static struct usb_serial_driver * const serial_drivers[] = {
  97         &kl5kusb105d_device, NULL
  98 };
  99 
 100 struct klsi_105_port_settings {
 101         u8      pktlen;         /* always 5, it seems */
 102         u8      baudrate;
 103         u8      databits;
 104         u8      unknown1;
 105         u8      unknown2;
 106 };
 107 
 108 struct klsi_105_private {
 109         struct klsi_105_port_settings   cfg;
 110         unsigned long                   line_state; /* modem line settings */
 111         spinlock_t                      lock;
 112 };
 113 
 114 
 115 /*
 116  * Handle vendor specific USB requests
 117  */
 118 
 119 
 120 #define KLSI_TIMEOUT     5000 /* default urb timeout */
 121 
 122 static int klsi_105_chg_port_settings(struct usb_serial_port *port,
 123                                       struct klsi_105_port_settings *settings)
 124 {
 125         int rc;
 126 
 127         rc = usb_control_msg(port->serial->dev,
 128                         usb_sndctrlpipe(port->serial->dev, 0),
 129                         KL5KUSB105A_SIO_SET_DATA,
 130                         USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_INTERFACE,
 131                         0, /* value */
 132                         0, /* index */
 133                         settings,
 134                         sizeof(struct klsi_105_port_settings),
 135                         KLSI_TIMEOUT);
 136         if (rc < 0)
 137                 dev_err(&port->dev,
 138                         "Change port settings failed (error = %d)\n", rc);
 139 
 140         dev_dbg(&port->dev,
 141                 "pktlen %u, baudrate 0x%02x, databits %u, u1 %u, u2 %u\n",
 142                 settings->pktlen, settings->baudrate, settings->databits,
 143                 settings->unknown1, settings->unknown2);
 144 
 145         return rc;
 146 }
 147 
 148 /* translate a 16-bit status value from the device to linux's TIO bits */
 149 static unsigned long klsi_105_status2linestate(const __u16 status)
 150 {
 151         unsigned long res = 0;
 152 
 153         res =   ((status & KL5KUSB105A_DSR) ? TIOCM_DSR : 0)
 154               | ((status & KL5KUSB105A_CTS) ? TIOCM_CTS : 0)
 155               ;
 156 
 157         return res;
 158 }
 159 
 160 /*
 161  * Read line control via vendor command and return result through
 162  * *line_state_p
 163  */
 164 /* It seems that the status buffer has always only 2 bytes length */
 165 #define KLSI_STATUSBUF_LEN      2
 166 static int klsi_105_get_line_state(struct usb_serial_port *port,
 167                                    unsigned long *line_state_p)
 168 {
 169         int rc;
 170         u8 *status_buf;
 171         __u16 status;
 172 
 173         status_buf = kmalloc(KLSI_STATUSBUF_LEN, GFP_KERNEL);
 174         if (!status_buf)
 175                 return -ENOMEM;
 176 
 177         status_buf[0] = 0xff;
 178         status_buf[1] = 0xff;
 179         rc = usb_control_msg(port->serial->dev,
 180                              usb_rcvctrlpipe(port->serial->dev, 0),
 181                              KL5KUSB105A_SIO_POLL,
 182                              USB_TYPE_VENDOR | USB_DIR_IN,
 183                              0, /* value */
 184                              0, /* index */
 185                              status_buf, KLSI_STATUSBUF_LEN,
 186                              10000
 187                              );
 188         if (rc != KLSI_STATUSBUF_LEN) {
 189                 dev_err(&port->dev, "reading line status failed: %d\n", rc);
 190                 if (rc >= 0)
 191                         rc = -EIO;
 192         } else {
 193                 status = get_unaligned_le16(status_buf);
 194 
 195                 dev_dbg(&port->dev, "read status %02x %02x\n",
 196                         status_buf[0], status_buf[1]);
 197 
 198                 *line_state_p = klsi_105_status2linestate(status);
 199         }
 200 
 201         kfree(status_buf);
 202         return rc;
 203 }
 204 
 205 
 206 /*
 207  * Driver's tty interface functions
 208  */
 209 
 210 static int klsi_105_port_probe(struct usb_serial_port *port)
 211 {
 212         struct klsi_105_private *priv;
 213 
 214         priv = kmalloc(sizeof(*priv), GFP_KERNEL);
 215         if (!priv)
 216                 return -ENOMEM;
 217 
 218         /* set initial values for control structures */
 219         priv->cfg.pktlen    = 5;
 220         priv->cfg.baudrate  = kl5kusb105a_sio_b9600;
 221         priv->cfg.databits  = kl5kusb105a_dtb_8;
 222         priv->cfg.unknown1  = 0;
 223         priv->cfg.unknown2  = 1;
 224 
 225         priv->line_state    = 0;
 226 
 227         spin_lock_init(&priv->lock);
 228 
 229         usb_set_serial_port_data(port, priv);
 230 
 231         return 0;
 232 }
 233 
 234 static int klsi_105_port_remove(struct usb_serial_port *port)
 235 {
 236         struct klsi_105_private *priv;
 237 
 238         priv = usb_get_serial_port_data(port);
 239         kfree(priv);
 240 
 241         return 0;
 242 }
 243 
 244 static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
 245 {
 246         struct klsi_105_private *priv = usb_get_serial_port_data(port);
 247         int retval = 0;
 248         int rc;
 249         unsigned long line_state;
 250         struct klsi_105_port_settings *cfg;
 251         unsigned long flags;
 252 
 253         /* Do a defined restart:
 254          * Set up sane default baud rate and send the 'READ_ON'
 255          * vendor command.
 256          * FIXME: set modem line control (how?)
 257          * Then read the modem line control and store values in
 258          * priv->line_state.
 259          */
 260         cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
 261         if (!cfg)
 262                 return -ENOMEM;
 263 
 264         cfg->pktlen   = 5;
 265         cfg->baudrate = kl5kusb105a_sio_b9600;
 266         cfg->databits = kl5kusb105a_dtb_8;
 267         cfg->unknown1 = 0;
 268         cfg->unknown2 = 1;
 269         klsi_105_chg_port_settings(port, cfg);
 270 
 271         spin_lock_irqsave(&priv->lock, flags);
 272         priv->cfg.pktlen   = cfg->pktlen;
 273         priv->cfg.baudrate = cfg->baudrate;
 274         priv->cfg.databits = cfg->databits;
 275         priv->cfg.unknown1 = cfg->unknown1;
 276         priv->cfg.unknown2 = cfg->unknown2;
 277         spin_unlock_irqrestore(&priv->lock, flags);
 278 
 279         /* READ_ON and urb submission */
 280         rc = usb_serial_generic_open(tty, port);
 281         if (rc) {
 282                 retval = rc;
 283                 goto err_free_cfg;
 284         }
 285 
 286         rc = usb_control_msg(port->serial->dev,
 287                              usb_sndctrlpipe(port->serial->dev, 0),
 288                              KL5KUSB105A_SIO_CONFIGURE,
 289                              USB_TYPE_VENDOR|USB_DIR_OUT|USB_RECIP_INTERFACE,
 290                              KL5KUSB105A_SIO_CONFIGURE_READ_ON,
 291                              0, /* index */
 292                              NULL,
 293                              0,
 294                              KLSI_TIMEOUT);
 295         if (rc < 0) {
 296                 dev_err(&port->dev, "Enabling read failed (error = %d)\n", rc);
 297                 retval = rc;
 298                 goto err_generic_close;
 299         } else
 300                 dev_dbg(&port->dev, "%s - enabled reading\n", __func__);
 301 
 302         rc = klsi_105_get_line_state(port, &line_state);
 303         if (rc < 0) {
 304                 retval = rc;
 305                 goto err_disable_read;
 306         }
 307 
 308         spin_lock_irqsave(&priv->lock, flags);
 309         priv->line_state = line_state;
 310         spin_unlock_irqrestore(&priv->lock, flags);
 311         dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__,
 312                         line_state);
 313 
 314         return 0;
 315 
 316 err_disable_read:
 317         usb_control_msg(port->serial->dev,
 318                              usb_sndctrlpipe(port->serial->dev, 0),
 319                              KL5KUSB105A_SIO_CONFIGURE,
 320                              USB_TYPE_VENDOR | USB_DIR_OUT,
 321                              KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
 322                              0, /* index */
 323                              NULL, 0,
 324                              KLSI_TIMEOUT);
 325 err_generic_close:
 326         usb_serial_generic_close(port);
 327 err_free_cfg:
 328         kfree(cfg);
 329 
 330         return retval;
 331 }
 332 
 333 static void klsi_105_close(struct usb_serial_port *port)
 334 {
 335         int rc;
 336 
 337         /* send READ_OFF */
 338         rc = usb_control_msg(port->serial->dev,
 339                              usb_sndctrlpipe(port->serial->dev, 0),
 340                              KL5KUSB105A_SIO_CONFIGURE,
 341                              USB_TYPE_VENDOR | USB_DIR_OUT,
 342                              KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
 343                              0, /* index */
 344                              NULL, 0,
 345                              KLSI_TIMEOUT);
 346         if (rc < 0)
 347                 dev_err(&port->dev, "failed to disable read: %d\n", rc);
 348 
 349         /* shutdown our bulk reads and writes */
 350         usb_serial_generic_close(port);
 351 }
 352 
 353 /* We need to write a complete 64-byte data block and encode the
 354  * number actually sent in the first double-byte, LSB-order. That
 355  * leaves at most 62 bytes of payload.
 356  */
 357 #define KLSI_HDR_LEN            2
 358 static int klsi_105_prepare_write_buffer(struct usb_serial_port *port,
 359                                                 void *dest, size_t size)
 360 {
 361         unsigned char *buf = dest;
 362         int count;
 363 
 364         count = kfifo_out_locked(&port->write_fifo, buf + KLSI_HDR_LEN, size,
 365                                                                 &port->lock);
 366         put_unaligned_le16(count, buf);
 367 
 368         return count + KLSI_HDR_LEN;
 369 }
 370 
 371 /* The data received is preceded by a length double-byte in LSB-first order.
 372  */
 373 static void klsi_105_process_read_urb(struct urb *urb)
 374 {
 375         struct usb_serial_port *port = urb->context;
 376         unsigned char *data = urb->transfer_buffer;
 377         unsigned len;
 378 
 379         /* empty urbs seem to happen, we ignore them */
 380         if (!urb->actual_length)
 381                 return;
 382 
 383         if (urb->actual_length <= KLSI_HDR_LEN) {
 384                 dev_dbg(&port->dev, "%s - malformed packet\n", __func__);
 385                 return;
 386         }
 387 
 388         len = get_unaligned_le16(data);
 389         if (len > urb->actual_length - KLSI_HDR_LEN) {
 390                 dev_dbg(&port->dev, "%s - packet length mismatch\n", __func__);
 391                 len = urb->actual_length - KLSI_HDR_LEN;
 392         }
 393 
 394         tty_insert_flip_string(&port->port, data + KLSI_HDR_LEN, len);
 395         tty_flip_buffer_push(&port->port);
 396 }
 397 
 398 static void klsi_105_set_termios(struct tty_struct *tty,
 399                                  struct usb_serial_port *port,
 400                                  struct ktermios *old_termios)
 401 {
 402         struct klsi_105_private *priv = usb_get_serial_port_data(port);
 403         struct device *dev = &port->dev;
 404         unsigned int iflag = tty->termios.c_iflag;
 405         unsigned int old_iflag = old_termios->c_iflag;
 406         unsigned int cflag = tty->termios.c_cflag;
 407         unsigned int old_cflag = old_termios->c_cflag;
 408         struct klsi_105_port_settings *cfg;
 409         unsigned long flags;
 410         speed_t baud;
 411 
 412         cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
 413         if (!cfg)
 414                 return;
 415 
 416         /* lock while we are modifying the settings */
 417         spin_lock_irqsave(&priv->lock, flags);
 418 
 419         /*
 420          * Update baud rate
 421          */
 422         baud = tty_get_baud_rate(tty);
 423 
 424         switch (baud) {
 425         case 0: /* handled below */
 426                 break;
 427         case 1200:
 428                 priv->cfg.baudrate = kl5kusb105a_sio_b1200;
 429                 break;
 430         case 2400:
 431                 priv->cfg.baudrate = kl5kusb105a_sio_b2400;
 432                 break;
 433         case 4800:
 434                 priv->cfg.baudrate = kl5kusb105a_sio_b4800;
 435                 break;
 436         case 9600:
 437                 priv->cfg.baudrate = kl5kusb105a_sio_b9600;
 438                 break;
 439         case 19200:
 440                 priv->cfg.baudrate = kl5kusb105a_sio_b19200;
 441                 break;
 442         case 38400:
 443                 priv->cfg.baudrate = kl5kusb105a_sio_b38400;
 444                 break;
 445         case 57600:
 446                 priv->cfg.baudrate = kl5kusb105a_sio_b57600;
 447                 break;
 448         case 115200:
 449                 priv->cfg.baudrate = kl5kusb105a_sio_b115200;
 450                 break;
 451         default:
 452                 dev_dbg(dev, "unsupported baudrate, using 9600\n");
 453                 priv->cfg.baudrate = kl5kusb105a_sio_b9600;
 454                 baud = 9600;
 455                 break;
 456         }
 457 
 458         /*
 459          * FIXME: implement B0 handling
 460          *
 461          * Maybe this should be simulated by sending read disable and read
 462          * enable messages?
 463          */
 464 
 465         tty_encode_baud_rate(tty, baud, baud);
 466 
 467         if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
 468                 /* set the number of data bits */
 469                 switch (cflag & CSIZE) {
 470                 case CS5:
 471                         dev_dbg(dev, "%s - 5 bits/byte not supported\n", __func__);
 472                         spin_unlock_irqrestore(&priv->lock, flags);
 473                         goto err;
 474                 case CS6:
 475                         dev_dbg(dev, "%s - 6 bits/byte not supported\n", __func__);
 476                         spin_unlock_irqrestore(&priv->lock, flags);
 477                         goto err;
 478                 case CS7:
 479                         priv->cfg.databits = kl5kusb105a_dtb_7;
 480                         break;
 481                 case CS8:
 482                         priv->cfg.databits = kl5kusb105a_dtb_8;
 483                         break;
 484                 default:
 485                         dev_err(dev, "CSIZE was not CS5-CS8, using default of 8\n");
 486                         priv->cfg.databits = kl5kusb105a_dtb_8;
 487                         break;
 488                 }
 489         }
 490 
 491         /*
 492          * Update line control register (LCR)
 493          */
 494         if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
 495             || (cflag & CSTOPB) != (old_cflag & CSTOPB)) {
 496                 /* Not currently supported */
 497                 tty->termios.c_cflag &= ~(PARENB|PARODD|CSTOPB);
 498         }
 499         /*
 500          * Set flow control: well, I do not really now how to handle DTR/RTS.
 501          * Just do what we have seen with SniffUSB on Win98.
 502          */
 503         if ((iflag & IXOFF) != (old_iflag & IXOFF)
 504             || (iflag & IXON) != (old_iflag & IXON)
 505             ||  (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
 506                 /* Not currently supported */
 507                 tty->termios.c_cflag &= ~CRTSCTS;
 508         }
 509         memcpy(cfg, &priv->cfg, sizeof(*cfg));
 510         spin_unlock_irqrestore(&priv->lock, flags);
 511 
 512         /* now commit changes to device */
 513         klsi_105_chg_port_settings(port, cfg);
 514 err:
 515         kfree(cfg);
 516 }
 517 
 518 static int klsi_105_tiocmget(struct tty_struct *tty)
 519 {
 520         struct usb_serial_port *port = tty->driver_data;
 521         struct klsi_105_private *priv = usb_get_serial_port_data(port);
 522         unsigned long flags;
 523         int rc;
 524         unsigned long line_state;
 525 
 526         rc = klsi_105_get_line_state(port, &line_state);
 527         if (rc < 0) {
 528                 dev_err(&port->dev,
 529                         "Reading line control failed (error = %d)\n", rc);
 530                 /* better return value? EAGAIN? */
 531                 return rc;
 532         }
 533 
 534         spin_lock_irqsave(&priv->lock, flags);
 535         priv->line_state = line_state;
 536         spin_unlock_irqrestore(&priv->lock, flags);
 537         dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__, line_state);
 538         return (int)line_state;
 539 }
 540 
 541 module_usb_serial_driver(serial_drivers, id_table);
 542 
 543 MODULE_AUTHOR(DRIVER_AUTHOR);
 544 MODULE_DESCRIPTION(DRIVER_DESC);
 545 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */