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