1/* 2 * KOBIL USB Smart Card Terminal Driver 3 * 4 * Copyright (C) 2002 KOBIL Systems GmbH 5 * Author: Thomas Wahrenbruch 6 * 7 * Contact: linuxusb@kobil.de 8 * 9 * This program is largely derived from work by the linux-usb group 10 * and associated source files. Please see the usb/serial files for 11 * individual credits and copyrights. 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 * 18 * Thanks to Greg Kroah-Hartman (greg@kroah.com) for his help and 19 * patience. 20 * 21 * Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus 22 * (Adapter K), B1 Professional and KAAN Professional (Adapter B) 23 */ 24 25 26#include <linux/kernel.h> 27#include <linux/errno.h> 28#include <linux/slab.h> 29#include <linux/tty.h> 30#include <linux/tty_driver.h> 31#include <linux/tty_flip.h> 32#include <linux/module.h> 33#include <linux/spinlock.h> 34#include <linux/uaccess.h> 35#include <linux/usb.h> 36#include <linux/usb/serial.h> 37#include <linux/ioctl.h> 38#include "kobil_sct.h" 39 40#define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com" 41#define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)" 42 43#define KOBIL_VENDOR_ID 0x0D46 44#define KOBIL_ADAPTER_B_PRODUCT_ID 0x2011 45#define KOBIL_ADAPTER_K_PRODUCT_ID 0x2012 46#define KOBIL_USBTWIN_PRODUCT_ID 0x0078 47#define KOBIL_KAAN_SIM_PRODUCT_ID 0x0081 48 49#define KOBIL_TIMEOUT 500 50#define KOBIL_BUF_LENGTH 300 51 52 53/* Function prototypes */ 54static int kobil_port_probe(struct usb_serial_port *probe); 55static int kobil_port_remove(struct usb_serial_port *probe); 56static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port); 57static void kobil_close(struct usb_serial_port *port); 58static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, 59 const unsigned char *buf, int count); 60static int kobil_write_room(struct tty_struct *tty); 61static int kobil_ioctl(struct tty_struct *tty, 62 unsigned int cmd, unsigned long arg); 63static int kobil_tiocmget(struct tty_struct *tty); 64static int kobil_tiocmset(struct tty_struct *tty, 65 unsigned int set, unsigned int clear); 66static void kobil_read_int_callback(struct urb *urb); 67static void kobil_write_int_callback(struct urb *urb); 68static void kobil_set_termios(struct tty_struct *tty, 69 struct usb_serial_port *port, struct ktermios *old); 70static void kobil_init_termios(struct tty_struct *tty); 71 72static const struct usb_device_id id_table[] = { 73 { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_B_PRODUCT_ID) }, 74 { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_K_PRODUCT_ID) }, 75 { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_USBTWIN_PRODUCT_ID) }, 76 { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_KAAN_SIM_PRODUCT_ID) }, 77 { } /* Terminating entry */ 78}; 79MODULE_DEVICE_TABLE(usb, id_table); 80 81static struct usb_serial_driver kobil_device = { 82 .driver = { 83 .owner = THIS_MODULE, 84 .name = "kobil", 85 }, 86 .description = "KOBIL USB smart card terminal", 87 .id_table = id_table, 88 .num_ports = 1, 89 .port_probe = kobil_port_probe, 90 .port_remove = kobil_port_remove, 91 .ioctl = kobil_ioctl, 92 .set_termios = kobil_set_termios, 93 .init_termios = kobil_init_termios, 94 .tiocmget = kobil_tiocmget, 95 .tiocmset = kobil_tiocmset, 96 .open = kobil_open, 97 .close = kobil_close, 98 .write = kobil_write, 99 .write_room = kobil_write_room, 100 .read_int_callback = kobil_read_int_callback, 101 .write_int_callback = kobil_write_int_callback, 102}; 103 104static struct usb_serial_driver * const serial_drivers[] = { 105 &kobil_device, NULL 106}; 107 108struct kobil_private { 109 unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */ 110 int filled; /* index of the last char in buf */ 111 int cur_pos; /* index of the next char to send in buf */ 112 __u16 device_type; 113}; 114 115 116static int kobil_port_probe(struct usb_serial_port *port) 117{ 118 struct usb_serial *serial = port->serial; 119 struct kobil_private *priv; 120 121 priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL); 122 if (!priv) 123 return -ENOMEM; 124 125 priv->filled = 0; 126 priv->cur_pos = 0; 127 priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct); 128 129 switch (priv->device_type) { 130 case KOBIL_ADAPTER_B_PRODUCT_ID: 131 dev_dbg(&serial->dev->dev, "KOBIL B1 PRO / KAAN PRO detected\n"); 132 break; 133 case KOBIL_ADAPTER_K_PRODUCT_ID: 134 dev_dbg(&serial->dev->dev, "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n"); 135 break; 136 case KOBIL_USBTWIN_PRODUCT_ID: 137 dev_dbg(&serial->dev->dev, "KOBIL USBTWIN detected\n"); 138 break; 139 case KOBIL_KAAN_SIM_PRODUCT_ID: 140 dev_dbg(&serial->dev->dev, "KOBIL KAAN SIM detected\n"); 141 break; 142 } 143 usb_set_serial_port_data(port, priv); 144 145 return 0; 146} 147 148 149static int kobil_port_remove(struct usb_serial_port *port) 150{ 151 struct kobil_private *priv; 152 153 priv = usb_get_serial_port_data(port); 154 kfree(priv); 155 156 return 0; 157} 158 159static void kobil_init_termios(struct tty_struct *tty) 160{ 161 /* Default to echo off and other sane device settings */ 162 tty->termios.c_lflag = 0; 163 tty->termios.c_iflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE); 164 tty->termios.c_iflag |= IGNBRK | IGNPAR | IXOFF; 165 /* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */ 166 tty->termios.c_oflag &= ~ONLCR; 167} 168 169static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) 170{ 171 struct device *dev = &port->dev; 172 int result = 0; 173 struct kobil_private *priv; 174 unsigned char *transfer_buffer; 175 int transfer_buffer_length = 8; 176 177 priv = usb_get_serial_port_data(port); 178 179 /* allocate memory for transfer buffer */ 180 transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); 181 if (!transfer_buffer) 182 return -ENOMEM; 183 184 /* get hardware version */ 185 result = usb_control_msg(port->serial->dev, 186 usb_rcvctrlpipe(port->serial->dev, 0), 187 SUSBCRequest_GetMisc, 188 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, 189 SUSBCR_MSC_GetHWVersion, 190 0, 191 transfer_buffer, 192 transfer_buffer_length, 193 KOBIL_TIMEOUT 194 ); 195 dev_dbg(dev, "%s - Send get_HW_version URB returns: %i\n", __func__, result); 196 dev_dbg(dev, "Hardware version: %i.%i.%i\n", transfer_buffer[0], 197 transfer_buffer[1], transfer_buffer[2]); 198 199 /* get firmware version */ 200 result = usb_control_msg(port->serial->dev, 201 usb_rcvctrlpipe(port->serial->dev, 0), 202 SUSBCRequest_GetMisc, 203 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, 204 SUSBCR_MSC_GetFWVersion, 205 0, 206 transfer_buffer, 207 transfer_buffer_length, 208 KOBIL_TIMEOUT 209 ); 210 dev_dbg(dev, "%s - Send get_FW_version URB returns: %i\n", __func__, result); 211 dev_dbg(dev, "Firmware version: %i.%i.%i\n", transfer_buffer[0], 212 transfer_buffer[1], transfer_buffer[2]); 213 214 if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || 215 priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { 216 /* Setting Baudrate, Parity and Stopbits */ 217 result = usb_control_msg(port->serial->dev, 218 usb_sndctrlpipe(port->serial->dev, 0), 219 SUSBCRequest_SetBaudRateParityAndStopBits, 220 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, 221 SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity | 222 SUSBCR_SPASB_1StopBit, 223 0, 224 NULL, 225 0, 226 KOBIL_TIMEOUT 227 ); 228 dev_dbg(dev, "%s - Send set_baudrate URB returns: %i\n", __func__, result); 229 230 /* reset all queues */ 231 result = usb_control_msg(port->serial->dev, 232 usb_sndctrlpipe(port->serial->dev, 0), 233 SUSBCRequest_Misc, 234 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, 235 SUSBCR_MSC_ResetAllQueues, 236 0, 237 NULL, 238 0, 239 KOBIL_TIMEOUT 240 ); 241 dev_dbg(dev, "%s - Send reset_all_queues URB returns: %i\n", __func__, result); 242 } 243 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || 244 priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || 245 priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { 246 /* start reading (Adapter B 'cause PNP string) */ 247 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); 248 dev_dbg(dev, "%s - Send read URB returns: %i\n", __func__, result); 249 } 250 251 kfree(transfer_buffer); 252 return 0; 253} 254 255 256static void kobil_close(struct usb_serial_port *port) 257{ 258 /* FIXME: Add rts/dtr methods */ 259 usb_kill_urb(port->interrupt_out_urb); 260 usb_kill_urb(port->interrupt_in_urb); 261} 262 263 264static void kobil_read_int_callback(struct urb *urb) 265{ 266 int result; 267 struct usb_serial_port *port = urb->context; 268 unsigned char *data = urb->transfer_buffer; 269 int status = urb->status; 270 271 if (status) { 272 dev_dbg(&port->dev, "%s - Read int status not zero: %d\n", __func__, status); 273 return; 274 } 275 276 if (urb->actual_length) { 277 usb_serial_debug_data(&port->dev, __func__, urb->actual_length, 278 data); 279 tty_insert_flip_string(&port->port, data, urb->actual_length); 280 tty_flip_buffer_push(&port->port); 281 } 282 283 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); 284 dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result); 285} 286 287 288static void kobil_write_int_callback(struct urb *urb) 289{ 290} 291 292 293static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, 294 const unsigned char *buf, int count) 295{ 296 int length = 0; 297 int result = 0; 298 int todo = 0; 299 struct kobil_private *priv; 300 301 if (count == 0) { 302 dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__); 303 return 0; 304 } 305 306 priv = usb_get_serial_port_data(port); 307 308 if (count > (KOBIL_BUF_LENGTH - priv->filled)) { 309 dev_dbg(&port->dev, "%s - Error: write request bigger than buffer size\n", __func__); 310 return -ENOMEM; 311 } 312 313 /* Copy data to buffer */ 314 memcpy(priv->buf + priv->filled, buf, count); 315 usb_serial_debug_data(&port->dev, __func__, count, priv->buf + priv->filled); 316 priv->filled = priv->filled + count; 317 318 /* only send complete block. TWIN, KAAN SIM and adapter K 319 use the same protocol. */ 320 if (((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) || 321 ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4)))) { 322 /* stop reading (except TWIN and KAAN SIM) */ 323 if ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) 324 || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID)) 325 usb_kill_urb(port->interrupt_in_urb); 326 327 todo = priv->filled - priv->cur_pos; 328 329 while (todo > 0) { 330 /* max 8 byte in one urb (endpoint size) */ 331 length = min(todo, port->interrupt_out_size); 332 /* copy data to transfer buffer */ 333 memcpy(port->interrupt_out_buffer, 334 priv->buf + priv->cur_pos, length); 335 port->interrupt_out_urb->transfer_buffer_length = length; 336 337 priv->cur_pos = priv->cur_pos + length; 338 result = usb_submit_urb(port->interrupt_out_urb, 339 GFP_ATOMIC); 340 dev_dbg(&port->dev, "%s - Send write URB returns: %i\n", __func__, result); 341 todo = priv->filled - priv->cur_pos; 342 343 if (todo > 0) 344 msleep(24); 345 } 346 347 priv->filled = 0; 348 priv->cur_pos = 0; 349 350 /* start reading (except TWIN and KAAN SIM) */ 351 if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || 352 priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { 353 result = usb_submit_urb(port->interrupt_in_urb, 354 GFP_ATOMIC); 355 dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result); 356 } 357 } 358 return count; 359} 360 361 362static int kobil_write_room(struct tty_struct *tty) 363{ 364 /* FIXME */ 365 return 8; 366} 367 368 369static int kobil_tiocmget(struct tty_struct *tty) 370{ 371 struct usb_serial_port *port = tty->driver_data; 372 struct kobil_private *priv; 373 int result; 374 unsigned char *transfer_buffer; 375 int transfer_buffer_length = 8; 376 377 priv = usb_get_serial_port_data(port); 378 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID 379 || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { 380 /* This device doesn't support ioctl calls */ 381 return -EINVAL; 382 } 383 384 /* allocate memory for transfer buffer */ 385 transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); 386 if (!transfer_buffer) 387 return -ENOMEM; 388 389 result = usb_control_msg(port->serial->dev, 390 usb_rcvctrlpipe(port->serial->dev, 0), 391 SUSBCRequest_GetStatusLineState, 392 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, 393 0, 394 0, 395 transfer_buffer, 396 transfer_buffer_length, 397 KOBIL_TIMEOUT); 398 399 dev_dbg(&port->dev, "%s - Send get_status_line_state URB returns: %i. Statusline: %02x\n", 400 __func__, result, transfer_buffer[0]); 401 402 result = 0; 403 if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0) 404 result = TIOCM_DSR; 405 kfree(transfer_buffer); 406 return result; 407} 408 409static int kobil_tiocmset(struct tty_struct *tty, 410 unsigned int set, unsigned int clear) 411{ 412 struct usb_serial_port *port = tty->driver_data; 413 struct device *dev = &port->dev; 414 struct kobil_private *priv; 415 int result; 416 int dtr = 0; 417 int rts = 0; 418 419 /* FIXME: locking ? */ 420 priv = usb_get_serial_port_data(port); 421 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID 422 || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { 423 /* This device doesn't support ioctl calls */ 424 return -EINVAL; 425 } 426 427 if (set & TIOCM_RTS) 428 rts = 1; 429 if (set & TIOCM_DTR) 430 dtr = 1; 431 if (clear & TIOCM_RTS) 432 rts = 0; 433 if (clear & TIOCM_DTR) 434 dtr = 0; 435 436 if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) { 437 if (dtr != 0) 438 dev_dbg(dev, "%s - Setting DTR\n", __func__); 439 else 440 dev_dbg(dev, "%s - Clearing DTR\n", __func__); 441 result = usb_control_msg(port->serial->dev, 442 usb_sndctrlpipe(port->serial->dev, 0), 443 SUSBCRequest_SetStatusLinesOrQueues, 444 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, 445 ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR), 446 0, 447 NULL, 448 0, 449 KOBIL_TIMEOUT); 450 } else { 451 if (rts != 0) 452 dev_dbg(dev, "%s - Setting RTS\n", __func__); 453 else 454 dev_dbg(dev, "%s - Clearing RTS\n", __func__); 455 result = usb_control_msg(port->serial->dev, 456 usb_sndctrlpipe(port->serial->dev, 0), 457 SUSBCRequest_SetStatusLinesOrQueues, 458 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, 459 ((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS), 460 0, 461 NULL, 462 0, 463 KOBIL_TIMEOUT); 464 } 465 dev_dbg(dev, "%s - Send set_status_line URB returns: %i\n", __func__, result); 466 return (result < 0) ? result : 0; 467} 468 469static void kobil_set_termios(struct tty_struct *tty, 470 struct usb_serial_port *port, struct ktermios *old) 471{ 472 struct kobil_private *priv; 473 int result; 474 unsigned short urb_val = 0; 475 int c_cflag = tty->termios.c_cflag; 476 speed_t speed; 477 478 priv = usb_get_serial_port_data(port); 479 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || 480 priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { 481 /* This device doesn't support ioctl calls */ 482 tty_termios_copy_hw(&tty->termios, old); 483 return; 484 } 485 486 speed = tty_get_baud_rate(tty); 487 switch (speed) { 488 case 1200: 489 urb_val = SUSBCR_SBR_1200; 490 break; 491 default: 492 speed = 9600; 493 case 9600: 494 urb_val = SUSBCR_SBR_9600; 495 break; 496 } 497 urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : 498 SUSBCR_SPASB_1StopBit; 499 if (c_cflag & PARENB) { 500 if (c_cflag & PARODD) 501 urb_val |= SUSBCR_SPASB_OddParity; 502 else 503 urb_val |= SUSBCR_SPASB_EvenParity; 504 } else 505 urb_val |= SUSBCR_SPASB_NoParity; 506 tty->termios.c_cflag &= ~CMSPAR; 507 tty_encode_baud_rate(tty, speed, speed); 508 509 result = usb_control_msg(port->serial->dev, 510 usb_sndctrlpipe(port->serial->dev, 0), 511 SUSBCRequest_SetBaudRateParityAndStopBits, 512 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, 513 urb_val, 514 0, 515 NULL, 516 0, 517 KOBIL_TIMEOUT 518 ); 519} 520 521static int kobil_ioctl(struct tty_struct *tty, 522 unsigned int cmd, unsigned long arg) 523{ 524 struct usb_serial_port *port = tty->driver_data; 525 struct kobil_private *priv = usb_get_serial_port_data(port); 526 int result; 527 528 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || 529 priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) 530 /* This device doesn't support ioctl calls */ 531 return -ENOIOCTLCMD; 532 533 switch (cmd) { 534 case TCFLSH: 535 result = usb_control_msg(port->serial->dev, 536 usb_sndctrlpipe(port->serial->dev, 0), 537 SUSBCRequest_Misc, 538 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, 539 SUSBCR_MSC_ResetAllQueues, 540 0, 541 NULL, 542 0, 543 KOBIL_TIMEOUT 544 ); 545 546 dev_dbg(&port->dev, 547 "%s - Send reset_all_queues (FLUSH) URB returns: %i\n", 548 __func__, result); 549 return (result < 0) ? -EIO: 0; 550 default: 551 return -ENOIOCTLCMD; 552 } 553} 554 555module_usb_serial_driver(serial_drivers, id_table); 556 557MODULE_AUTHOR(DRIVER_AUTHOR); 558MODULE_DESCRIPTION(DRIVER_DESC); 559MODULE_LICENSE("GPL"); 560