kobil_sct.c 20 KB

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