kobil_sct.c revision 606d099cdd1080bbb50ea50dc52d98252f8f10a1
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
53static 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 */
71static int  kobil_startup (struct usb_serial *serial);
72static void kobil_shutdown (struct usb_serial *serial);
73static int  kobil_open (struct usb_serial_port *port, struct file *filp);
74static void kobil_close (struct usb_serial_port *port, struct file *filp);
75static int  kobil_write (struct usb_serial_port *port,
76			 const unsigned char *buf, int count);
77static int  kobil_write_room(struct usb_serial_port *port);
78static int  kobil_ioctl(struct usb_serial_port *port, struct file *file,
79			unsigned int cmd, unsigned long arg);
80static int  kobil_tiocmget(struct usb_serial_port *port, struct file *file);
81static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
82			   unsigned int set, unsigned int clear);
83static void kobil_read_int_callback( struct urb *urb );
84static void kobil_write_callback( struct urb *purb );
85
86
87static 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
96MODULE_DEVICE_TABLE (usb, id_table);
97
98static 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
107static 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
131struct 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
143static 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
201static 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
216static 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
347static 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
360static 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
405static void kobil_write_callback( struct urb *purb )
406{
407}
408
409
410static 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
493static int kobil_write_room (struct usb_serial_port *port)
494{
495	//dbg("%s - port %d", __FUNCTION__, port->number);
496	return 8;
497}
498
499
500static 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
542static 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
608static 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
725static 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;
739failed_usb_register:
740	usb_serial_deregister(&kobil_device);
741failed_usb_serial_register:
742	return retval;
743}
744
745
746static void __exit kobil_exit (void)
747{
748	usb_deregister (&kobil_driver);
749	usb_serial_deregister (&kobil_device);
750}
751
752module_init(kobil_init);
753module_exit(kobil_exit);
754
755MODULE_AUTHOR( DRIVER_AUTHOR );
756MODULE_DESCRIPTION( DRIVER_DESC );
757MODULE_LICENSE( "GPL" );
758
759module_param(debug, bool, S_IRUGO | S_IWUSR);
760MODULE_PARM_DESC(debug, "Debug enabled or not");
761