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