1/* 2 * REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver 3 * 4 * Copyright (C) 2001 REINER SCT 5 * Author: Matthias Bruestle 6 * 7 * Contact: linux-usb@sii.li (see MAINTAINERS) 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 * In case of problems, please write to the contact e-mail address 22 * mentioned above. 23 */ 24 25 26#include <linux/config.h> 27#include <linux/kernel.h> 28#include <linux/errno.h> 29#include <linux/init.h> 30#include <linux/slab.h> 31#include <linux/tty.h> 32#include <linux/tty_driver.h> 33#include <linux/tty_flip.h> 34#include <linux/module.h> 35#include <linux/spinlock.h> 36#include <asm/uaccess.h> 37#include <linux/usb.h> 38 39#ifdef CONFIG_USB_SERIAL_DEBUG 40 static int debug = 1; 41#else 42 static int debug; 43#endif 44 45#include "usb-serial.h" 46 47/* 48 * Version Information 49 */ 50#define DRIVER_VERSION "v1.0" 51#define DRIVER_AUTHOR "Matthias Bruestle" 52#define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver" 53 54 55#define CYBERJACK_VENDOR_ID 0x0C4B 56#define CYBERJACK_PRODUCT_ID 0x0100 57 58/* Function prototypes */ 59static int cyberjack_startup (struct usb_serial *serial); 60static void cyberjack_shutdown (struct usb_serial *serial); 61static int cyberjack_open (struct usb_serial_port *port, struct file *filp); 62static void cyberjack_close (struct usb_serial_port *port, struct file *filp); 63static int cyberjack_write (struct usb_serial_port *port, int from_user, 64 const unsigned char *buf, int count); 65static void cyberjack_read_int_callback( struct urb *urb ); 66static void cyberjack_read_bulk_callback (struct urb *urb); 67static void cyberjack_write_bulk_callback (struct urb *urb); 68 69static struct usb_device_id id_table [] = { 70 { USB_DEVICE(CYBERJACK_VENDOR_ID, CYBERJACK_PRODUCT_ID) }, 71 { } /* Terminating entry */ 72}; 73 74MODULE_DEVICE_TABLE (usb, id_table); 75 76static struct usb_serial_device_type cyberjack_device = { 77 .owner = THIS_MODULE, 78 .name = "Reiner SCT Cyberjack USB card reader", 79 .id_table = id_table, 80 .num_interrupt_in = 1, 81 .num_bulk_in = 1, 82 .num_bulk_out = 1, 83 .num_ports = 1, 84 .startup = cyberjack_startup, 85 .shutdown = cyberjack_shutdown, 86 .open = cyberjack_open, 87 .close = cyberjack_close, 88 .write = cyberjack_write, 89 .read_int_callback = cyberjack_read_int_callback, 90 .read_bulk_callback = cyberjack_read_bulk_callback, 91 .write_bulk_callback = cyberjack_write_bulk_callback, 92}; 93 94struct cyberjack_private { 95 short rdtodo; /* Bytes still to read */ 96 unsigned char wrbuf[5*64]; /* Buffer for collecting data to write */ 97 short wrfilled; /* Overall data size we already got */ 98 short wrsent; /* Data akready sent */ 99}; 100 101/* do some startup allocations not currently performed by usb_serial_probe() */ 102static int cyberjack_startup (struct usb_serial *serial) 103{ 104 struct cyberjack_private *priv; 105 106 dbg("%s", __FUNCTION__); 107 108 /* allocate the private data structure */ 109 serial->port->private = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL); 110 if (!serial->port->private) 111 return (-1); /* error */ 112 113 /* set initial values */ 114 priv = (struct cyberjack_private *)serial->port->private; 115 priv->rdtodo = 0; 116 priv->wrfilled = 0; 117 priv->wrsent = 0; 118 119 init_waitqueue_head(&serial->port->write_wait); 120 121 return( 0 ); 122} 123 124static void cyberjack_shutdown (struct usb_serial *serial) 125{ 126 int i; 127 128 dbg("%s", __FUNCTION__); 129 130 for (i=0; i < serial->num_ports; ++i) { 131 /* My special items, the standard routines free my urbs */ 132 if (serial->port[i].private) 133 kfree(serial->port[i].private); 134 } 135} 136 137static int cyberjack_open (struct usb_serial_port *port, struct file *filp) 138{ 139 struct cyberjack_private *priv; 140 int result = 0; 141 142 if (port_paranoia_check (port, __FUNCTION__)) 143 return -ENODEV; 144 145 dbg("%s - port %d", __FUNCTION__, port->number); 146 147 /* force low_latency on so that our tty_push actually forces 148 * the data through, otherwise it is scheduled, and with high 149 * data rates (like with OHCI) data can get lost. 150 */ 151 port->tty->low_latency = 1; 152 153 priv = (struct cyberjack_private *)port->private; 154 priv->rdtodo = 0; 155 priv->wrfilled = 0; 156 priv->wrsent = 0; 157 158 /* shutdown any bulk reads that might be going on */ 159 usb_unlink_urb (port->write_urb); 160 usb_unlink_urb (port->read_urb); 161 usb_unlink_urb (port->interrupt_in_urb); 162 163 port->interrupt_in_urb->dev = port->serial->dev; 164 result = usb_submit_urb(port->interrupt_in_urb); 165 if (result) 166 err(" usb_submit_urb(read int) failed"); 167 dbg("%s - usb_submit_urb(int urb)", __FUNCTION__); 168 169 return result; 170} 171 172static void cyberjack_close (struct usb_serial_port *port, struct file *filp) 173{ 174 dbg("%s - port %d", __FUNCTION__, port->number); 175 176 if (port->serial->dev) { 177 /* shutdown any bulk reads that might be going on */ 178 usb_unlink_urb (port->write_urb); 179 usb_unlink_urb (port->read_urb); 180 usb_unlink_urb (port->interrupt_in_urb); 181 } 182} 183 184static int cyberjack_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) 185{ 186 struct usb_serial *serial = port->serial; 187 struct cyberjack_private *priv = (struct cyberjack_private *)port->private; 188 int result; 189 int wrexpected; 190 191 dbg("%s - port %d", __FUNCTION__, port->number); 192 dbg("%s - from_user %d", __FUNCTION__, from_user); 193 194 if (count == 0) { 195 dbg("%s - write request of 0 bytes", __FUNCTION__); 196 return (0); 197 } 198 199 if (port->write_urb->status == -EINPROGRESS) { 200 dbg("%s - already writing", __FUNCTION__); 201 return (0); 202 } 203 204 if( (count+priv->wrfilled)>sizeof(priv->wrbuf) ) { 205 /* To much data for buffer. Reset buffer. */ 206 priv->wrfilled=0; 207 return (0); 208 } 209 210 /* Copy data */ 211 if (from_user) { 212 if (copy_from_user(priv->wrbuf+priv->wrfilled, buf, count)) { 213 return -EFAULT; 214 } 215 } else { 216 memcpy (priv->wrbuf+priv->wrfilled, buf, count); 217 } 218 usb_serial_debug_data (__FILE__, __FUNCTION__, count, 219 priv->wrbuf+priv->wrfilled); 220 priv->wrfilled += count; 221 222 if( priv->wrfilled >= 3 ) { 223 wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3; 224 dbg("%s - expected data: %d", __FUNCTION__, wrexpected); 225 } else { 226 wrexpected = sizeof(priv->wrbuf); 227 } 228 229 if( priv->wrfilled >= wrexpected ) { 230 /* We have enough data to begin transmission */ 231 int length; 232 233 dbg("%s - transmitting data (frame 1)", __FUNCTION__); 234 length = (wrexpected > port->bulk_out_size) ? port->bulk_out_size : wrexpected; 235 236 memcpy (port->write_urb->transfer_buffer, priv->wrbuf, length ); 237 priv->wrsent=length; 238 239 /* set up our urb */ 240 FILL_BULK_URB(port->write_urb, serial->dev, 241 usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), 242 port->write_urb->transfer_buffer, length, 243 ((serial->type->write_bulk_callback) ? 244 serial->type->write_bulk_callback : 245 cyberjack_write_bulk_callback), 246 port); 247 248 /* send the data out the bulk port */ 249 result = usb_submit_urb(port->write_urb); 250 if (result) { 251 err("%s - failed submitting write urb, error %d", __FUNCTION__, result); 252 /* Throw away data. No better idea what to do with it. */ 253 priv->wrfilled=0; 254 priv->wrsent=0; 255 return 0; 256 } 257 258 dbg("%s - priv->wrsent=%d", __FUNCTION__,priv->wrsent); 259 dbg("%s - priv->wrfilled=%d", __FUNCTION__,priv->wrfilled); 260 261 if( priv->wrsent>=priv->wrfilled ) { 262 dbg("%s - buffer cleaned", __FUNCTION__); 263 memset( priv->wrbuf, 0, sizeof(priv->wrbuf) ); 264 priv->wrfilled=0; 265 priv->wrsent=0; 266 } 267 } 268 269 return (count); 270} 271 272static void cyberjack_read_int_callback( struct urb *urb ) 273{ 274 struct usb_serial_port *port = (struct usb_serial_port *)urb->context; 275 struct cyberjack_private *priv = (struct cyberjack_private *)port->private; 276 struct usb_serial *serial; 277 unsigned char *data = urb->transfer_buffer; 278 279 if (port_paranoia_check (port, __FUNCTION__)) return; 280 281 dbg("%s - port %d", __FUNCTION__, port->number); 282 283 /* the urb might have been killed. */ 284 if (urb->status) 285 return; 286 287 serial = port->serial; 288 if (serial_paranoia_check (serial, __FUNCTION__)) return; 289 290 usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); 291 292 /* React only to interrupts signaling a bulk_in transfer */ 293 if( (urb->actual_length==4) && (data[0]==0x01) ) { 294 short old_rdtodo = priv->rdtodo; 295 int result; 296 297 /* This is a announcement of comming bulk_ins. */ 298 unsigned short size = ((unsigned short)data[3]<<8)+data[2]+3; 299 300 if( (size>259) || (size==0) ) { 301 dbg( "Bad announced bulk_in data length: %d", size ); 302 /* Dunno what is most reliable to do here. */ 303 /* return; */ 304 } 305 306 if( (old_rdtodo+size)<(old_rdtodo) ) { 307 dbg( "To many bulk_in urbs to do." ); 308 return; 309 } 310 311 /* "+=" is probably more fault tollerant than "=" */ 312 priv->rdtodo += size; 313 314 dbg("%s - rdtodo: %d", __FUNCTION__, priv->rdtodo); 315 316 if( !old_rdtodo ) { 317 port->read_urb->dev = port->serial->dev; 318 result = usb_submit_urb(port->read_urb); 319 if( result ) 320 err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); 321 dbg("%s - usb_submit_urb(read urb)", __FUNCTION__); 322 } 323 } 324} 325 326static void cyberjack_read_bulk_callback (struct urb *urb) 327{ 328 struct usb_serial_port *port = (struct usb_serial_port *)urb->context; 329 struct cyberjack_private *priv = (struct cyberjack_private *)port->private; 330 struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); 331 struct tty_struct *tty; 332 unsigned char *data = urb->transfer_buffer; 333 int i; 334 int result; 335 336 dbg("%s - port %d", __FUNCTION__, port->number); 337 338 if (!serial) { 339 dbg("%s - bad serial pointer, exiting", __FUNCTION__); 340 return; 341 } 342 343 if (urb->status) { 344 usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, urb->transfer_buffer); 345 dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); 346 return; 347 } 348 349 usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); 350 351 tty = port->tty; 352 if (urb->actual_length) { 353 for (i = 0; i < urb->actual_length ; ++i) { 354 /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ 355 if(tty->flip.count >= TTY_FLIPBUF_SIZE) { 356 tty_flip_buffer_push(tty); 357 } 358 /* this doesn't actually push the data through unless tty->low_latency is set */ 359 tty_insert_flip_char(tty, data[i], 0); 360 } 361 tty_flip_buffer_push(tty); 362 } 363 364 /* Reduce urbs to do by one. */ 365 priv->rdtodo-=urb->actual_length; 366 /* Just to be sure */ 367 if( priv->rdtodo<0 ) priv->rdtodo=0; 368 369 dbg("%s - rdtodo: %d", __FUNCTION__, priv->rdtodo); 370 371 /* Continue to read if we have still urbs to do. */ 372 if( priv->rdtodo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) { 373 port->read_urb->dev = port->serial->dev; 374 result = usb_submit_urb(port->read_urb); 375 if (result) 376 err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); 377 dbg("%s - usb_submit_urb(read urb)", __FUNCTION__); 378 } 379} 380 381static void cyberjack_write_bulk_callback (struct urb *urb) 382{ 383 struct usb_serial_port *port = (struct usb_serial_port *)urb->context; 384 struct cyberjack_private *priv = (struct cyberjack_private *)port->private; 385 struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); 386 387 dbg("%s - port %d", __FUNCTION__, port->number); 388 389 if (!serial) { 390 dbg("%s - bad serial pointer, exiting", __FUNCTION__); 391 return; 392 } 393 394 if (urb->status) { 395 dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); 396 return; 397 } 398 399 /* only do something if we have more data to send */ 400 if( priv->wrfilled ) { 401 int length, blksize, result; 402 403 if (port->write_urb->status == -EINPROGRESS) { 404 dbg("%s - already writing", __FUNCTION__); 405 return; 406 } 407 408 dbg("%s - transmitting data (frame n)", __FUNCTION__); 409 410 length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ? 411 port->bulk_out_size : (priv->wrfilled - priv->wrsent); 412 413 memcpy (port->write_urb->transfer_buffer, priv->wrbuf + priv->wrsent, 414 length ); 415 priv->wrsent+=length; 416 417 /* set up our urb */ 418 FILL_BULK_URB(port->write_urb, serial->dev, 419 usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), 420 port->write_urb->transfer_buffer, length, 421 ((serial->type->write_bulk_callback) ? 422 serial->type->write_bulk_callback : 423 cyberjack_write_bulk_callback), 424 port); 425 426 /* send the data out the bulk port */ 427 result = usb_submit_urb(port->write_urb); 428 if (result) { 429 err("%s - failed submitting write urb, error %d", __FUNCTION__, result); 430 /* Throw away data. No better idea what to do with it. */ 431 priv->wrfilled=0; 432 priv->wrsent=0; 433 queue_task(&port->tqueue, &tq_immediate); 434 mark_bh(IMMEDIATE_BH); 435 return; 436 } 437 438 dbg("%s - priv->wrsent=%d", __FUNCTION__,priv->wrsent); 439 dbg("%s - priv->wrfilled=%d", __FUNCTION__,priv->wrfilled); 440 441 blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3; 442 443 if( (priv->wrsent>=priv->wrfilled) || (priv->wrsent>=blksize) ) { 444 dbg("%s - buffer cleaned", __FUNCTION__); 445 memset( priv->wrbuf, 0, sizeof(priv->wrbuf) ); 446 priv->wrfilled=0; 447 priv->wrsent=0; 448 } 449 450 queue_task(&port->tqueue, &tq_immediate); 451 mark_bh(IMMEDIATE_BH); 452 return; 453 } 454 455 queue_task(&port->tqueue, &tq_immediate); 456 mark_bh(IMMEDIATE_BH); 457 458 return; 459} 460 461static int __init cyberjack_init (void) 462{ 463 usb_serial_register (&cyberjack_device); 464 465 info(DRIVER_VERSION " " DRIVER_AUTHOR); 466 info(DRIVER_DESC); 467 468 return 0; 469} 470 471static void __exit cyberjack_exit (void) 472{ 473 usb_serial_deregister (&cyberjack_device); 474} 475 476module_init(cyberjack_init); 477module_exit(cyberjack_exit); 478 479MODULE_AUTHOR( DRIVER_AUTHOR ); 480MODULE_DESCRIPTION( DRIVER_DESC ); 481MODULE_LICENSE("GPL"); 482 483MODULE_PARM(debug, "i"); 484MODULE_PARM_DESC(debug, "Debug enabled or not"); 485 486