mct_u232.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:27k
源码类别:

嵌入式Linux

开发平台:

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/sched.h>
  64. #include <linux/signal.h>
  65. #include <linux/errno.h>
  66. #include <linux/poll.h>
  67. #include <linux/init.h>
  68. #include <linux/slab.h>
  69. #include <linux/fcntl.h>
  70. #include <linux/tty.h>
  71. #include <linux/tty_driver.h>
  72. #include <linux/tty_flip.h>
  73. #include <linux/module.h>
  74. #include <linux/spinlock.h>
  75. #include <linux/usb.h>
  76. #ifdef CONFIG_USB_SERIAL_DEBUG
  77.   static int debug = 1;
  78. #else
  79.   static int debug;
  80. #endif
  81. #include "usb-serial.h"
  82. #include "mct_u232.h"
  83. /*
  84.  * Version Information
  85.  */
  86. #define DRIVER_VERSION "v1.1"
  87. #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
  88. #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
  89. /*
  90.  * Some not properly written applications do not handle the return code of
  91.  * write() correctly. This can result in character losses. A work-a-round
  92.  * can be compiled in with the following definition. This work-a-round
  93.  * should _NOT_ be part of an 'official' kernel release, of course!
  94.  */
  95. #undef FIX_WRITE_RETURN_CODE_PROBLEM
  96. #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
  97. static int write_blocking; /* disabled by default */
  98. #endif
  99. /*
  100.  * Function prototypes
  101.  */
  102. static int  mct_u232_startup          (struct usb_serial *serial);
  103. static void mct_u232_shutdown          (struct usb_serial *serial);
  104. static int  mct_u232_open          (struct usb_serial_port *port,
  105.   struct file *filp);
  106. static void mct_u232_close          (struct usb_serial_port *port,
  107.   struct file *filp);
  108. #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
  109. static int  mct_u232_write          (struct usb_serial_port *port,
  110.   int from_user,
  111.   const unsigned char *buf,
  112.   int count);
  113. static void mct_u232_write_bulk_callback (struct urb *urb);
  114. #endif
  115. static void mct_u232_read_int_callback   (struct urb *urb);
  116. static void mct_u232_set_termios         (struct usb_serial_port *port,
  117.   struct termios * old);
  118. static int  mct_u232_ioctl          (struct usb_serial_port *port,
  119.   struct file * file,
  120.   unsigned int cmd,
  121.   unsigned long arg);
  122. static void mct_u232_break_ctl          (struct usb_serial_port *port,
  123.   int break_state );
  124. /*
  125.  * All of the device info needed for the MCT USB-RS232 converter.
  126.  */
  127. static __devinitdata struct usb_device_id id_table_combined [] = {
  128. { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
  129. { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
  130. { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
  131. { USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
  132. { } /* Terminating entry */
  133. };
  134. static __devinitdata struct usb_device_id mct_u232_table [] = {
  135.         { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
  136. { USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
  137.         { }                        /* Terminating entry */
  138. };
  139. static __devinitdata struct usb_device_id mct_u232_sitecom_table [] = {
  140.         { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
  141.         { }                        /* Terminating entry */
  142. };
  143. static __devinitdata struct usb_device_id mct_u232_du_h3sp_table [] = {
  144.         { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
  145.         { }                        /* Terminating entry */
  146. };
  147. MODULE_DEVICE_TABLE (usb, id_table_combined);
  148. static struct usb_serial_device_type mct_u232_device = {
  149. name:      "Magic Control Technology USB-RS232",
  150. id_table:      mct_u232_table,
  151. needs_interrupt_in:  MUST_HAVE,  /* 2 interrupt-in endpoints */
  152. needs_bulk_in:      MUST_HAVE_NOT,   /* no bulk-in endpoint */
  153. needs_bulk_out:      MUST_HAVE,       /* 1 bulk-out endpoint */
  154. num_interrupt_in:    2,
  155. num_bulk_in:      0,
  156. num_bulk_out:      1,
  157. num_ports:      1,
  158. open:      mct_u232_open,
  159. close:      mct_u232_close,
  160. #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
  161. write:      mct_u232_write,
  162. write_bulk_callback: mct_u232_write_bulk_callback,
  163. #endif
  164. read_int_callback:   mct_u232_read_int_callback,
  165. ioctl:      mct_u232_ioctl,
  166. set_termios:      mct_u232_set_termios,
  167. break_ctl:      mct_u232_break_ctl,
  168. startup:      mct_u232_startup,
  169. shutdown:      mct_u232_shutdown,
  170. };
  171. static struct usb_serial_device_type mct_u232_sitecom_device = {
  172. name:      "MCT/Sitecom USB-RS232",
  173. id_table:      mct_u232_sitecom_table,
  174. needs_interrupt_in:  MUST_HAVE,  /* 2 interrupt-in endpoints */
  175. needs_bulk_in:      MUST_HAVE_NOT,   /* no bulk-in endpoint */
  176. needs_bulk_out:      MUST_HAVE,       /* 1 bulk-out endpoint */
  177. num_interrupt_in:    2,
  178. num_bulk_in:      0,
  179. num_bulk_out:      1,
  180. num_ports:      1,
  181. open:      mct_u232_open,
  182. close:      mct_u232_close,
  183. #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
  184. write:      mct_u232_write,
  185. write_bulk_callback: mct_u232_write_bulk_callback,
  186. #endif
  187. read_int_callback:   mct_u232_read_int_callback,
  188. ioctl:      mct_u232_ioctl,
  189. set_termios:      mct_u232_set_termios,
  190. break_ctl:      mct_u232_break_ctl,
  191. startup:      mct_u232_startup,
  192. shutdown:      mct_u232_shutdown,
  193. };
  194. static struct usb_serial_device_type mct_u232_du_h3sp_device = {
  195.         name:                "MCT/D-Link DU-H3SP USB BAY",
  196.         id_table:            mct_u232_du_h3sp_table,
  197.         needs_interrupt_in:  MUST_HAVE,  /* 2 interrupt-in endpoints */
  198.         needs_bulk_in:       MUST_HAVE_NOT,   /* no bulk-in endpoint */
  199.         needs_bulk_out:      MUST_HAVE,       /* 1 bulk-out endpoint */
  200.         num_interrupt_in:    2,
  201.         num_bulk_in:         0,
  202.         num_bulk_out:        1,
  203.         num_ports:           1,
  204.         open:                mct_u232_open,
  205.         close:               mct_u232_close,
  206. #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
  207.         write:               mct_u232_write,
  208.         write_bulk_callback: mct_u232_write_bulk_callback,
  209. #endif
  210.         read_int_callback:   mct_u232_read_int_callback,
  211.         ioctl:               mct_u232_ioctl,
  212.         set_termios:         mct_u232_set_termios,
  213.         break_ctl:           mct_u232_break_ctl,
  214.         startup:             mct_u232_startup,
  215.         shutdown:            mct_u232_shutdown,
  216. };
  217. struct mct_u232_private {
  218. unsigned long      control_state; /* Modem Line Setting (TIOCM) */
  219. unsigned char        last_lcr;      /* Line Control Register */
  220. unsigned char      last_lsr;      /* Line Status Register */
  221. unsigned char      last_msr;      /* Modem Status Register */
  222. };
  223. /*
  224.  * Handle vendor specific USB requests
  225.  */
  226. #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
  227. static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) {
  228. if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID
  229.   || serial->dev->descriptor.idProduct == MCT_U232_BELKIN_F5U109_PID) {
  230. switch (value) {
  231. case    300: return 0x01;
  232. case    600: return 0x02; /* this one not tested */
  233. case   1200: return 0x03;
  234. case   2400: return 0x04;
  235. case   4800: return 0x06;
  236. case   9600: return 0x08;
  237. case  19200: return 0x09;
  238. case  38400: return 0x0a;
  239. case  57600: return 0x0b;
  240. case 115200: return 0x0c;
  241. default:     return -1; /* normally not reached */
  242. }
  243. }
  244. else
  245. return MCT_U232_BAUD_RATE(value);
  246. }
  247. static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
  248. {
  249. unsigned int divisor;
  250.         int rc;
  251. divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
  252.         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
  253.                              MCT_U232_SET_BAUD_RATE_REQUEST,
  254.      MCT_U232_SET_REQUEST_TYPE,
  255.                              0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
  256.      WDR_TIMEOUT);
  257. if (rc < 0)
  258. err("Set BAUD RATE %d failed (error = %d)", value, rc);
  259. dbg("set_baud_rate: value: %d, divisor: 0x%x", value, divisor);
  260.         return rc;
  261. } /* mct_u232_set_baud_rate */
  262. static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
  263. {
  264.         int rc;
  265.         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
  266.                              MCT_U232_SET_LINE_CTRL_REQUEST,
  267.      MCT_U232_SET_REQUEST_TYPE,
  268.                              0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
  269.      WDR_TIMEOUT);
  270. if (rc < 0)
  271. err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc);
  272. dbg("set_line_ctrl: 0x%x", lcr);
  273.         return rc;
  274. } /* mct_u232_set_line_ctrl */
  275. static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
  276.    unsigned long control_state)
  277. {
  278.         int rc;
  279. unsigned char mcr = MCT_U232_MCR_NONE;
  280. if (control_state & TIOCM_DTR)
  281. mcr |= MCT_U232_MCR_DTR;
  282. if (control_state & TIOCM_RTS)
  283. mcr |= MCT_U232_MCR_RTS;
  284.         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
  285.                              MCT_U232_SET_MODEM_CTRL_REQUEST,
  286.      MCT_U232_SET_REQUEST_TYPE,
  287.                              0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
  288.      WDR_TIMEOUT);
  289. if (rc < 0)
  290. err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
  291. dbg("set_modem_ctrl: state=0x%lx ==> mcr=0x%x", control_state, mcr);
  292.         return rc;
  293. } /* mct_u232_set_modem_ctrl */
  294. static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr)
  295. {
  296.         int rc;
  297.         rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
  298.                              MCT_U232_GET_MODEM_STAT_REQUEST,
  299.      MCT_U232_GET_REQUEST_TYPE,
  300.                              0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
  301.      WDR_TIMEOUT);
  302. if (rc < 0) {
  303. err("Get MODEM STATus failed (error = %d)", rc);
  304. *msr = 0;
  305. }
  306. dbg("get_modem_stat: 0x%x", *msr);
  307.         return rc;
  308. } /* mct_u232_get_modem_stat */
  309. static void mct_u232_msr_to_state(unsigned long *control_state, unsigned char msr)
  310. {
  311.   /* Translate Control Line states */
  312. if (msr & MCT_U232_MSR_DSR)
  313. *control_state |=  TIOCM_DSR;
  314. else
  315. *control_state &= ~TIOCM_DSR;
  316. if (msr & MCT_U232_MSR_CTS)
  317. *control_state |=  TIOCM_CTS;
  318. else
  319. *control_state &= ~TIOCM_CTS;
  320. if (msr & MCT_U232_MSR_RI)
  321. *control_state |=  TIOCM_RI;
  322. else
  323. *control_state &= ~TIOCM_RI;
  324. if (msr & MCT_U232_MSR_CD)
  325. *control_state |=  TIOCM_CD;
  326. else
  327. *control_state &= ~TIOCM_CD;
  328.   dbg("msr_to_state: msr=0x%x ==> state=0x%lx", msr, *control_state);
  329. } /* mct_u232_msr_to_state */
  330. /*
  331.  * Driver's tty interface functions
  332.  */
  333. static int mct_u232_startup (struct usb_serial *serial)
  334. {
  335. struct mct_u232_private *priv;
  336. /* allocate the private data structure */
  337. serial->port->private = kmalloc(sizeof(struct mct_u232_private),
  338. GFP_KERNEL);
  339. if (!serial->port->private)
  340. return (-1); /* error */
  341. priv = (struct mct_u232_private *)serial->port->private;
  342. /* set initial values for control structures */
  343. priv->control_state = 0;
  344. priv->last_lsr = 0;
  345. priv->last_msr = 0;
  346. init_waitqueue_head(&serial->port->write_wait);
  347. return (0);
  348. } /* mct_u232_startup */
  349. static void mct_u232_shutdown (struct usb_serial *serial)
  350. {
  351. int i;
  352. dbg (__FUNCTION__);
  353. /* stop reads and writes on all ports */
  354. for (i=0; i < serial->num_ports; ++i) {
  355. while (serial->port[i].open_count > 0) {
  356. mct_u232_close (&serial->port[i], NULL);
  357. }
  358. /* My special items, the standard routines free my urbs */
  359. if (serial->port[i].private)
  360. kfree(serial->port[i].private);
  361. }
  362. } /* mct_u232_shutdown */
  363. static int  mct_u232_open (struct usb_serial_port *port, struct file *filp)
  364. {
  365. struct usb_serial *serial = port->serial;
  366. struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
  367. int retval = 0;
  368. dbg(__FUNCTION__" port %d", port->number);
  369. down (&port->sem);
  370. ++port->open_count;
  371. MOD_INC_USE_COUNT;
  372. if (!port->active) {
  373. port->active = 1;
  374. /* Compensate for a hardware bug: although the Sitecom U232-P25
  375.  * device reports a maximum output packet size of 32 bytes,
  376.  * it seems to be able to accept only 16 bytes (and that's what
  377.  * SniffUSB says too...)
  378.  */
  379. if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID)
  380. port->bulk_out_size = 16;
  381. /* Do a defined restart: the normal serial device seems to 
  382.  * always turn on DTR and RTS here, so do the same. I'm not
  383.  * sure if this is really necessary. But it should not harm
  384.  * either.
  385.  */
  386. if (port->tty->termios->c_cflag & CBAUD)
  387. priv->control_state = TIOCM_DTR | TIOCM_RTS;
  388. else
  389. priv->control_state = 0;
  390. mct_u232_set_modem_ctrl(serial, priv->control_state);
  391. priv->last_lcr = (MCT_U232_DATA_BITS_8 | 
  392.   MCT_U232_PARITY_NONE |
  393.   MCT_U232_STOP_BITS_1);
  394. mct_u232_set_line_ctrl(serial, priv->last_lcr);
  395. /* Read modem status and update control state */
  396. mct_u232_get_modem_stat(serial, &priv->last_msr);
  397. mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
  398. {
  399. /* Puh, that's dirty */
  400. struct usb_serial_port *rport;
  401. rport = &serial->port[1];
  402. rport->tty = port->tty;
  403. rport->private = port->private;
  404. port->read_urb = rport->interrupt_in_urb;
  405. }
  406. port->read_urb->dev = port->serial->dev;
  407. retval = usb_submit_urb(port->read_urb);
  408. if (retval) {
  409. err("usb_submit_urb(read bulk) failed");
  410. goto exit;
  411. }
  412. port->interrupt_in_urb->dev = port->serial->dev;
  413. retval = usb_submit_urb(port->interrupt_in_urb);
  414. if (retval)
  415. err(" usb_submit_urb(read int) failed");
  416. }
  417. exit:
  418. up (&port->sem);
  419. return 0;
  420. } /* mct_u232_open */
  421. static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
  422. {
  423. dbg(__FUNCTION__" port %d", port->number);
  424. down (&port->sem);
  425. --port->open_count;
  426. if (port->open_count <= 0) {
  427. if (port->serial->dev) {
  428. /* shutdown our urbs */
  429. usb_unlink_urb (port->write_urb);
  430. usb_unlink_urb (port->read_urb);
  431. usb_unlink_urb (port->interrupt_in_urb);
  432. }
  433. port->active = 0;
  434. }
  435. up (&port->sem);
  436. MOD_DEC_USE_COUNT;
  437. } /* mct_u232_close */
  438. #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
  439. /* The generic routines work fine otherwise */
  440. static int mct_u232_write (struct usb_serial_port *port, int from_user,
  441.    const unsigned char *buf, int count)
  442. {
  443. struct usb_serial *serial = port->serial;
  444. int result, bytes_sent, size;
  445. dbg(__FUNCTION__ " - port %d", port->number);
  446. if (count == 0) {
  447. dbg(__FUNCTION__ " - write request of 0 bytes");
  448. return (0);
  449. }
  450. /* only do something if we have a bulk out endpoint */
  451. if (!serial->num_bulk_out)
  452. return(0);;
  453. /* another write is still pending? */
  454. if (port->write_urb->status == -EINPROGRESS) {
  455. dbg (__FUNCTION__ " - already writing");
  456. return (0);
  457. }
  458. bytes_sent = 0;
  459. while (count > 0) {
  460. down (&port->sem);
  461. size = (count > port->bulk_out_size) ? port->bulk_out_size : count;
  462. usb_serial_debug_data (__FILE__, __FUNCTION__, size, buf);
  463. if (from_user) {
  464. if (copy_from_user(port->write_urb->transfer_buffer, buf, size)) {
  465. up (&port->sem);
  466. return -EFAULT;
  467. }
  468. }
  469. else {
  470. memcpy (port->write_urb->transfer_buffer, buf, size);
  471. }
  472. /* set up our urb */
  473. FILL_BULK_URB(port->write_urb, serial->dev,
  474.       usb_sndbulkpipe(serial->dev,
  475.       port->bulk_out_endpointAddress),
  476.       port->write_urb->transfer_buffer, size,
  477.       ((serial->type->write_bulk_callback) ?
  478.        serial->type->write_bulk_callback :
  479.        mct_u232_write_bulk_callback),
  480.       port);
  481. /* send the data out the bulk port */
  482. result = usb_submit_urb(port->write_urb);
  483. if (result) {
  484. err(__FUNCTION__
  485.     " - failed submitting write urb, error %d", result);
  486. up (&port->sem);
  487. return result;
  488. }
  489. up (&port->sem);
  490. bytes_sent += size;
  491. if (write_blocking)
  492. interruptible_sleep_on(&port->write_wait);
  493. else
  494. break;
  495. buf += size;
  496. count -= size;
  497. }
  498. return bytes_sent;
  499. } /* mct_u232_write */
  500. static void mct_u232_write_bulk_callback (struct urb *urb)
  501. {
  502. struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
  503. struct usb_serial *serial = port->serial;
  504.         struct tty_struct *tty = port->tty;
  505. dbg(__FUNCTION__ " - port %d", port->number);
  506. if (!serial) {
  507. dbg(__FUNCTION__ " - bad serial pointer, exiting");
  508. return;
  509. }
  510. if (urb->status) {
  511. dbg(__FUNCTION__ " - nonzero write bulk status received: %d",
  512.     urb->status);
  513. return;
  514. }
  515. if (write_blocking) {
  516. wake_up_interruptible(&port->write_wait);
  517. if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
  518.     tty->ldisc.write_wakeup)
  519. (tty->ldisc.write_wakeup)(tty);
  520. wake_up_interruptible(&tty->write_wait);
  521. } else {
  522. /* from generic_write_bulk_callback */
  523. queue_task(&port->tqueue, &tq_immediate);
  524. mark_bh(IMMEDIATE_BH);
  525. }
  526. return;
  527. } /* mct_u232_write_bulk_callback */
  528. #endif
  529. static void mct_u232_read_int_callback (struct urb *urb)
  530. {
  531. struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
  532. struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
  533. struct usb_serial *serial = port->serial;
  534. struct tty_struct *tty;
  535. unsigned char *data = urb->transfer_buffer;
  536.         dbg(__FUNCTION__ " - port %d", port->number);
  537. /* The urb might have been killed. */
  538.         if (urb->status) {
  539.                 dbg(__FUNCTION__ " - nonzero read bulk status received: %d",
  540.     urb->status);
  541.                 return;
  542.         }
  543. if (!serial) {
  544. dbg(__FUNCTION__ " - bad serial pointer, exiting");
  545. return;
  546. }
  547. usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
  548. /*
  549.  * Work-a-round: handle the 'usual' bulk-in pipe here
  550.  */
  551. if (urb->transfer_buffer_length > 2) {
  552. int i;
  553. tty = port->tty;
  554. if (urb->actual_length) {
  555. for (i = 0; i < urb->actual_length ; ++i) {
  556. tty_insert_flip_char(tty, data[i], 0);
  557. }
  558. tty_flip_buffer_push(tty);
  559. }
  560. /* INT urbs are automatically re-submitted */
  561. return;
  562. }
  563. /*
  564.  * The interrupt-in pipe signals exceptional conditions (modem line
  565.  * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
  566.  */
  567. priv->last_msr = data[MCT_U232_MSR_INDEX];
  568. /* Record Control Line states */
  569. mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
  570. #if 0
  571. /* Not yet handled. See belin_sa.c for further information */
  572. /* Now to report any errors */
  573. priv->last_lsr = data[MCT_U232_LSR_INDEX];
  574. /*
  575.  * fill in the flip buffer here, but I do not know the relation
  576.  * to the current/next receive buffer or characters.  I need
  577.  * to look in to this before committing any code.
  578.  */
  579. if (priv->last_lsr & MCT_U232_LSR_ERR) {
  580. tty = port->tty;
  581. /* Overrun Error */
  582. if (priv->last_lsr & MCT_U232_LSR_OE) {
  583. }
  584. /* Parity Error */
  585. if (priv->last_lsr & MCT_U232_LSR_PE) {
  586. }
  587. /* Framing Error */
  588. if (priv->last_lsr & MCT_U232_LSR_FE) {
  589. }
  590. /* Break Indicator */
  591. if (priv->last_lsr & MCT_U232_LSR_BI) {
  592. }
  593. }
  594. #endif
  595. /* INT urbs are automatically re-submitted */
  596. } /* mct_u232_read_int_callback */
  597. static void mct_u232_set_termios (struct usb_serial_port *port,
  598.   struct termios *old_termios)
  599. {
  600. struct usb_serial *serial = port->serial;
  601. struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
  602. unsigned int iflag = port->tty->termios->c_iflag;
  603. unsigned int old_iflag = old_termios->c_iflag;
  604. unsigned int cflag = port->tty->termios->c_cflag;
  605. unsigned int old_cflag = old_termios->c_cflag;
  606. /*
  607.  * Update baud rate
  608.  */
  609. if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {
  610.         /* reassert DTR and (maybe) RTS on transition from B0 */
  611. if( (old_cflag & CBAUD) == B0 ) {
  612. dbg(__FUNCTION__ ": baud was B0");
  613. priv->control_state |= TIOCM_DTR;
  614. /* don't set RTS if using hardware flow control */
  615. if (!(old_cflag & CRTSCTS)) {
  616. priv->control_state |= TIOCM_RTS;
  617. }
  618. mct_u232_set_modem_ctrl(serial, priv->control_state);
  619. }
  620. switch(cflag & CBAUD) {
  621. case B0: /* handled below */
  622. break;
  623. case B300: mct_u232_set_baud_rate(serial, 300);
  624. break;
  625. case B600: mct_u232_set_baud_rate(serial, 600);
  626. break;
  627. case B1200: mct_u232_set_baud_rate(serial, 1200);
  628. break;
  629. case B2400: mct_u232_set_baud_rate(serial, 2400);
  630. break;
  631. case B4800: mct_u232_set_baud_rate(serial, 4800);
  632. break;
  633. case B9600: mct_u232_set_baud_rate(serial, 9600);
  634. break;
  635. case B19200: mct_u232_set_baud_rate(serial, 19200);
  636. break;
  637. case B38400: mct_u232_set_baud_rate(serial, 38400);
  638. break;
  639. case B57600: mct_u232_set_baud_rate(serial, 57600);
  640. break;
  641. case B115200: mct_u232_set_baud_rate(serial, 115200);
  642. break;
  643. default: err("MCT USB-RS232 converter: unsupported baudrate request, using default of 9600");
  644. mct_u232_set_baud_rate(serial, 9600); break;
  645. }
  646. if ((cflag & CBAUD) == B0 ) {
  647. dbg(__FUNCTION__ ": baud is B0");
  648. /* Drop RTS and DTR */
  649. priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
  650.          mct_u232_set_modem_ctrl(serial, priv->control_state);
  651. }
  652. }
  653. /*
  654.  * Update line control register (LCR)
  655.  */
  656. if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
  657.     || (cflag & CSIZE) != (old_cflag & CSIZE)
  658.     || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
  659. priv->last_lcr = 0;
  660. /* set the parity */
  661. if (cflag & PARENB)
  662. priv->last_lcr |= (cflag & PARODD) ?
  663. MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
  664. else
  665. priv->last_lcr |= MCT_U232_PARITY_NONE;
  666. /* set the number of data bits */
  667. switch (cflag & CSIZE) {
  668. case CS5:
  669. priv->last_lcr |= MCT_U232_DATA_BITS_5; break;
  670. case CS6:
  671. priv->last_lcr |= MCT_U232_DATA_BITS_6; break;
  672. case CS7:
  673. priv->last_lcr |= MCT_U232_DATA_BITS_7; break;
  674. case CS8:
  675. priv->last_lcr |= MCT_U232_DATA_BITS_8; break;
  676. default:
  677. err("CSIZE was not CS5-CS8, using default of 8");
  678. priv->last_lcr |= MCT_U232_DATA_BITS_8;
  679. break;
  680. }
  681. /* set the number of stop bits */
  682. priv->last_lcr |= (cflag & CSTOPB) ?
  683. MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
  684. mct_u232_set_line_ctrl(serial, priv->last_lcr);
  685. }
  686. /*
  687.  * Set flow control: well, I do not really now how to handle DTR/RTS.
  688.  * Just do what we have seen with SniffUSB on Win98.
  689.  */
  690. if( (iflag & IXOFF) != (old_iflag & IXOFF)
  691.     || (iflag & IXON) != (old_iflag & IXON)
  692.     ||  (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {
  693. /* Drop DTR/RTS if no flow control otherwise assert */
  694. if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
  695. priv->control_state |= TIOCM_DTR | TIOCM_RTS;
  696. else
  697. priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
  698. mct_u232_set_modem_ctrl(serial, priv->control_state);
  699. }
  700. } /* mct_u232_set_termios */
  701. static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
  702. {
  703. struct usb_serial *serial = port->serial;
  704. struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
  705. unsigned char lcr = priv->last_lcr;
  706. dbg (__FUNCTION__ "state=%d", break_state);
  707. if (break_state)
  708. lcr |= MCT_U232_SET_BREAK;
  709. mct_u232_set_line_ctrl(serial, lcr);
  710. } /* mct_u232_break_ctl */
  711. static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
  712.    unsigned int cmd, unsigned long arg)
  713. {
  714. struct usb_serial *serial = port->serial;
  715. struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
  716. int mask;
  717. dbg (__FUNCTION__ "cmd=0x%x", cmd);
  718. /* Based on code from acm.c and others */
  719. switch (cmd) {
  720. case TIOCMGET:
  721. return put_user(priv->control_state, (unsigned long *) arg);
  722. break;
  723. case TIOCMSET: /* Turns on and off the lines as specified by the mask */
  724. case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
  725. case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
  726. if (get_user(mask, (unsigned long *) arg))
  727. return -EFAULT;
  728. if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) {
  729. /* RTS needs set */
  730. if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||
  731.     (cmd == TIOCMBIS) )
  732. priv->control_state |=  TIOCM_RTS;
  733. else
  734. priv->control_state &= ~TIOCM_RTS;
  735. }
  736. if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) {
  737. /* DTR needs set */
  738. if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) ||
  739.     (cmd == TIOCMBIS) )
  740. priv->control_state |=  TIOCM_DTR;
  741. else
  742. priv->control_state &= ~TIOCM_DTR;
  743. }
  744. mct_u232_set_modem_ctrl(serial, priv->control_state);
  745. break;
  746. case TIOCMIWAIT:
  747. /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
  748. /* TODO */
  749. return( 0 );
  750. case TIOCGICOUNT:
  751. /* return count of modemline transitions */
  752. /* TODO */
  753. return 0;
  754. default:
  755. dbg(__FUNCTION__ ": arg not supported - 0x%04x",cmd);
  756. return(-ENOIOCTLCMD);
  757. break;
  758. }
  759. return 0;
  760. } /* mct_u232_ioctl */
  761. static int __init mct_u232_init (void)
  762. {
  763. usb_serial_register (&mct_u232_device);
  764. usb_serial_register (&mct_u232_sitecom_device);
  765. usb_serial_register (&mct_u232_du_h3sp_device);
  766. info(DRIVER_VERSION ":" DRIVER_DESC);
  767. return 0;
  768. }
  769. static void __exit mct_u232_exit (void)
  770. {
  771. usb_serial_deregister (&mct_u232_device);
  772. usb_serial_deregister (&mct_u232_sitecom_device);
  773. usb_serial_deregister (&mct_u232_du_h3sp_device);
  774. }
  775. module_init (mct_u232_init);
  776. module_exit(mct_u232_exit);
  777. MODULE_AUTHOR( DRIVER_AUTHOR );
  778. MODULE_DESCRIPTION( DRIVER_DESC );
  779. MODULE_LICENSE("GPL");
  780. #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
  781. MODULE_PARM(write_blocking, "i");
  782. MODULE_PARM_DESC(write_blocking, 
  783.  "The write function will block to write out all data");
  784. #endif
  785. MODULE_PARM(debug, "i");
  786. MODULE_PARM_DESC(debug, "Debug enabled or not");