kobil_sct.c revision 32078f915d1acab356080b144aa89fe3487f3979
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/init.h> 29#include <linux/slab.h> 30#include <linux/tty.h> 31#include <linux/tty_driver.h> 32#include <linux/tty_flip.h> 33#include <linux/module.h> 34#include <linux/spinlock.h> 35#include <linux/uaccess.h> 36#include <linux/usb.h> 37#include <linux/usb/serial.h> 38#include <linux/ioctl.h> 39#include "kobil_sct.h" 40 41static bool debug; 42 43/* Version Information */ 44#define DRIVER_VERSION "21/05/2004" 45#define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com" 46#define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)" 47 48#define KOBIL_VENDOR_ID 0x0D46 49#define KOBIL_ADAPTER_B_PRODUCT_ID 0x2011 50#define KOBIL_ADAPTER_K_PRODUCT_ID 0x2012 51#define KOBIL_USBTWIN_PRODUCT_ID 0x0078 52#define KOBIL_KAAN_SIM_PRODUCT_ID 0x0081 53 54#define KOBIL_TIMEOUT 500 55#define KOBIL_BUF_LENGTH 300 56 57 58/* Function prototypes */ 59static int kobil_startup(struct usb_serial *serial); 60static void kobil_release(struct usb_serial *serial); 61static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port); 62static void kobil_close(struct usb_serial_port *port); 63static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, 64 const unsigned char *buf, int count); 65static int kobil_write_room(struct tty_struct *tty); 66static int kobil_ioctl(struct tty_struct *tty, 67 unsigned int cmd, unsigned long arg); 68static int kobil_tiocmget(struct tty_struct *tty); 69static int kobil_tiocmset(struct tty_struct *tty, 70 unsigned int set, unsigned int clear); 71static void kobil_read_int_callback(struct urb *urb); 72static void kobil_write_callback(struct urb *purb); 73static void kobil_set_termios(struct tty_struct *tty, 74 struct usb_serial_port *port, struct ktermios *old); 75static void kobil_init_termios(struct tty_struct *tty); 76 77static const struct usb_device_id id_table[] = { 78 { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_B_PRODUCT_ID) }, 79 { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_K_PRODUCT_ID) }, 80 { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_USBTWIN_PRODUCT_ID) }, 81 { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_KAAN_SIM_PRODUCT_ID) }, 82 { } /* Terminating entry */ 83}; 84 85 86MODULE_DEVICE_TABLE(usb, id_table); 87 88static struct usb_driver kobil_driver = { 89 .name = "kobil", 90 .id_table = id_table, 91}; 92 93 94static struct usb_serial_driver kobil_device = { 95 .driver = { 96 .owner = THIS_MODULE, 97 .name = "kobil", 98 }, 99 .description = "KOBIL USB smart card terminal", 100 .id_table = id_table, 101 .num_ports = 1, 102 .attach = kobil_startup, 103 .release = kobil_release, 104 .ioctl = kobil_ioctl, 105 .set_termios = kobil_set_termios, 106 .init_termios = kobil_init_termios, 107 .tiocmget = kobil_tiocmget, 108 .tiocmset = kobil_tiocmset, 109 .open = kobil_open, 110 .close = kobil_close, 111 .write = kobil_write, 112 .write_room = kobil_write_room, 113 .read_int_callback = kobil_read_int_callback, 114}; 115 116static struct usb_serial_driver * const serial_drivers[] = { 117 &kobil_device, NULL 118}; 119 120struct kobil_private { 121 int write_int_endpoint_address; 122 int read_int_endpoint_address; 123 unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */ 124 int filled; /* index of the last char in buf */ 125 int cur_pos; /* index of the next char to send in buf */ 126 __u16 device_type; 127}; 128 129 130static int kobil_startup(struct usb_serial *serial) 131{ 132 int i; 133 struct kobil_private *priv; 134 struct usb_device *pdev; 135 struct usb_host_config *actconfig; 136 struct usb_interface *interface; 137 struct usb_host_interface *altsetting; 138 struct usb_host_endpoint *endpoint; 139 140 priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL); 141 if (!priv) 142 return -ENOMEM; 143 144 priv->filled = 0; 145 priv->cur_pos = 0; 146 priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct); 147 148 switch (priv->device_type) { 149 case KOBIL_ADAPTER_B_PRODUCT_ID: 150 printk(KERN_DEBUG "KOBIL B1 PRO / KAAN PRO detected\n"); 151 break; 152 case KOBIL_ADAPTER_K_PRODUCT_ID: 153 printk(KERN_DEBUG 154 "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n"); 155 break; 156 case KOBIL_USBTWIN_PRODUCT_ID: 157 printk(KERN_DEBUG "KOBIL USBTWIN detected\n"); 158 break; 159 case KOBIL_KAAN_SIM_PRODUCT_ID: 160 printk(KERN_DEBUG "KOBIL KAAN SIM detected\n"); 161 break; 162 } 163 usb_set_serial_port_data(serial->port[0], priv); 164 165 /* search for the necessary endpoints */ 166 pdev = serial->dev; 167 actconfig = pdev->actconfig; 168 interface = actconfig->interface[0]; 169 altsetting = interface->cur_altsetting; 170 endpoint = altsetting->endpoint; 171 172 for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { 173 endpoint = &altsetting->endpoint[i]; 174 if (usb_endpoint_is_int_out(&endpoint->desc)) { 175 dbg("%s Found interrupt out endpoint. Address: %d", 176 __func__, endpoint->desc.bEndpointAddress); 177 priv->write_int_endpoint_address = 178 endpoint->desc.bEndpointAddress; 179 } 180 if (usb_endpoint_is_int_in(&endpoint->desc)) { 181 dbg("%s Found interrupt in endpoint. Address: %d", 182 __func__, endpoint->desc.bEndpointAddress); 183 priv->read_int_endpoint_address = 184 endpoint->desc.bEndpointAddress; 185 } 186 } 187 return 0; 188} 189 190 191static void kobil_release(struct usb_serial *serial) 192{ 193 int i; 194 195 for (i = 0; i < serial->num_ports; ++i) 196 kfree(usb_get_serial_port_data(serial->port[i])); 197} 198 199static void kobil_init_termios(struct tty_struct *tty) 200{ 201 /* Default to echo off and other sane device settings */ 202 tty->termios->c_lflag = 0; 203 tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE); 204 tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF; 205 /* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */ 206 tty->termios->c_oflag &= ~ONLCR; 207} 208 209static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) 210{ 211 int result = 0; 212 struct kobil_private *priv; 213 unsigned char *transfer_buffer; 214 int transfer_buffer_length = 8; 215 int write_urb_transfer_buffer_length = 8; 216 217 priv = usb_get_serial_port_data(port); 218 219 /* allocate memory for transfer buffer */ 220 transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); 221 if (!transfer_buffer) 222 return -ENOMEM; 223 224 /* allocate write_urb */ 225 if (!port->write_urb) { 226 dbg("%s - port %d Allocating port->write_urb", 227 __func__, port->number); 228 port->write_urb = usb_alloc_urb(0, GFP_KERNEL); 229 if (!port->write_urb) { 230 dbg("%s - port %d usb_alloc_urb failed", 231 __func__, port->number); 232 kfree(transfer_buffer); 233 return -ENOMEM; 234 } 235 } 236 237 /* allocate memory for write_urb transfer buffer */ 238 port->write_urb->transfer_buffer = 239 kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL); 240 if (!port->write_urb->transfer_buffer) { 241 kfree(transfer_buffer); 242 usb_free_urb(port->write_urb); 243 port->write_urb = NULL; 244 return -ENOMEM; 245 } 246 247 /* get hardware version */ 248 result = usb_control_msg(port->serial->dev, 249 usb_rcvctrlpipe(port->serial->dev, 0), 250 SUSBCRequest_GetMisc, 251 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, 252 SUSBCR_MSC_GetHWVersion, 253 0, 254 transfer_buffer, 255 transfer_buffer_length, 256 KOBIL_TIMEOUT 257 ); 258 dbg("%s - port %d Send get_HW_version URB returns: %i", 259 __func__, port->number, result); 260 dbg("Harware version: %i.%i.%i", 261 transfer_buffer[0], transfer_buffer[1], transfer_buffer[2]); 262 263 /* get firmware version */ 264 result = usb_control_msg(port->serial->dev, 265 usb_rcvctrlpipe(port->serial->dev, 0), 266 SUSBCRequest_GetMisc, 267 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, 268 SUSBCR_MSC_GetFWVersion, 269 0, 270 transfer_buffer, 271 transfer_buffer_length, 272 KOBIL_TIMEOUT 273 ); 274 dbg("%s - port %d Send get_FW_version URB returns: %i", 275 __func__, port->number, result); 276 dbg("Firmware version: %i.%i.%i", 277 transfer_buffer[0], transfer_buffer[1], transfer_buffer[2]); 278 279 if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || 280 priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { 281 /* Setting Baudrate, Parity and Stopbits */ 282 result = usb_control_msg(port->serial->dev, 283 usb_rcvctrlpipe(port->serial->dev, 0), 284 SUSBCRequest_SetBaudRateParityAndStopBits, 285 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, 286 SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity | 287 SUSBCR_SPASB_1StopBit, 288 0, 289 transfer_buffer, 290 0, 291 KOBIL_TIMEOUT 292 ); 293 dbg("%s - port %d Send set_baudrate URB returns: %i", 294 __func__, port->number, result); 295 296 /* reset all queues */ 297 result = usb_control_msg(port->serial->dev, 298 usb_rcvctrlpipe(port->serial->dev, 0), 299 SUSBCRequest_Misc, 300 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, 301 SUSBCR_MSC_ResetAllQueues, 302 0, 303 transfer_buffer, 304 0, 305 KOBIL_TIMEOUT 306 ); 307 dbg("%s - port %d Send reset_all_queues URB returns: %i", 308 __func__, port->number, result); 309 } 310 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || 311 priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || 312 priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { 313 /* start reading (Adapter B 'cause PNP string) */ 314 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); 315 dbg("%s - port %d Send read URB returns: %i", 316 __func__, port->number, result); 317 } 318 319 kfree(transfer_buffer); 320 return 0; 321} 322 323 324static void kobil_close(struct usb_serial_port *port) 325{ 326 /* FIXME: Add rts/dtr methods */ 327 if (port->write_urb) { 328 usb_poison_urb(port->write_urb); 329 kfree(port->write_urb->transfer_buffer); 330 usb_free_urb(port->write_urb); 331 port->write_urb = NULL; 332 } 333 usb_kill_urb(port->interrupt_in_urb); 334} 335 336 337static void kobil_read_int_callback(struct urb *urb) 338{ 339 int result; 340 struct usb_serial_port *port = urb->context; 341 struct tty_struct *tty; 342 unsigned char *data = urb->transfer_buffer; 343 int status = urb->status; 344/* char *dbg_data; */ 345 346 if (status) { 347 dbg("%s - port %d Read int status not zero: %d", 348 __func__, port->number, status); 349 return; 350 } 351 352 tty = tty_port_tty_get(&port->port); 353 if (tty && urb->actual_length) { 354 355 /* BEGIN DEBUG */ 356 /* 357 dbg_data = kzalloc((3 * purb->actual_length + 10) 358 * sizeof(char), GFP_KERNEL); 359 if (! dbg_data) { 360 return; 361 } 362 for (i = 0; i < purb->actual_length; i++) { 363 sprintf(dbg_data +3*i, "%02X ", data[i]); 364 } 365 dbg(" <-- %s", dbg_data); 366 kfree(dbg_data); 367 */ 368 /* END DEBUG */ 369 370 tty_insert_flip_string(tty, data, urb->actual_length); 371 tty_flip_buffer_push(tty); 372 } 373 tty_kref_put(tty); 374 375 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); 376 dbg("%s - port %d Send read URB returns: %i", 377 __func__, port->number, result); 378} 379 380 381static void kobil_write_callback(struct urb *purb) 382{ 383} 384 385 386static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, 387 const unsigned char *buf, int count) 388{ 389 int length = 0; 390 int result = 0; 391 int todo = 0; 392 struct kobil_private *priv; 393 394 if (count == 0) { 395 dbg("%s - port %d write request of 0 bytes", 396 __func__, port->number); 397 return 0; 398 } 399 400 priv = usb_get_serial_port_data(port); 401 402 if (count > (KOBIL_BUF_LENGTH - priv->filled)) { 403 dbg("%s - port %d Error: write request bigger than buffer size", __func__, port->number); 404 return -ENOMEM; 405 } 406 407 /* Copy data to buffer */ 408 memcpy(priv->buf + priv->filled, buf, count); 409 usb_serial_debug_data(debug, &port->dev, __func__, count, 410 priv->buf + priv->filled); 411 priv->filled = priv->filled + count; 412 413 /* only send complete block. TWIN, KAAN SIM and adapter K 414 use the same protocol. */ 415 if (((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) || 416 ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4)))) { 417 /* stop reading (except TWIN and KAAN SIM) */ 418 if ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) 419 || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID)) 420 usb_kill_urb(port->interrupt_in_urb); 421 422 todo = priv->filled - priv->cur_pos; 423 424 while (todo > 0) { 425 /* max 8 byte in one urb (endpoint size) */ 426 length = (todo < 8) ? todo : 8; 427 /* copy data to transfer buffer */ 428 memcpy(port->write_urb->transfer_buffer, 429 priv->buf + priv->cur_pos, length); 430 usb_fill_int_urb(port->write_urb, 431 port->serial->dev, 432 usb_sndintpipe(port->serial->dev, 433 priv->write_int_endpoint_address), 434 port->write_urb->transfer_buffer, 435 length, 436 kobil_write_callback, 437 port, 438 8 439 ); 440 441 priv->cur_pos = priv->cur_pos + length; 442 result = usb_submit_urb(port->write_urb, GFP_NOIO); 443 dbg("%s - port %d Send write URB returns: %i", 444 __func__, port->number, result); 445 todo = priv->filled - priv->cur_pos; 446 447 if (todo > 0) 448 msleep(24); 449 } 450 451 priv->filled = 0; 452 priv->cur_pos = 0; 453 454 /* start reading (except TWIN and KAAN SIM) */ 455 if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || 456 priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { 457 result = usb_submit_urb(port->interrupt_in_urb, 458 GFP_NOIO); 459 dbg("%s - port %d Send read URB returns: %i", 460 __func__, port->number, result); 461 } 462 } 463 return count; 464} 465 466 467static int kobil_write_room(struct tty_struct *tty) 468{ 469 /* FIXME */ 470 return 8; 471} 472 473 474static int kobil_tiocmget(struct tty_struct *tty) 475{ 476 struct usb_serial_port *port = tty->driver_data; 477 struct kobil_private *priv; 478 int result; 479 unsigned char *transfer_buffer; 480 int transfer_buffer_length = 8; 481 482 priv = usb_get_serial_port_data(port); 483 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID 484 || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { 485 /* This device doesn't support ioctl calls */ 486 return -EINVAL; 487 } 488 489 /* allocate memory for transfer buffer */ 490 transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); 491 if (!transfer_buffer) 492 return -ENOMEM; 493 494 result = usb_control_msg(port->serial->dev, 495 usb_rcvctrlpipe(port->serial->dev, 0), 496 SUSBCRequest_GetStatusLineState, 497 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, 498 0, 499 0, 500 transfer_buffer, 501 transfer_buffer_length, 502 KOBIL_TIMEOUT); 503 504 dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x", 505 __func__, port->number, result, transfer_buffer[0]); 506 507 result = 0; 508 if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0) 509 result = TIOCM_DSR; 510 kfree(transfer_buffer); 511 return result; 512} 513 514static int kobil_tiocmset(struct tty_struct *tty, 515 unsigned int set, unsigned int clear) 516{ 517 struct usb_serial_port *port = tty->driver_data; 518 struct kobil_private *priv; 519 int result; 520 int dtr = 0; 521 int rts = 0; 522 unsigned char *transfer_buffer; 523 int transfer_buffer_length = 8; 524 525 /* FIXME: locking ? */ 526 priv = usb_get_serial_port_data(port); 527 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID 528 || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { 529 /* This device doesn't support ioctl calls */ 530 return -EINVAL; 531 } 532 533 /* allocate memory for transfer buffer */ 534 transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); 535 if (!transfer_buffer) 536 return -ENOMEM; 537 538 if (set & TIOCM_RTS) 539 rts = 1; 540 if (set & TIOCM_DTR) 541 dtr = 1; 542 if (clear & TIOCM_RTS) 543 rts = 0; 544 if (clear & TIOCM_DTR) 545 dtr = 0; 546 547 if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) { 548 if (dtr != 0) 549 dbg("%s - port %d Setting DTR", 550 __func__, port->number); 551 else 552 dbg("%s - port %d Clearing DTR", 553 __func__, port->number); 554 result = usb_control_msg(port->serial->dev, 555 usb_rcvctrlpipe(port->serial->dev, 0), 556 SUSBCRequest_SetStatusLinesOrQueues, 557 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, 558 ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR), 559 0, 560 transfer_buffer, 561 0, 562 KOBIL_TIMEOUT); 563 } else { 564 if (rts != 0) 565 dbg("%s - port %d Setting RTS", 566 __func__, port->number); 567 else 568 dbg("%s - port %d Clearing RTS", 569 __func__, port->number); 570 result = usb_control_msg(port->serial->dev, 571 usb_rcvctrlpipe(port->serial->dev, 0), 572 SUSBCRequest_SetStatusLinesOrQueues, 573 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, 574 ((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS), 575 0, 576 transfer_buffer, 577 0, 578 KOBIL_TIMEOUT); 579 } 580 dbg("%s - port %d Send set_status_line URB returns: %i", 581 __func__, port->number, result); 582 kfree(transfer_buffer); 583 return (result < 0) ? result : 0; 584} 585 586static void kobil_set_termios(struct tty_struct *tty, 587 struct usb_serial_port *port, struct ktermios *old) 588{ 589 struct kobil_private *priv; 590 int result; 591 unsigned short urb_val = 0; 592 int c_cflag = tty->termios->c_cflag; 593 speed_t speed; 594 595 priv = usb_get_serial_port_data(port); 596 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || 597 priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { 598 /* This device doesn't support ioctl calls */ 599 *tty->termios = *old; 600 return; 601 } 602 603 speed = tty_get_baud_rate(tty); 604 switch (speed) { 605 case 1200: 606 urb_val = SUSBCR_SBR_1200; 607 break; 608 default: 609 speed = 9600; 610 case 9600: 611 urb_val = SUSBCR_SBR_9600; 612 break; 613 } 614 urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : 615 SUSBCR_SPASB_1StopBit; 616 if (c_cflag & PARENB) { 617 if (c_cflag & PARODD) 618 urb_val |= SUSBCR_SPASB_OddParity; 619 else 620 urb_val |= SUSBCR_SPASB_EvenParity; 621 } else 622 urb_val |= SUSBCR_SPASB_NoParity; 623 tty->termios->c_cflag &= ~CMSPAR; 624 tty_encode_baud_rate(tty, speed, speed); 625 626 result = usb_control_msg(port->serial->dev, 627 usb_rcvctrlpipe(port->serial->dev, 0), 628 SUSBCRequest_SetBaudRateParityAndStopBits, 629 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, 630 urb_val, 631 0, 632 NULL, 633 0, 634 KOBIL_TIMEOUT 635 ); 636} 637 638static int kobil_ioctl(struct tty_struct *tty, 639 unsigned int cmd, unsigned long arg) 640{ 641 struct usb_serial_port *port = tty->driver_data; 642 struct kobil_private *priv = usb_get_serial_port_data(port); 643 unsigned char *transfer_buffer; 644 int transfer_buffer_length = 8; 645 int result; 646 647 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || 648 priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) 649 /* This device doesn't support ioctl calls */ 650 return -ENOIOCTLCMD; 651 652 switch (cmd) { 653 case TCFLSH: 654 transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL); 655 if (!transfer_buffer) 656 return -ENOBUFS; 657 658 result = usb_control_msg(port->serial->dev, 659 usb_rcvctrlpipe(port->serial->dev, 0), 660 SUSBCRequest_Misc, 661 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, 662 SUSBCR_MSC_ResetAllQueues, 663 0, 664 NULL, /* transfer_buffer, */ 665 0, 666 KOBIL_TIMEOUT 667 ); 668 669 dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __func__, port->number, result); 670 kfree(transfer_buffer); 671 return (result < 0) ? -EIO: 0; 672 default: 673 return -ENOIOCTLCMD; 674 } 675} 676 677module_usb_serial_driver(kobil_driver, serial_drivers); 678 679MODULE_AUTHOR(DRIVER_AUTHOR); 680MODULE_DESCRIPTION(DRIVER_DESC); 681MODULE_LICENSE("GPL"); 682 683module_param(debug, bool, S_IRUGO | S_IWUSR); 684MODULE_PARM_DESC(debug, "Debug enabled or not"); 685