mct_u232.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:23k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * MCT (Magic Control Technology Corp.) USB RS232 Converter Driver
  3.  *
  4.  *   Copyright (C) 2000 Wolfgang Grandegger (wolfgang@ces.ch)
  5.  *
  6.  *   This program is free software; you can redistribute it and/or modify
  7.  *   it under the terms of the GNU General Public License as published by
  8.  *   the Free Software Foundation; either version 2 of the License, or
  9.  *   (at your option) any later version.
  10.  *
  11.  * This program is largely derived from the Belkin USB Serial Adapter Driver
  12.  * (see belkin_sa.[ch]). All of the information about the device was acquired
  13.  * by using SniffUSB on Windows98. For technical details see mct_u232.h.
  14.  *
  15.  * William G. Greathouse and Greg Kroah-Hartman provided great help on how to
  16.  * do the reverse engineering and how to write a USB serial device driver.
  17.  *
  18.  * TO BE DONE, TO BE CHECKED:
  19.  *   DTR/RTS signal handling may be incomplete or incorrect. I have mainly
  20.  *   implemented what I have seen with SniffUSB or found in belkin_sa.c.
  21.  *   For further TODOs check also belkin_sa.c.
  22.  *
  23.  * TEST STATUS:
  24.  *   Basic tests have been performed with minicom/zmodem transfers and
  25.  *   modem dialing under Linux 2.4.0-test10 (for me it works fine).
  26.  *
  27.  * 10-Nov-2001 Wolfgang Grandegger
  28.  *   - Fixed an endianess problem with the baudrate selection for PowerPC.
  29.  *
  30.  * 06-Dec-2001 Martin Hamilton <martinh@gnu.org>
  31.  * Added support for the Belkin F5U109 DB9 adaptor
  32.  *
  33.  * 30-May-2001 Greg Kroah-Hartman
  34.  * switched from using spinlock to a semaphore, which fixes lots of problems.
  35.  *
  36.  * 04-May-2001 Stelian Pop
  37.  *   - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes
  38.  *     instead of the device reported 32 (using 32 bytes causes many data
  39.  *     loss, Windows driver uses 16 too).
  40.  *
  41.  * 02-May-2001 Stelian Pop
  42.  *   - Fixed the baud calculation for Sitecom U232-P25 model
  43.  *
  44.  * 08-Apr-2001 gb
  45.  *   - Identify version on module load.
  46.  *
  47.  * 06-Jan-2001 Cornel Ciocirlan 
  48.  *   - Added support for Sitecom U232-P25 model (Product Id 0x0230)
  49.  *   - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200)
  50.  *
  51.  * 29-Nov-2000 Greg Kroah-Hartman
  52.  *   - Added device id table to fit with 2.4.0-test11 structure.
  53.  *   - took out DEAL_WITH_TWO_INT_IN_ENDPOINTS #define as it's not needed
  54.  *     (lots of things will change if/when the usb-serial core changes to
  55.  *     handle these issues.
  56.  *
  57.  * 27-Nov-2000 Wolfgang Grandegger
  58.  *   A version for kernel 2.4.0-test10 released to the Linux community 
  59.  *   (via linux-usb-devel).
  60.  */
  61. #include <linux/config.h>
  62. #include <linux/kernel.h>
  63. #include <linux/errno.h>
  64. #include <linux/init.h>
  65. #include <linux/slab.h>
  66. #include <linux/tty.h>
  67. #include <linux/tty_driver.h>
  68. #include <linux/tty_flip.h>
  69. #include <linux/module.h>
  70. #include <linux/spinlock.h>
  71. #include <asm/uaccess.h>
  72. #include <linux/usb.h>
  73. #ifdef CONFIG_USB_SERIAL_DEBUG
  74.   static int debug = 1;
  75. #else
  76.   static int debug;
  77. #endif
  78. #include "usb-serial.h"
  79. #include "mct_u232.h"
  80. /*
  81.  * Version Information
  82.  */
  83. #define DRIVER_VERSION "v1.1"
  84. #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
  85. #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
  86. /*
  87.  * Some not properly written applications do not handle the return code of
  88.  * write() correctly. This can result in character losses. A work-a-round
  89.  * can be compiled in with the following definition. This work-a-round
  90.  * should _NOT_ be part of an 'official' kernel release, of course!
  91.  */
  92. #undef FIX_WRITE_RETURN_CODE_PROBLEM
  93. #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
  94. static int write_blocking; /* disabled by default */
  95. #endif
  96. /*
  97.  * Function prototypes
  98.  */
  99. static int  mct_u232_startup          (struct usb_serial *serial);
  100. static void mct_u232_shutdown          (struct usb_serial *serial);
  101. static int  mct_u232_open          (struct usb_serial_port *port,
  102.   struct file *filp);
  103. static void mct_u232_close          (struct usb_serial_port *port,
  104.   struct file *filp);
  105. #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
  106. static int  mct_u232_write          (struct usb_serial_port *port,
  107.   int from_user,
  108.   const unsigned char *buf,
  109.   int count);
  110. static void mct_u232_write_bulk_callback (struct urb *urb);
  111. #endif
  112. static void mct_u232_read_int_callback   (struct urb *urb);
  113. static void mct_u232_set_termios         (struct usb_serial_port *port,
  114.   struct termios * old);
  115. static int  mct_u232_ioctl          (struct usb_serial_port *port,
  116.   struct file * file,
  117.   unsigned int cmd,
  118.   unsigned long arg);
  119. static void mct_u232_break_ctl          (struct usb_serial_port *port,
  120.   int break_state );
  121. /*
  122.  * All of the device info needed for the MCT USB-RS232 converter.
  123.  */
  124. static struct usb_device_id id_table_combined [] = {
  125. { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
  126. { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
  127. { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
  128. { USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
  129. { } /* Terminating entry */
  130. };
  131. MODULE_DEVICE_TABLE (usb, id_table_combined);
  132. static struct usb_serial_device_type mct_u232_device = {
  133. .owner =      THIS_MODULE,
  134. .name =      "Magic Control Technology USB-RS232",
  135. .id_table =      id_table_combined,
  136. .num_interrupt_in =  2,
  137. .num_bulk_in =      0,
  138. .num_bulk_out =      1,
  139. .num_ports =      1,
  140. .open =      mct_u232_open,
  141. .close =      mct_u232_close,
  142. #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
  143. .write =      mct_u232_write,
  144. .write_bulk_callback = mct_u232_write_bulk_callback,
  145. #endif
  146. .read_int_callback = mct_u232_read_int_callback,
  147. .ioctl =      mct_u232_ioctl,
  148. .set_termios =      mct_u232_set_termios,
  149. .break_ctl =      mct_u232_break_ctl,
  150. .startup =      mct_u232_startup,
  151. .shutdown =      mct_u232_shutdown,
  152. };
  153. struct mct_u232_private {
  154. unsigned long      control_state; /* Modem Line Setting (TIOCM) */
  155. unsigned char        last_lcr;      /* Line Control Register */
  156. unsigned char      last_lsr;      /* Line Status Register */
  157. unsigned char      last_msr;      /* Modem Status Register */
  158. };
  159. /*
  160.  * Handle vendor specific USB requests
  161.  */
  162. #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
  163. static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) {
  164. if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID
  165.   || serial->dev->descriptor.idProduct == MCT_U232_BELKIN_F5U109_PID) {
  166. switch (value) {
  167. case    300: return 0x01;
  168. case    600: return 0x02; /* this one not tested */
  169. case   1200: return 0x03;
  170. case   2400: return 0x04;
  171. case   4800: return 0x06;
  172. case   9600: return 0x08;
  173. case  19200: return 0x09;
  174. case  38400: return 0x0a;
  175. case  57600: return 0x0b;
  176. case 115200: return 0x0c;
  177. default:     return -1; /* normally not reached */
  178. }
  179. }
  180. else
  181. return MCT_U232_BAUD_RATE(value);
  182. }
  183. static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
  184. {
  185. unsigned int divisor;
  186.         int rc;
  187. divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
  188.         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
  189.                              MCT_U232_SET_BAUD_RATE_REQUEST,
  190.      MCT_U232_SET_REQUEST_TYPE,
  191.                              0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
  192.      WDR_TIMEOUT);
  193. if (rc < 0)
  194. err("Set BAUD RATE %d failed (error = %d)", value, rc);
  195. dbg("set_baud_rate: value: %d, divisor: 0x%x", value, divisor);
  196.         return rc;
  197. } /* mct_u232_set_baud_rate */
  198. static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
  199. {
  200.         int rc;
  201.         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
  202.                              MCT_U232_SET_LINE_CTRL_REQUEST,
  203.      MCT_U232_SET_REQUEST_TYPE,
  204.                              0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
  205.      WDR_TIMEOUT);
  206. if (rc < 0)
  207. err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc);
  208. dbg("set_line_ctrl: 0x%x", lcr);
  209.         return rc;
  210. } /* mct_u232_set_line_ctrl */
  211. static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
  212.    unsigned long control_state)
  213. {
  214.         int rc;
  215. unsigned char mcr = MCT_U232_MCR_NONE;
  216. if (control_state & TIOCM_DTR)
  217. mcr |= MCT_U232_MCR_DTR;
  218. if (control_state & TIOCM_RTS)
  219. mcr |= MCT_U232_MCR_RTS;
  220.         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
  221.                              MCT_U232_SET_MODEM_CTRL_REQUEST,
  222.      MCT_U232_SET_REQUEST_TYPE,
  223.                              0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
  224.      WDR_TIMEOUT);
  225. if (rc < 0)
  226. err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
  227. dbg("set_modem_ctrl: state=0x%lx ==> mcr=0x%x", control_state, mcr);
  228.         return rc;
  229. } /* mct_u232_set_modem_ctrl */
  230. static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr)
  231. {
  232.         int rc;
  233.         rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
  234.                              MCT_U232_GET_MODEM_STAT_REQUEST,
  235.      MCT_U232_GET_REQUEST_TYPE,
  236.                              0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
  237.      WDR_TIMEOUT);
  238. if (rc < 0) {
  239. err("Get MODEM STATus failed (error = %d)", rc);
  240. *msr = 0;
  241. }
  242. dbg("get_modem_stat: 0x%x", *msr);
  243.         return rc;
  244. } /* mct_u232_get_modem_stat */
  245. static void mct_u232_msr_to_state(unsigned long *control_state, unsigned char msr)
  246. {
  247.   /* Translate Control Line states */
  248. if (msr & MCT_U232_MSR_DSR)
  249. *control_state |=  TIOCM_DSR;
  250. else
  251. *control_state &= ~TIOCM_DSR;
  252. if (msr & MCT_U232_MSR_CTS)
  253. *control_state |=  TIOCM_CTS;
  254. else
  255. *control_state &= ~TIOCM_CTS;
  256. if (msr & MCT_U232_MSR_RI)
  257. *control_state |=  TIOCM_RI;
  258. else
  259. *control_state &= ~TIOCM_RI;
  260. if (msr & MCT_U232_MSR_CD)
  261. *control_state |=  TIOCM_CD;
  262. else
  263. *control_state &= ~TIOCM_CD;
  264.   dbg("msr_to_state: msr=0x%x ==> state=0x%lx", msr, *control_state);
  265. } /* mct_u232_msr_to_state */
  266. /*
  267.  * Driver's tty interface functions
  268.  */
  269. static int mct_u232_startup (struct usb_serial *serial)
  270. {
  271. struct mct_u232_private *priv;
  272. /* allocate the private data structure */
  273. serial->port->private = kmalloc(sizeof(struct mct_u232_private),
  274. GFP_KERNEL);
  275. if (!serial->port->private)
  276. return (-1); /* error */
  277. priv = (struct mct_u232_private *)serial->port->private;
  278. /* set initial values for control structures */
  279. priv->control_state = 0;
  280. priv->last_lsr = 0;
  281. priv->last_msr = 0;
  282. init_waitqueue_head(&serial->port->write_wait);
  283. return (0);
  284. } /* mct_u232_startup */
  285. static void mct_u232_shutdown (struct usb_serial *serial)
  286. {
  287. int i;
  288. dbg("%s", __FUNCTION__);
  289. /* stop reads and writes on all ports */
  290. for (i=0; i < serial->num_ports; ++i) {
  291. /* My special items, the standard routines free my urbs */
  292. if (serial->port[i].private)
  293. kfree(serial->port[i].private);
  294. }
  295. } /* mct_u232_shutdown */
  296. static int  mct_u232_open (struct usb_serial_port *port, struct file *filp)
  297. {
  298. struct usb_serial *serial = port->serial;
  299. struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
  300. int retval = 0;
  301. dbg("%s port %d", __FUNCTION__, port->number);
  302. /* Compensate for a hardware bug: although the Sitecom U232-P25
  303.  * device reports a maximum output packet size of 32 bytes,
  304.  * it seems to be able to accept only 16 bytes (and that's what
  305.  * SniffUSB says too...)
  306.  */
  307. if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID)
  308. port->bulk_out_size = 16;
  309. /* Do a defined restart: the normal serial device seems to 
  310.  * always turn on DTR and RTS here, so do the same. I'm not
  311.  * sure if this is really necessary. But it should not harm
  312.  * either.
  313.  */
  314. if (port->tty->termios->c_cflag & CBAUD)
  315. priv->control_state = TIOCM_DTR | TIOCM_RTS;
  316. else
  317. priv->control_state = 0;
  318. mct_u232_set_modem_ctrl(serial, priv->control_state);
  319. priv->last_lcr = (MCT_U232_DATA_BITS_8 | 
  320.   MCT_U232_PARITY_NONE |
  321.   MCT_U232_STOP_BITS_1);
  322. mct_u232_set_line_ctrl(serial, priv->last_lcr);
  323. /* Read modem status and update control state */
  324. mct_u232_get_modem_stat(serial, &priv->last_msr);
  325. mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
  326. {
  327. /* Puh, that's dirty */
  328. struct usb_serial_port *rport;
  329. rport = &serial->port[1];
  330. rport->tty = port->tty;
  331. rport->private = port->private;
  332. port->read_urb = rport->interrupt_in_urb;
  333. }
  334. port->read_urb->dev = port->serial->dev;
  335. retval = usb_submit_urb(port->read_urb);
  336. if (retval) {
  337. err("usb_submit_urb(read bulk) failed");
  338. goto exit;
  339. }
  340. port->interrupt_in_urb->dev = port->serial->dev;
  341. retval = usb_submit_urb(port->interrupt_in_urb);
  342. if (retval)
  343. err(" usb_submit_urb(read int) failed");
  344. exit:
  345. return 0;
  346. } /* mct_u232_open */
  347. static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
  348. {
  349. dbg("%s port %d", __FUNCTION__, port->number);
  350. if (port->serial->dev) {
  351. /* shutdown our urbs */
  352. usb_unlink_urb (port->write_urb);
  353. usb_unlink_urb (port->read_urb);
  354. usb_unlink_urb (port->interrupt_in_urb);
  355. }
  356. } /* mct_u232_close */
  357. #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
  358. /* The generic routines work fine otherwise */
  359. static int mct_u232_write (struct usb_serial_port *port, int from_user,
  360.    const unsigned char *buf, int count)
  361. {
  362. struct usb_serial *serial = port->serial;
  363. int result, bytes_sent, size;
  364. dbg("%s - port %d", __FUNCTION__, port->number);
  365. if (count == 0) {
  366. dbg("%s - write request of 0 bytes", __FUNCTION__);
  367. return (0);
  368. }
  369. /* only do something if we have a bulk out endpoint */
  370. if (!serial->num_bulk_out)
  371. return(0);;
  372. /* another write is still pending? */
  373. if (port->write_urb->status == -EINPROGRESS) {
  374. dbg("%s - already writing", __FUNCTION__);
  375. return (0);
  376. }
  377. bytes_sent = 0;
  378. while (count > 0) {
  379. size = (count > port->bulk_out_size) ? port->bulk_out_size : count;
  380. usb_serial_debug_data (__FILE__, __FUNCTION__, size, buf);
  381. if (from_user) {
  382. if (copy_from_user(port->write_urb->transfer_buffer, buf, size)) {
  383. return -EFAULT;
  384. }
  385. }
  386. else {
  387. memcpy (port->write_urb->transfer_buffer, buf, size);
  388. }
  389. /* set up our urb */
  390. FILL_BULK_URB(port->write_urb, serial->dev,
  391.       usb_sndbulkpipe(serial->dev,
  392.       port->bulk_out_endpointAddress),
  393.       port->write_urb->transfer_buffer, size,
  394.       ((serial->type->write_bulk_callback) ?
  395.        serial->type->write_bulk_callback :
  396.        mct_u232_write_bulk_callback),
  397.       port);
  398. /* send the data out the bulk port */
  399. result = usb_submit_urb(port->write_urb);
  400. if (result) {
  401. err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
  402. return result;
  403. }
  404. bytes_sent += size;
  405. if (write_blocking)
  406. interruptible_sleep_on(&port->write_wait);
  407. else
  408. break;
  409. buf += size;
  410. count -= size;
  411. }
  412. return bytes_sent;
  413. } /* mct_u232_write */
  414. static void mct_u232_write_bulk_callback (struct urb *urb)
  415. {
  416. struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
  417. struct usb_serial *serial = port->serial;
  418.         struct tty_struct *tty = port->tty;
  419. dbg("%s - port %d", __FUNCTION__, port->number);
  420. if (!serial) {
  421. dbg("%s - bad serial pointer, exiting", __FUNCTION__);
  422. return;
  423. }
  424. if (urb->status) {
  425. dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
  426.     urb->status);
  427. return;
  428. }
  429. if (write_blocking) {
  430. wake_up_interruptible(&port->write_wait);
  431. if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
  432.     tty->ldisc.write_wakeup)
  433. (tty->ldisc.write_wakeup)(tty);
  434. wake_up_interruptible(&tty->write_wait);
  435. } else {
  436. /* from generic_write_bulk_callback */
  437. queue_task(&port->tqueue, &tq_immediate);
  438. mark_bh(IMMEDIATE_BH);
  439. }
  440. return;
  441. } /* mct_u232_write_bulk_callback */
  442. #endif
  443. static void mct_u232_read_int_callback (struct urb *urb)
  444. {
  445. struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
  446. struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
  447. struct usb_serial *serial = port->serial;
  448. struct tty_struct *tty;
  449. unsigned char *data = urb->transfer_buffer;
  450.         dbg("%s - port %d", __FUNCTION__, port->number);
  451. /* The urb might have been killed. */
  452.         if (urb->status) {
  453.                 dbg("%s - nonzero read bulk status received: %d", __FUNCTION__,
  454.     urb->status);
  455.                 return;
  456.         }
  457. if (!serial) {
  458. dbg("%s - bad serial pointer, exiting", __FUNCTION__);
  459. return;
  460. }
  461. usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
  462. /*
  463.  * Work-a-round: handle the 'usual' bulk-in pipe here
  464.  */
  465. if (urb->transfer_buffer_length > 2) {
  466. int i;
  467. tty = port->tty;
  468. if (urb->actual_length) {
  469. for (i = 0; i < urb->actual_length ; ++i) {
  470. tty_insert_flip_char(tty, data[i], 0);
  471. }
  472. tty_flip_buffer_push(tty);
  473. }
  474. /* INT urbs are automatically re-submitted */
  475. return;
  476. }
  477. /*
  478.  * The interrupt-in pipe signals exceptional conditions (modem line
  479.  * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
  480.  */
  481. priv->last_msr = data[MCT_U232_MSR_INDEX];
  482. /* Record Control Line states */
  483. mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
  484. #if 0
  485. /* Not yet handled. See belin_sa.c for further information */
  486. /* Now to report any errors */
  487. priv->last_lsr = data[MCT_U232_LSR_INDEX];
  488. /*
  489.  * fill in the flip buffer here, but I do not know the relation
  490.  * to the current/next receive buffer or characters.  I need
  491.  * to look in to this before committing any code.
  492.  */
  493. if (priv->last_lsr & MCT_U232_LSR_ERR) {
  494. tty = port->tty;
  495. /* Overrun Error */
  496. if (priv->last_lsr & MCT_U232_LSR_OE) {
  497. }
  498. /* Parity Error */
  499. if (priv->last_lsr & MCT_U232_LSR_PE) {
  500. }
  501. /* Framing Error */
  502. if (priv->last_lsr & MCT_U232_LSR_FE) {
  503. }
  504. /* Break Indicator */
  505. if (priv->last_lsr & MCT_U232_LSR_BI) {
  506. }
  507. }
  508. #endif
  509. /* INT urbs are automatically re-submitted */
  510. } /* mct_u232_read_int_callback */
  511. static void mct_u232_set_termios (struct usb_serial_port *port,
  512.   struct termios *old_termios)
  513. {
  514. struct usb_serial *serial = port->serial;
  515. struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
  516. unsigned int iflag = port->tty->termios->c_iflag;
  517. unsigned int old_iflag = old_termios->c_iflag;
  518. unsigned int cflag = port->tty->termios->c_cflag;
  519. unsigned int old_cflag = old_termios->c_cflag;
  520. /*
  521.  * Update baud rate
  522.  */
  523. if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {
  524.         /* reassert DTR and (maybe) RTS on transition from B0 */
  525. if( (old_cflag & CBAUD) == B0 ) {
  526. dbg("%s: baud was B0", __FUNCTION__);
  527. priv->control_state |= TIOCM_DTR;
  528. /* don't set RTS if using hardware flow control */
  529. if (!(old_cflag & CRTSCTS)) {
  530. priv->control_state |= TIOCM_RTS;
  531. }
  532. mct_u232_set_modem_ctrl(serial, priv->control_state);
  533. }
  534. switch(cflag & CBAUD) {
  535. case B0: /* handled below */
  536. break;
  537. case B300: mct_u232_set_baud_rate(serial, 300);
  538. break;
  539. case B600: mct_u232_set_baud_rate(serial, 600);
  540. break;
  541. case B1200: mct_u232_set_baud_rate(serial, 1200);
  542. break;
  543. case B2400: mct_u232_set_baud_rate(serial, 2400);
  544. break;
  545. case B4800: mct_u232_set_baud_rate(serial, 4800);
  546. break;
  547. case B9600: mct_u232_set_baud_rate(serial, 9600);
  548. break;
  549. case B19200: mct_u232_set_baud_rate(serial, 19200);
  550. break;
  551. case B38400: mct_u232_set_baud_rate(serial, 38400);
  552. break;
  553. case B57600: mct_u232_set_baud_rate(serial, 57600);
  554. break;
  555. case B115200: mct_u232_set_baud_rate(serial, 115200);
  556. break;
  557. default: err("MCT USB-RS232 converter: unsupported baudrate request, using default of 9600");
  558. mct_u232_set_baud_rate(serial, 9600); break;
  559. }
  560. if ((cflag & CBAUD) == B0 ) {
  561. dbg("%s: baud is B0", __FUNCTION__);
  562. /* Drop RTS and DTR */
  563. priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
  564.          mct_u232_set_modem_ctrl(serial, priv->control_state);
  565. }
  566. }
  567. /*
  568.  * Update line control register (LCR)
  569.  */
  570. if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
  571.     || (cflag & CSIZE) != (old_cflag & CSIZE)
  572.     || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
  573. priv->last_lcr = 0;
  574. /* set the parity */
  575. if (cflag & PARENB)
  576. priv->last_lcr |= (cflag & PARODD) ?
  577. MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
  578. else
  579. priv->last_lcr |= MCT_U232_PARITY_NONE;
  580. /* set the number of data bits */
  581. switch (cflag & CSIZE) {
  582. case CS5:
  583. priv->last_lcr |= MCT_U232_DATA_BITS_5; break;
  584. case CS6:
  585. priv->last_lcr |= MCT_U232_DATA_BITS_6; break;
  586. case CS7:
  587. priv->last_lcr |= MCT_U232_DATA_BITS_7; break;
  588. case CS8:
  589. priv->last_lcr |= MCT_U232_DATA_BITS_8; break;
  590. default:
  591. err("CSIZE was not CS5-CS8, using default of 8");
  592. priv->last_lcr |= MCT_U232_DATA_BITS_8;
  593. break;
  594. }
  595. /* set the number of stop bits */
  596. priv->last_lcr |= (cflag & CSTOPB) ?
  597. MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
  598. mct_u232_set_line_ctrl(serial, priv->last_lcr);
  599. }
  600. /*
  601.  * Set flow control: well, I do not really now how to handle DTR/RTS.
  602.  * Just do what we have seen with SniffUSB on Win98.
  603.  */
  604. if( (iflag & IXOFF) != (old_iflag & IXOFF)
  605.     || (iflag & IXON) != (old_iflag & IXON)
  606.     ||  (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {
  607. /* Drop DTR/RTS if no flow control otherwise assert */
  608. if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
  609. priv->control_state |= TIOCM_DTR | TIOCM_RTS;
  610. else
  611. priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
  612. mct_u232_set_modem_ctrl(serial, priv->control_state);
  613. }
  614. } /* mct_u232_set_termios */
  615. static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
  616. {
  617. struct usb_serial *serial = port->serial;
  618. struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
  619. unsigned char lcr = priv->last_lcr;
  620. dbg("%sstate=%d", __FUNCTION__, break_state);
  621. if (break_state)
  622. lcr |= MCT_U232_SET_BREAK;
  623. mct_u232_set_line_ctrl(serial, lcr);
  624. } /* mct_u232_break_ctl */
  625. static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
  626.    unsigned int cmd, unsigned long arg)
  627. {
  628. struct usb_serial *serial = port->serial;
  629. struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
  630. int mask;
  631. dbg("%scmd=0x%x", __FUNCTION__, cmd);
  632. /* Based on code from acm.c and others */
  633. switch (cmd) {
  634. case TIOCMGET:
  635. return put_user(priv->control_state, (unsigned long *) arg);
  636. break;
  637. case TIOCMSET: /* Turns on and off the lines as specified by the mask */
  638. case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
  639. case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
  640. if (get_user(mask, (unsigned long *) arg))
  641. return -EFAULT;
  642. if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) {
  643. /* RTS needs set */
  644. if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||
  645.     (cmd == TIOCMBIS) )
  646. priv->control_state |=  TIOCM_RTS;
  647. else
  648. priv->control_state &= ~TIOCM_RTS;
  649. }
  650. if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) {
  651. /* DTR needs set */
  652. if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) ||
  653.     (cmd == TIOCMBIS) )
  654. priv->control_state |=  TIOCM_DTR;
  655. else
  656. priv->control_state &= ~TIOCM_DTR;
  657. }
  658. mct_u232_set_modem_ctrl(serial, priv->control_state);
  659. break;
  660. case TIOCMIWAIT:
  661. /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
  662. /* TODO */
  663. return( 0 );
  664. case TIOCGICOUNT:
  665. /* return count of modemline transitions */
  666. /* TODO */
  667. return 0;
  668. default:
  669. dbg("%s: arg not supported - 0x%04x", __FUNCTION__,cmd);
  670. return(-ENOIOCTLCMD);
  671. break;
  672. }
  673. return 0;
  674. } /* mct_u232_ioctl */
  675. static int __init mct_u232_init (void)
  676. {
  677. usb_serial_register (&mct_u232_device);
  678. info(DRIVER_DESC " " DRIVER_VERSION);
  679. return 0;
  680. }
  681. static void __exit mct_u232_exit (void)
  682. {
  683. usb_serial_deregister (&mct_u232_device);
  684. }
  685. module_init (mct_u232_init);
  686. module_exit(mct_u232_exit);
  687. MODULE_AUTHOR( DRIVER_AUTHOR );
  688. MODULE_DESCRIPTION( DRIVER_DESC );
  689. MODULE_LICENSE("GPL");
  690. #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
  691. MODULE_PARM(write_blocking, "i");
  692. MODULE_PARM_DESC(write_blocking, 
  693.  "The write function will block to write out all data");
  694. #endif
  695. MODULE_PARM(debug, "i");
  696. MODULE_PARM_DESC(debug, "Debug enabled or not");