| Start/ | End/ | |||
| True | False | - | Line | Source |
| 1 | /* | |||
| 2 | * Belkin USB Serial Adapter Driver | |||
| 3 | * | |||
| 4 | * Copyright (C) 2000 William Greathouse (wgreathouse@smva.com) | |||
| 5 | * Copyright (C) 2000-2001 Greg Kroah-Hartman (greg@kroah.com) | |||
| 6 | * | |||
| 7 | * This program is largely derived from work by the linux-usb group | |||
| 8 | * and associated source files. Please see the usb/serial files for | |||
| 9 | * individual credits and copyrights. | |||
| 10 | * | |||
| 11 | * This program is free software; you can redistribute it and/or modify | |||
| 12 | * it under the terms of the GNU General Public License as published by | |||
| 13 | * the Free Software Foundation; either version 2 of the License, or | |||
| 14 | * (at your option) any later version. | |||
| 15 | * | |||
| 16 | * See Documentation/usb/usb-serial.txt for more information on using this driver | |||
| 17 | * | |||
| 18 | * TODO: | |||
| 19 | * -- Add true modem contol line query capability. Currently we track the | |||
| 20 | * states reported by the interrupt and the states we request. | |||
| 21 | * -- Add error reporting back to application for UART error conditions. | |||
| 22 | * Just point me at how to implement this and I'll do it. I've put the | |||
| 23 | * framework in, but haven't analyzed the "tty_flip" interface yet. | |||
| 24 | * -- Add support for flush commands | |||
| 25 | * -- Add everything that is missing :) | |||
| 26 | * | |||
| 27 | * 27-Nov-2001 gkh | |||
| 28 | * compressed all the differnent device entries into 1. | |||
| 29 | * | |||
| 30 | * 30-May-2001 gkh | |||
| 31 | * switched from using spinlock to a semaphore, which fixes lots of problems. | |||
| 32 | * | |||
| 33 | * 08-Apr-2001 gb | |||
| 34 | * - Identify version on module load. | |||
| 35 | * | |||
| 36 | * 12-Mar-2001 gkh | |||
| 37 | * - Added support for the GoHubs GO-COM232 device which is the same as the | |||
| 38 | * Peracom device. | |||
| 39 | * | |||
| 40 | * 06-Nov-2000 gkh | |||
| 41 | * - Added support for the old Belkin and Peracom devices. | |||
| 42 | * - Made the port able to be opened multiple times. | |||
| 43 | * - Added some defaults incase the line settings are things these devices | |||
| 44 | * can't support. | |||
| 45 | * | |||
| 46 | * 18-Oct-2000 William Greathouse | |||
| 47 | * Released into the wild (linux-usb-devel) | |||
| 48 | * | |||
| 49 | * 17-Oct-2000 William Greathouse | |||
| 50 | * Add code to recognize firmware version and set hardware flow control | |||
| 51 | * appropriately. Belkin states that firmware prior to 3.05 does not | |||
| 52 | * operate correctly in hardware handshake mode. I have verified this | |||
| 53 | * on firmware 2.05 -- for both RTS and DTR input flow control, the control | |||
| 54 | * line is not reset. The test performed by the Belkin Win* driver is | |||
| 55 | * to enable hardware flow control for firmware 2.06 or greater and | |||
| 56 | * for 1.00 or prior. I am only enabling for 2.06 or greater. | |||
| 57 | * | |||
| 58 | * 12-Oct-2000 William Greathouse | |||
| 59 | * First cut at supporting Belkin USB Serial Adapter F5U103 | |||
| 60 | * I did not have a copy of the original work to support this | |||
| 61 | * adapter, so pardon any stupid mistakes. All of the information | |||
| 62 | * I am using to write this driver was acquired by using a modified | |||
| 63 | * UsbSnoop on Windows2000 and from examining the other USB drivers. | |||
| 64 | */ | |||
| 65 | ||||
| 66 | #include <linux/config.h> | |||
| 67 | #include <linux/kernel.h> | |||
| 68 | #include <linux/errno.h> | |||
| 69 | #include <linux/init.h> | |||
| 70 | #include <linux/slab.h> | |||
| 71 | #include <linux/tty.h> | |||
| 72 | #include <linux/tty_driver.h> | |||
| 73 | #include <linux/tty_flip.h> | |||
| 74 | #include <linux/module.h> | |||
| 75 | #include <linux/spinlock.h> | |||
| 76 | #include <asm/uaccess.h> | |||
| 77 | #include <linux/usb.h> | |||
| 78 | #include "usb-serial.h" | |||
| 79 | #include "belkin_sa.h" | |||
| 80 | ||||
| 81 | static int debug; | |||
| 82 | ||||
| 83 | /* | |||
| 84 | * Version Information | |||
| 85 | */ | |||
| 86 | #define DRIVER_VERSION "v1.2" | |||
| 87 | #define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>" | |||
| 88 | #define DRIVER_DESC "USB Belkin Serial converter driver" | |||
| 89 | ||||
| 90 | /* function prototypes for a Belkin USB Serial Adapter F5U103 */ | |||
| 91 | static int belkin_sa_startup (struct usb_serial *serial); | |||
| 92 | static void belkin_sa_shutdown (struct usb_serial *serial); | |||
| 93 | static int belkin_sa_open (struct usb_serial_port *port, struct file *filp); | |||
| 94 | static void belkin_sa_close (struct usb_serial_port *port, struct file *filp); | |||
| 95 | static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs); | |||
| 96 | static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios * old); | |||
| 97 | static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); | |||
| 98 | static void belkin_sa_break_ctl (struct usb_serial_port *port, int break_state ); | |||
| 99 | static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file); | |||
| 100 | static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); | |||
| 101 | ||||
| 102 | ||||
| 103 | static struct usb_device_id id_table_combined [] = { | |||
| 104 | { USB_DEVICE(BELKIN_SA_VID, BELKIN_SA_PID) }, | |||
| 105 | { USB_DEVICE(BELKIN_OLD_VID, BELKIN_OLD_PID) }, | |||
| 106 | { USB_DEVICE(PERACOM_VID, PERACOM_PID) }, | |||
| 107 | { USB_DEVICE(GOHUBS_VID, GOHUBS_PID) }, | |||
| 108 | { USB_DEVICE(GOHUBS_VID, HANDYLINK_PID) }, | |||
| 109 | { USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) }, | |||
| 110 | { } /* Terminating entry */ | |||
| 111 | }; | |||
| 112 | ||||
| 113 | MODULE_DEVICE_TABLE (usb, id_table_combined); | |||
| 114 | ||||
| 115 | static struct usb_driver belkin_driver = { | |||
| 116 | .name = "belkin", | |||
| 117 | .probe = usb_serial_probe, | |||
| 118 | .disconnect = usb_serial_disconnect, | |||
| 119 | .id_table = id_table_combined, | |||
| 120 | .no_dynamic_id = 1, | |||
| 121 | }; | |||
| 122 | ||||
| 123 | /* All of the device info needed for the serial converters */ | |||
| 124 | static struct usb_serial_driver belkin_device = { | |||
| 125 | .driver = { | |||
| 126 | .owner = THIS_MODULE, | |||
| 127 | .name = "belkin", | |||
| 128 | }, | |||
| 129 | .description = "Belkin / Peracom / GoHubs USB Serial Adapter", | |||
| 130 | .id_table = id_table_combined, | |||
| 131 | .num_interrupt_in = 1, | |||
| 132 | .num_bulk_in = 1, | |||
| 133 | .num_bulk_out = 1, | |||
| 134 | .num_ports = 1, | |||
| 135 | .open = belkin_sa_open, | |||
| 136 | .close = belkin_sa_close, | |||
| 137 | .read_int_callback = belkin_sa_read_int_callback, /* How we get the status info */ | |||
| 138 | .ioctl = belkin_sa_ioctl, | |||
| 139 | .set_termios = belkin_sa_set_termios, | |||
| 140 | .break_ctl = belkin_sa_break_ctl, | |||
| 141 | .tiocmget = belkin_sa_tiocmget, | |||
| 142 | .tiocmset = belkin_sa_tiocmset, | |||
| 143 | .attach = belkin_sa_startup, | |||
| 144 | .shutdown = belkin_sa_shutdown, | |||
| 145 | }; | |||
| 146 | ||||
| 147 | ||||
| 148 | struct belkin_sa_private { | |||
| 149 | spinlock_t lock; | |||
| 150 | unsigned long control_state; | |||
| 151 | unsigned char last_lsr; | |||
| 152 | unsigned char last_msr; | |||
| 153 | int bad_flow_control; | |||
| 154 | }; | |||
| 155 | ||||
| 156 | ||||
| 157 | /* | |||
| 158 | * *************************************************************************** | |||
| 159 | * Belkin USB Serial Adapter F5U103 specific driver functions | |||
| 160 | * *************************************************************************** | |||
| 161 | */ | |||
| 162 | ||||
| 163 | #define WDR_TIMEOUT 5000 /* default urb timeout */ | |||
| 164 | ||||
| 165 | /* assumes that struct usb_serial *serial is available */ | |||
| 166 | #define BSA_USB_CMD(c,v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \ | |||
| 167 | (c), BELKIN_SA_SET_REQUEST_TYPE, \ | |||
| 168 | (v), 0, NULL, 0, WDR_TIMEOUT) | |||
| 169 | ||||
| 170 | /* do some startup allocations not currently performed by usb_serial_probe() */ | |||
| 0 | 0 | - | 171 | static int belkin_sa_startup (struct usb_serial *serial) |
| 172 | { | |||
| 173 | struct usb_device *dev = serial->dev; | |||
| 174 | struct belkin_sa_private *priv; | |||
| 175 | ||||
| 176 | /* allocate the private data structure */ | |||
| 177 | priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL); | |||
| 0 | 0 | - | 178 | if (!priv) |
| 0 | - | 179 | return (-1); /* error */ | |
| 180 | /* set initial values for control structures */ | |||
| 181 | spin_lock_init(&priv->lock); | |||
| 0 | 0 | - | 181 | do-while (0) |
| 182 | priv->control_state = 0; | |||
| 183 | priv->last_lsr = 0; | |||
| 184 | priv->last_msr = 0; | |||
| 185 | /* see comments at top of file */ | |||
| 186 | priv->bad_flow_control = (le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0; | |||
| 0 | 0 | - | 186 | ternary-?: ( ( ( __u16 ) ( __le16 ) ( dev -> d.. |
| 187 | info("bcdDevice: %04x, bfc: %d", le16_to_cpu(dev->descriptor.bcdDevice), priv->bad_flow_control); | |||
| 188 | ||||
| 189 | init_waitqueue_head(&serial->port[0]->write_wait); | |||
| 190 | usb_set_serial_port_data(serial->port[0], priv); | |||
| 191 | ||||
| 0 | - | 192 | return (0); | |
| 193 | } | |||
| 194 | ||||
| 195 | ||||
| 0 | 0 | - | 196 | static void belkin_sa_shutdown (struct usb_serial *serial) |
| 197 | { | |||
| 198 | struct belkin_sa_private *priv; | |||
| 199 | int i; | |||
| 200 | ||||
| 201 | dbg ("%s", __FUNCTION__); | |||
| 0 | 0 | - | 201 | if (debug) |
| 0 | 0 | - | 201 | do-while (0) |
| 202 | ||||
| 203 | /* stop reads and writes on all ports */ | |||
| 0 | 0 | - | 204 | for (i=0; i < serial->num_ports; ++i) { |
| 205 | /* My special items, the standard routines free my urbs */ | |||
| 206 | priv = usb_get_serial_port_data(serial->port[i]); | |||
| 207 | kfree(priv); | |||
| 208 | } | |||
| 209 | } | |||
| 210 | ||||
| 211 | ||||
| 0 | 0 | - | 212 | static int belkin_sa_open (struct usb_serial_port *port, struct file *filp) |
| 213 | { | |||
| 214 | int retval = 0; | |||
| 215 | ||||
| 216 | dbg("%s port %d", __FUNCTION__, port->number); | |||
| 0 | 0 | - | 216 | if (debug) |
| 0 | 0 | - | 216 | do-while (0) |
| 217 | ||||
| 218 | /*Start reading from the device*/ | |||
| 219 | /* TODO: Look at possibility of submitting multiple URBs to device to | |||
| 220 | * enhance buffering. Win trace shows 16 initial read URBs. | |||
| 221 | */ | |||
| 222 | port->read_urb->dev = port->serial->dev; | |||
| 223 | retval = usb_submit_urb(port->read_urb, GFP_KERNEL); | |||
| 0 | 0 | - | 224 | if (retval) { |
| 225 | err("usb_submit_urb(read bulk) failed"); | |||
| 0 | - | 226 | goto exit; | |
| 227 | } | |||
| 228 | ||||
| 229 | port->interrupt_in_urb->dev = port->serial->dev; | |||
| 230 | retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | |||
| 0 | 0 | - | 231 | if (retval) { |
| 232 | usb_kill_urb(port->read_urb); | |||
| 233 | err(" usb_submit_urb(read int) failed"); | |||
| 234 | } | |||
| 235 | ||||
| 236 | exit: | |||
| 0 | - | 237 | return retval; | |
| 238 | } /* belkin_sa_open */ | |||
| 239 | ||||
| 240 | ||||
| 0 | 0 | - | 241 | static void belkin_sa_close (struct usb_serial_port *port, struct file *filp) |
| 242 | { | |||
| 243 | dbg("%s port %d", __FUNCTION__, port->number); | |||
| 0 | 0 | - | 243 | if (debug) |
| 0 | 0 | - | 243 | do-while (0) |
| 244 | ||||
| 245 | /* shutdown our bulk reads and writes */ | |||
| 246 | usb_kill_urb(port->write_urb); | |||
| 247 | usb_kill_urb(port->read_urb); | |||
| 248 | usb_kill_urb(port->interrupt_in_urb); | |||
| 249 | } /* belkin_sa_close */ | |||
| 250 | ||||
| 251 | ||||
| 0 | 0 | - | 252 | static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs) |
| 253 | { | |||
| 254 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | |||
| 255 | struct belkin_sa_private *priv; | |||
| 256 | unsigned char *data = urb->transfer_buffer; | |||
| 257 | int retval; | |||
| 258 | unsigned long flags; | |||
| 259 | ||||
| 260 | switch (urb->status) { | |||
| 0 | - | 261 | case 0: | |
| 262 | /* success */ | |||
| 0 | - | 263 | break; | |
| 0 | - | 264 | case -ECONNRESET: | |
| 0 | - | 265 | case -ENOENT: | |
| 0 | - | 266 | case -ESHUTDOWN: | |
| 267 | /* this urb is terminated, clean up */ | |||
| 268 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | |||
| 0 | 0 | - | 268 | if (debug) |
| 0 | 0 | - | 268 | do-while (0) |
| 0 | - | 269 | return; | |
| 0 | - | 270 | default: | |
| 271 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | |||
| 0 | 0 | - | 271 | if (debug) |
| 0 | 0 | - | 271 | do-while (0) |
| 0 | - | 272 | goto exit; | |
| 273 | } | |||
| 274 | ||||
| 275 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | |||
| 276 | ||||
| 277 | /* Handle known interrupt data */ | |||
| 278 | /* ignore data[0] and data[1] */ | |||
| 279 | ||||
| 280 | priv = usb_get_serial_port_data(port); | |||
| 281 | spin_lock_irqsave(&priv->lock, flags); | |||
| 281 | do | |||
| 281 | do | |||
| 0 | 0 | - | 281 | do-while (0) |
| 0 | 0 | - | 281 | do-while (0) |
| 281 | do | |||
| 281 | do | |||
| 0 | 0 | - | 281 | do-while (0) |
| 0 | 0 | - | 281 | do-while (0) |
| 0 | 0 | - | 281 | do-while (0) |
| 282 | priv->last_msr = data[BELKIN_SA_MSR_INDEX]; | |||
| 283 | ||||
| 284 | /* Record Control Line states */ | |||
| 0 | 0 | - | 285 | if (priv->last_msr & BELKIN_SA_MSR_DSR) |
| 286 | priv->control_state |= TIOCM_DSR; | |||
| 287 | else | |||
| 288 | priv->control_state &= ~TIOCM_DSR; | |||
| 289 | ||||
| 0 | 0 | - | 290 | if (priv->last_msr & BELKIN_SA_MSR_CTS) |
| 291 | priv->control_state |= TIOCM_CTS; | |||
| 292 | else | |||
| 293 | priv->control_state &= ~TIOCM_CTS; | |||
| 294 | ||||
| 0 | 0 | - | 295 | if (priv->last_msr & BELKIN_SA_MSR_RI) |
| 296 | priv->control_state |= TIOCM_RI; | |||
| 297 | else | |||
| 298 | priv->control_state &= ~TIOCM_RI; | |||
| 299 | ||||
| 0 | 0 | - | 300 | if (priv->last_msr & BELKIN_SA_MSR_CD) |
| 301 | priv->control_state |= TIOCM_CD; | |||
| 302 | else | |||
| 303 | priv->control_state &= ~TIOCM_CD; | |||
| 304 | ||||
| 305 | /* Now to report any errors */ | |||
| 306 | priv->last_lsr = data[BELKIN_SA_LSR_INDEX]; | |||
| 307 | #if 0 | |||
| 308 | /* | |||
| 309 | * fill in the flip buffer here, but I do not know the relation | |||
| 310 | * to the current/next receive buffer or characters. I need | |||
| 311 | * to look in to this before committing any code. | |||
| 312 | */ | |||
| 313 | if (priv->last_lsr & BELKIN_SA_LSR_ERR) { | |||
| 314 | tty = port->tty; | |||
| 315 | /* Overrun Error */ | |||
| 316 | if (priv->last_lsr & BELKIN_SA_LSR_OE) { | |||
| 317 | } | |||
| 318 | /* Parity Error */ | |||
| 319 | if (priv->last_lsr & BELKIN_SA_LSR_PE) { | |||
| 320 | } | |||
| 321 | /* Framing Error */ | |||
| 322 | if (priv->last_lsr & BELKIN_SA_LSR_FE) { | |||
| 323 | } | |||
| 324 | /* Break Indicator */ | |||
| 325 | if (priv->last_lsr & BELKIN_SA_LSR_BI) { | |||
| 326 | } | |||
| 327 | } | |||
| 328 | #endif | |||
| 329 | spin_unlock_irqrestore(&priv->lock, flags); | |||
| 329 | do | |||
| 329 | do | |||
| 0 | 0 | - | 329 | do-while (0) |
| 0 | 0 | - | 329 | do-while (0) |
| 0 | 0 | - | 329 | do-while (0) |
| 330 | exit: | |||
| 331 | retval = usb_submit_urb (urb, GFP_ATOMIC); | |||
| 0 | 0 | - | 332 | if (retval) |
| 333 | err ("%s - usb_submit_urb failed with result %d", | |||
| 334 | __FUNCTION__, retval); | |||
| 335 | } | |||
| 336 | ||||
| 0 | 0 | - | 337 | static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios *old_termios) |
| 338 | { | |||
| 339 | struct usb_serial *serial = port->serial; | |||
| 340 | struct belkin_sa_private *priv = usb_get_serial_port_data(port); | |||
| 341 | unsigned int iflag; | |||
| 342 | unsigned int cflag; | |||
| 343 | unsigned int old_iflag = 0; | |||
| 344 | unsigned int old_cflag = 0; | |||
| 345 | __u16 urb_value = 0; /* Will hold the new flags */ | |||
| 346 | unsigned long flags; | |||
| 347 | unsigned long control_state; | |||
| 348 | int bad_flow_control; | |||
| 349 | ||||
| 0 | 0 | - | 350 | if ((!port->tty) || (!port->tty->termios)) { |
| 0 | - | 350 | (T) || (_) | |
| 0 | - | 350 | (F) || (T) | |
| 0 | - | 350 | (F) || (F) | |
| 351 | dbg ("%s - no tty or termios structure", __FUNCTION__); | |||
| 0 | 0 | - | 351 | if (debug) |
| 0 | 0 | - | 351 | do-while (0) |
| 0 | - | 352 | return; | |
| 353 | } | |||
| 354 | ||||
| 355 | iflag = port->tty->termios->c_iflag; | |||
| 356 | cflag = port->tty->termios->c_cflag; | |||
| 357 | ||||
| 358 | /* get a local copy of the current port settings */ | |||
| 359 | spin_lock_irqsave(&priv->lock, flags); | |||
| 359 | do | |||
| 359 | do | |||
| 0 | 0 | - | 359 | do-while (0) |
| 0 | 0 | - | 359 | do-while (0) |
| 359 | do | |||
| 359 | do | |||
| 0 | 0 | - | 359 | do-while (0) |
| 0 | 0 | - | 359 | do-while (0) |
| 0 | 0 | - | 359 | do-while (0) |
| 360 | control_state = priv->control_state; | |||
| 361 | bad_flow_control = priv->bad_flow_control; | |||
| 362 | spin_unlock_irqrestore(&priv->lock, flags); | |||
| 362 | do | |||
| 362 | do | |||
| 0 | 0 | - | 362 | do-while (0) |
| 0 | 0 | - | 362 | do-while (0) |
| 0 | 0 | - | 362 | do-while (0) |
| 363 | ||||
| 364 | /* check that they really want us to change something */ | |||
| 0 | 0 | - | 365 | if (old_termios) { |
| 366 | if ((cflag == old_termios->c_cflag) && | |||
| 0 | 0 | - | 367 | (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { |
| 0 | - | 367 | (T) && (T) | |
| 0 | - | 367 | (T) && (F) | |
| 0 | - | 367 | (F) && (_) | |
| 368 | dbg("%s - nothing to change...", __FUNCTION__); | |||
| 0 | 0 | - | 368 | if (debug) |
| 0 | 0 | - | 368 | do-while (0) |
| 0 | - | 369 | return; | |
| 370 | } | |||
| 371 | old_iflag = old_termios->c_iflag; | |||
| 372 | old_cflag = old_termios->c_cflag; | |||
| 373 | } | |||
| 374 | ||||
| 375 | /* Set the baud rate */ | |||
| 0 | 0 | - | 376 | if( (cflag&CBAUD) != (old_cflag&CBAUD) ) { |
| 377 | /* reassert DTR and (maybe) RTS on transition from B0 */ | |||
| 0 | 0 | - | 378 | if( (old_cflag&CBAUD) == B0 ) { |
| 379 | control_state |= (TIOCM_DTR|TIOCM_RTS); | |||
| 0 | 0 | - | 380 | if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0) |
| 381 | err("Set DTR error"); | |||
| 382 | /* don't set RTS if using hardware flow control */ | |||
| 0 | 0 | - | 383 | if (!(old_cflag&CRTSCTS) ) |
| 0 | 0 | - | 384 | if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 1) < 0) |
| 385 | err("Set RTS error"); | |||
| 386 | } | |||
| 387 | ||||
| 388 | switch(cflag & CBAUD) { | |||
| 0 | - | 389 | case B0: /* handled below */ break; | |
| 0 | - | 389 | break | |
| 0 | - | 390 | case B300: urb_value = BELKIN_SA_BAUD(300); break; | |
| 0 | - | 390 | break | |
| 0 | - | 391 | case B600: urb_value = BELKIN_SA_BAUD(600); break; | |
| 0 | - | 391 | break | |
| 0 | - | 392 | case B1200: urb_value = BELKIN_SA_BAUD(1200); break; | |
| 0 | - | 392 | break | |
| 0 | - | 393 | case B2400: urb_value = BELKIN_SA_BAUD(2400); break; | |
| 0 | - | 393 | break | |
| 0 | - | 394 | case B4800: urb_value = BELKIN_SA_BAUD(4800); break; | |
| 0 | - | 394 | break | |
| 0 | - | 395 | case B9600: urb_value = BELKIN_SA_BAUD(9600); break; | |
| 0 | - | 395 | break | |
| 0 | - | 396 | case B19200: urb_value = BELKIN_SA_BAUD(19200); break; | |
| 0 | - | 396 | break | |
| 0 | - | 397 | case B38400: urb_value = BELKIN_SA_BAUD(38400); break; | |
| 0 | - | 397 | break | |
| 0 | - | 398 | case B57600: urb_value = BELKIN_SA_BAUD(57600); break; | |
| 0 | - | 398 | break | |
| 0 | - | 399 | case B115200: urb_value = BELKIN_SA_BAUD(115200); break; | |
| 0 | - | 399 | break | |
| 0 | - | 400 | case B230400: urb_value = BELKIN_SA_BAUD(230400); break; | |
| 0 | - | 400 | break | |
| 0 | - | 401 | default: err("BELKIN USB Serial Adapter: unsupported baudrate request, using default of 9600"); | |
| 0 | - | 402 | urb_value = BELKIN_SA_BAUD(9600); break; | |
| 403 | } | |||
| 0 | 0 | - | 404 | if ((cflag & CBAUD) != B0 ) { |
| 0 | 0 | - | 405 | if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0) |
| 406 | err("Set baudrate error"); | |||
| 407 | } else { | |||
| 408 | /* Disable flow control */ | |||
| 0 | 0 | - | 409 | if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0) |
| 410 | err("Disable flowcontrol error"); | |||
| 411 | ||||
| 412 | /* Drop RTS and DTR */ | |||
| 413 | control_state &= ~(TIOCM_DTR | TIOCM_RTS); | |||
| 0 | 0 | - | 414 | if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0) |
| 415 | err("DTR LOW error"); | |||
| 0 | 0 | - | 416 | if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0) |
| 417 | err("RTS LOW error"); | |||
| 418 | } | |||
| 419 | } | |||
| 420 | ||||
| 421 | /* set the parity */ | |||
| 0 | 0 | - | 422 | if( (cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD)) ) { |
| 0 | 0 | - | 423 | if (cflag & PARENB) |
| 424 | urb_value = (cflag & PARODD) ? BELKIN_SA_PARITY_ODD : BELKIN_SA_PARITY_EVEN; | |||
| 0 | 0 | - | 424 | ternary-?: ( cflag & 0001000 ) |
| 425 | else | |||
| 426 | urb_value = BELKIN_SA_PARITY_NONE; | |||
| 0 | 0 | - | 427 | if (BSA_USB_CMD(BELKIN_SA_SET_PARITY_REQUEST, urb_value) < 0) |
| 428 | err("Set parity error"); | |||
| 429 | } | |||
| 430 | ||||
| 431 | /* set the number of data bits */ | |||
| 0 | 0 | - | 432 | if( (cflag&CSIZE) != (old_cflag&CSIZE) ) { |
| 433 | switch (cflag & CSIZE) { | |||
| 0 | - | 434 | case CS5: urb_value = BELKIN_SA_DATA_BITS(5); break; | |
| 0 | - | 434 | break | |
| 0 | - | 435 | case CS6: urb_value = BELKIN_SA_DATA_BITS(6); break; | |
| 0 | - | 435 | break | |
| 0 | - | 436 | case CS7: urb_value = BELKIN_SA_DATA_BITS(7); break; | |
| 0 | - | 436 | break | |
| 0 | - | 437 | case CS8: urb_value = BELKIN_SA_DATA_BITS(8); break; | |
| 0 | - | 437 | break | |
| 0 | - | 438 | default: err("CSIZE was not CS5-CS8, using default of 8"); | |