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