diff options
Diffstat (limited to 'drivers/usb/serial/mct_u232.c')
-rw-r--r-- | drivers/usb/serial/mct_u232.c | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 0dc99f75bb09..fc1cea4aba13 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c | |||
@@ -182,10 +182,11 @@ struct mct_u232_private { | |||
182 | /* | 182 | /* |
183 | * Later day 2.6.0-test kernels have new baud rates like B230400 which | 183 | * Later day 2.6.0-test kernels have new baud rates like B230400 which |
184 | * we do not know how to support. We ignore them for the moment. | 184 | * we do not know how to support. We ignore them for the moment. |
185 | * XXX Rate-limit the error message, it's user triggerable. | ||
186 | */ | 185 | */ |
187 | static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value) | 186 | static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value, speed_t *result) |
188 | { | 187 | { |
188 | *result = value; | ||
189 | |||
189 | if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID | 190 | if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID |
190 | || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) { | 191 | || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) { |
191 | switch (value) { | 192 | switch (value) { |
@@ -200,11 +201,13 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value | |||
200 | case 57600: return 0x0b; | 201 | case 57600: return 0x0b; |
201 | case 115200: return 0x0c; | 202 | case 115200: return 0x0c; |
202 | default: | 203 | default: |
203 | err("MCT USB-RS232: unsupported baudrate request 0x%x," | 204 | *result = 9600; |
204 | " using default of B9600", value); | ||
205 | return 0x08; | 205 | return 0x08; |
206 | } | 206 | } |
207 | } else { | 207 | } else { |
208 | /* FIXME: Can we use any divider - should we do | ||
209 | divider = 115200/value; | ||
210 | real baud = 115200/divider */ | ||
208 | switch (value) { | 211 | switch (value) { |
209 | case 300: break; | 212 | case 300: break; |
210 | case 600: break; | 213 | case 600: break; |
@@ -217,9 +220,8 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value | |||
217 | case 57600: break; | 220 | case 57600: break; |
218 | case 115200: break; | 221 | case 115200: break; |
219 | default: | 222 | default: |
220 | err("MCT USB-RS232: unsupported baudrate request 0x%x," | ||
221 | " using default of B9600", value); | ||
222 | value = 9600; | 223 | value = 9600; |
224 | *result = 9600; | ||
223 | } | 225 | } |
224 | return 115200/value; | 226 | return 115200/value; |
225 | } | 227 | } |
@@ -232,16 +234,19 @@ static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_p | |||
232 | int rc; | 234 | int rc; |
233 | unsigned char zero_byte = 0; | 235 | unsigned char zero_byte = 0; |
234 | unsigned char cts_enable_byte = 0; | 236 | unsigned char cts_enable_byte = 0; |
237 | speed_t speed; | ||
235 | 238 | ||
236 | divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value)); | 239 | divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value, &speed)); |
237 | 240 | ||
238 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | 241 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
239 | MCT_U232_SET_BAUD_RATE_REQUEST, | 242 | MCT_U232_SET_BAUD_RATE_REQUEST, |
240 | MCT_U232_SET_REQUEST_TYPE, | 243 | MCT_U232_SET_REQUEST_TYPE, |
241 | 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE, | 244 | 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE, |
242 | WDR_TIMEOUT); | 245 | WDR_TIMEOUT); |
243 | if (rc < 0) | 246 | if (rc < 0) /*FIXME: What value speed results */ |
244 | err("Set BAUD RATE %d failed (error = %d)", value, rc); | 247 | err("Set BAUD RATE %d failed (error = %d)", value, rc); |
248 | else | ||
249 | tty_encode_baud_rate(port->tty, speed, speed); | ||
245 | dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor); | 250 | dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor); |
246 | 251 | ||
247 | /* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which | 252 | /* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which |
@@ -482,21 +487,22 @@ error: | |||
482 | static void mct_u232_close (struct usb_serial_port *port, struct file *filp) | 487 | static void mct_u232_close (struct usb_serial_port *port, struct file *filp) |
483 | { | 488 | { |
484 | unsigned int c_cflag; | 489 | unsigned int c_cflag; |
485 | unsigned long flags; | ||
486 | unsigned int control_state; | 490 | unsigned int control_state; |
487 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | 491 | struct mct_u232_private *priv = usb_get_serial_port_data(port); |
488 | dbg("%s port %d", __FUNCTION__, port->number); | 492 | dbg("%s port %d", __FUNCTION__, port->number); |
489 | 493 | ||
490 | if (port->tty) { | 494 | if (port->tty) { |
491 | c_cflag = port->tty->termios->c_cflag; | 495 | c_cflag = port->tty->termios->c_cflag; |
492 | if (c_cflag & HUPCL) { | 496 | mutex_lock(&port->serial->disc_mutex); |
493 | /* drop DTR and RTS */ | 497 | if (c_cflag & HUPCL && !port->serial->disconnected) { |
494 | spin_lock_irqsave(&priv->lock, flags); | 498 | /* drop DTR and RTS */ |
495 | priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); | 499 | spin_lock_irq(&priv->lock); |
496 | control_state = priv->control_state; | 500 | priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); |
497 | spin_unlock_irqrestore(&priv->lock, flags); | 501 | control_state = priv->control_state; |
498 | mct_u232_set_modem_ctrl(port->serial, control_state); | 502 | spin_unlock_irq(&priv->lock); |
503 | mct_u232_set_modem_ctrl(port->serial, control_state); | ||
499 | } | 504 | } |
505 | mutex_unlock(&port->serial->disc_mutex); | ||
500 | } | 506 | } |
501 | 507 | ||
502 | 508 | ||
@@ -608,7 +614,8 @@ static void mct_u232_set_termios (struct usb_serial_port *port, | |||
608 | { | 614 | { |
609 | struct usb_serial *serial = port->serial; | 615 | struct usb_serial *serial = port->serial; |
610 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | 616 | struct mct_u232_private *priv = usb_get_serial_port_data(port); |
611 | unsigned int cflag = port->tty->termios->c_cflag; | 617 | struct ktermios *termios = port->tty->termios; |
618 | unsigned int cflag = termios->c_cflag; | ||
612 | unsigned int old_cflag = old_termios->c_cflag; | 619 | unsigned int old_cflag = old_termios->c_cflag; |
613 | unsigned long flags; | 620 | unsigned long flags; |
614 | unsigned int control_state; | 621 | unsigned int control_state; |
@@ -670,6 +677,8 @@ static void mct_u232_set_termios (struct usb_serial_port *port, | |||
670 | break; | 677 | break; |
671 | } | 678 | } |
672 | 679 | ||
680 | termios->c_cflag &= ~CMSPAR; | ||
681 | |||
673 | /* set the number of stop bits */ | 682 | /* set the number of stop bits */ |
674 | last_lcr |= (cflag & CSTOPB) ? | 683 | last_lcr |= (cflag & CSTOPB) ? |
675 | MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1; | 684 | MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1; |