diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2008-03-10 17:59:28 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-04-25 00:16:41 -0400 |
commit | 8873aaa6e574d85c020a1c472d6d159cd1ec8aef (patch) | |
tree | 790e1b119dfa28ba2ce9ac5a38fe72fb88aa20a4 /drivers/usb/serial/cypress_m8.c | |
parent | 25b70a8665e9854504b9196c3098dadd37c721aa (diff) |
USB: cypress_m8: Speed handling
The recent changes to this driver cleaned it up a lot, follow that up
by sorting the speed side of things out as well
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/cypress_m8.c')
-rw-r--r-- | drivers/usb/serial/cypress_m8.c | 169 |
1 files changed, 29 insertions, 140 deletions
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 4bf45c711b9d..36f8ef079479 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
@@ -147,7 +147,6 @@ struct cypress_private { | |||
147 | enum packet_format pkt_fmt; /* format to use for packet send / receive */ | 147 | enum packet_format pkt_fmt; /* format to use for packet send / receive */ |
148 | int get_cfg_unsafe; /* If true, the CYPRESS_GET_CONFIG is unsafe */ | 148 | int get_cfg_unsafe; /* If true, the CYPRESS_GET_CONFIG is unsafe */ |
149 | int baud_rate; /* stores current baud rate in integer form */ | 149 | int baud_rate; /* stores current baud rate in integer form */ |
150 | int cbr_mask; /* stores current baud rate in masked form */ | ||
151 | int isthrottled; /* if throttled, discard reads */ | 150 | int isthrottled; /* if throttled, discard reads */ |
152 | wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */ | 151 | wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */ |
153 | char prev_status, diff_status; /* used for TIOCMIWAIT */ | 152 | char prev_status, diff_status; /* used for TIOCMIWAIT */ |
@@ -183,9 +182,6 @@ static void cypress_unthrottle (struct usb_serial_port *port); | |||
183 | static void cypress_set_dead (struct usb_serial_port *port); | 182 | static void cypress_set_dead (struct usb_serial_port *port); |
184 | static void cypress_read_int_callback (struct urb *urb); | 183 | static void cypress_read_int_callback (struct urb *urb); |
185 | static void cypress_write_int_callback (struct urb *urb); | 184 | static void cypress_write_int_callback (struct urb *urb); |
186 | /* baud helper functions */ | ||
187 | static int mask_to_rate (unsigned mask); | ||
188 | static unsigned rate_to_mask (int rate); | ||
189 | /* write buffer functions */ | 185 | /* write buffer functions */ |
190 | static struct cypress_buf *cypress_buf_alloc(unsigned int size); | 186 | static struct cypress_buf *cypress_buf_alloc(unsigned int size); |
191 | static void cypress_buf_free(struct cypress_buf *cb); | 187 | static void cypress_buf_free(struct cypress_buf *cb); |
@@ -291,9 +287,8 @@ static struct usb_serial_driver cypress_ca42v2_device = { | |||
291 | *****************************************************************************/ | 287 | *****************************************************************************/ |
292 | 288 | ||
293 | 289 | ||
294 | static int analyze_baud_rate(struct usb_serial_port *port, unsigned baud_mask) | 290 | static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate) |
295 | { | 291 | { |
296 | int new_rate; | ||
297 | struct cypress_private *priv; | 292 | struct cypress_private *priv; |
298 | priv = usb_get_serial_port_data(port); | 293 | priv = usb_get_serial_port_data(port); |
299 | 294 | ||
@@ -306,12 +301,6 @@ static int analyze_baud_rate(struct usb_serial_port *port, unsigned baud_mask) | |||
306 | * The Cypress HID->COM device will work successfully up to | 301 | * The Cypress HID->COM device will work successfully up to |
307 | * 115200bps (but the actual throughput is around 3kBps). | 302 | * 115200bps (but the actual throughput is around 3kBps). |
308 | */ | 303 | */ |
309 | new_rate = mask_to_rate(baud_mask); | ||
310 | if (new_rate < 0) { | ||
311 | dbg("%s - failed setting baud rate, untranslatable speed", | ||
312 | __func__); | ||
313 | return -1; | ||
314 | } | ||
315 | if (port->serial->dev->speed == USB_SPEED_LOW) { | 304 | if (port->serial->dev->speed == USB_SPEED_LOW) { |
316 | /* | 305 | /* |
317 | * Mike Isely <isely@pobox.com> 2-Feb-2008: The | 306 | * Mike Isely <isely@pobox.com> 2-Feb-2008: The |
@@ -345,7 +334,7 @@ static int analyze_baud_rate(struct usb_serial_port *port, unsigned baud_mask) | |||
345 | 334 | ||
346 | 335 | ||
347 | /* This function can either set or retrieve the current serial line settings */ | 336 | /* This function can either set or retrieve the current serial line settings */ |
348 | static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_mask, int data_bits, int stop_bits, | 337 | static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_rate, int data_bits, int stop_bits, |
349 | int parity_enable, int parity_type, int reset, int cypress_request_type) | 338 | int parity_enable, int parity_type, int reset, int cypress_request_type) |
350 | { | 339 | { |
351 | int new_baudrate = 0, retval = 0, tries = 0; | 340 | int new_baudrate = 0, retval = 0, tries = 0; |
@@ -363,9 +352,13 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m | |||
363 | switch(cypress_request_type) { | 352 | switch(cypress_request_type) { |
364 | case CYPRESS_SET_CONFIG: | 353 | case CYPRESS_SET_CONFIG: |
365 | new_baudrate = priv->baud_rate; | 354 | new_baudrate = priv->baud_rate; |
366 | if (baud_mask != priv->cbr_mask) { | 355 | /* 0 means 'Hang up' so doesn't change the true bit rate */ |
356 | if (baud_rate == 0) | ||
357 | new_baudrate = priv->baud_rate; | ||
358 | /* Change of speed ? */ | ||
359 | else if (baud_rate != priv->baud_rate) { | ||
367 | dbg("%s - baud rate is changing", __FUNCTION__); | 360 | dbg("%s - baud rate is changing", __FUNCTION__); |
368 | retval = analyze_baud_rate(port, baud_mask); | 361 | retval = analyze_baud_rate(port, baud_rate); |
369 | if (retval >= 0) { | 362 | if (retval >= 0) { |
370 | new_baudrate = retval; | 363 | new_baudrate = retval; |
371 | dbg("%s - New baud rate set to %d", | 364 | dbg("%s - New baud rate set to %d", |
@@ -410,9 +403,12 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m | |||
410 | } else { | 403 | } else { |
411 | spin_lock_irqsave(&priv->lock, flags); | 404 | spin_lock_irqsave(&priv->lock, flags); |
412 | priv->baud_rate = new_baudrate; | 405 | priv->baud_rate = new_baudrate; |
413 | priv->cbr_mask = baud_mask; | ||
414 | priv->current_config = feature_buffer[4]; | 406 | priv->current_config = feature_buffer[4]; |
415 | spin_unlock_irqrestore(&priv->lock, flags); | 407 | spin_unlock_irqrestore(&priv->lock, flags); |
408 | /* If we asked for a speed change encode it */ | ||
409 | if (baud_rate) | ||
410 | tty_encode_baud_rate(port->tty, | ||
411 | new_baudrate, new_baudrate); | ||
416 | } | 412 | } |
417 | break; | 413 | break; |
418 | case CYPRESS_GET_CONFIG: | 414 | case CYPRESS_GET_CONFIG: |
@@ -450,9 +446,6 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m | |||
450 | /* store the config in one byte, and later use bit masks to check values */ | 446 | /* store the config in one byte, and later use bit masks to check values */ |
451 | priv->current_config = feature_buffer[4]; | 447 | priv->current_config = feature_buffer[4]; |
452 | priv->baud_rate = *((u_int32_t *)feature_buffer); | 448 | priv->baud_rate = *((u_int32_t *)feature_buffer); |
453 | |||
454 | if ( (priv->cbr_mask = rate_to_mask(priv->baud_rate)) == 0x40) | ||
455 | dbg("%s - failed setting the baud mask (not defined)", __FUNCTION__); | ||
456 | spin_unlock_irqrestore(&priv->lock, flags); | 449 | spin_unlock_irqrestore(&priv->lock, flags); |
457 | } | 450 | } |
458 | } | 451 | } |
@@ -482,51 +475,6 @@ static void cypress_set_dead(struct usb_serial_port *port) | |||
482 | } | 475 | } |
483 | 476 | ||
484 | 477 | ||
485 | /* given a baud mask, it will return integer baud on success */ | ||
486 | static int mask_to_rate (unsigned mask) | ||
487 | { | ||
488 | int rate; | ||
489 | |||
490 | switch (mask) { | ||
491 | case B0: rate = 0; break; | ||
492 | case B300: rate = 300; break; | ||
493 | case B600: rate = 600; break; | ||
494 | case B1200: rate = 1200; break; | ||
495 | case B2400: rate = 2400; break; | ||
496 | case B4800: rate = 4800; break; | ||
497 | case B9600: rate = 9600; break; | ||
498 | case B19200: rate = 19200; break; | ||
499 | case B38400: rate = 38400; break; | ||
500 | case B57600: rate = 57600; break; | ||
501 | case B115200: rate = 115200; break; | ||
502 | default: rate = -1; | ||
503 | } | ||
504 | |||
505 | return rate; | ||
506 | } | ||
507 | |||
508 | |||
509 | static unsigned rate_to_mask (int rate) | ||
510 | { | ||
511 | unsigned mask; | ||
512 | |||
513 | switch (rate) { | ||
514 | case 0: mask = B0; break; | ||
515 | case 300: mask = B300; break; | ||
516 | case 600: mask = B600; break; | ||
517 | case 1200: mask = B1200; break; | ||
518 | case 2400: mask = B2400; break; | ||
519 | case 4800: mask = B4800; break; | ||
520 | case 9600: mask = B9600; break; | ||
521 | case 19200: mask = B19200; break; | ||
522 | case 38400: mask = B38400; break; | ||
523 | case 57600: mask = B57600; break; | ||
524 | case 115200: mask = B115200; break; | ||
525 | default: mask = 0x40; | ||
526 | } | ||
527 | |||
528 | return mask; | ||
529 | } | ||
530 | /***************************************************************************** | 478 | /***************************************************************************** |
531 | * Cypress serial driver functions | 479 | * Cypress serial driver functions |
532 | *****************************************************************************/ | 480 | *****************************************************************************/ |
@@ -558,7 +506,6 @@ static int generic_startup (struct usb_serial *serial) | |||
558 | priv->line_control = 0; | 506 | priv->line_control = 0; |
559 | priv->termios_initialized = 0; | 507 | priv->termios_initialized = 0; |
560 | priv->rx_flags = 0; | 508 | priv->rx_flags = 0; |
561 | priv->cbr_mask = B300; | ||
562 | /* Default packet format setting is determined by packet size. | 509 | /* Default packet format setting is determined by packet size. |
563 | Anything with a size larger then 9 must have a separate | 510 | Anything with a size larger then 9 must have a separate |
564 | count field since the 3 bit count field is otherwise too | 511 | count field since the 3 bit count field is otherwise too |
@@ -1004,9 +951,9 @@ static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, | |||
1004 | priv->line_control &= ~CONTROL_RTS; | 951 | priv->line_control &= ~CONTROL_RTS; |
1005 | if (clear & TIOCM_DTR) | 952 | if (clear & TIOCM_DTR) |
1006 | priv->line_control &= ~CONTROL_DTR; | 953 | priv->line_control &= ~CONTROL_DTR; |
954 | priv->cmd_ctrl = 1; | ||
1007 | spin_unlock_irqrestore(&priv->lock, flags); | 955 | spin_unlock_irqrestore(&priv->lock, flags); |
1008 | 956 | ||
1009 | priv->cmd_ctrl = 1; | ||
1010 | return cypress_write(port, NULL, 0); | 957 | return cypress_write(port, NULL, 0); |
1011 | } | 958 | } |
1012 | 959 | ||
@@ -1018,20 +965,6 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi | |||
1018 | dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd); | 965 | dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd); |
1019 | 966 | ||
1020 | switch (cmd) { | 967 | switch (cmd) { |
1021 | case TIOCGSERIAL: | ||
1022 | if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct ktermios))) { | ||
1023 | return -EFAULT; | ||
1024 | } | ||
1025 | return (0); | ||
1026 | break; | ||
1027 | case TIOCSSERIAL: | ||
1028 | if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct ktermios))) { | ||
1029 | return -EFAULT; | ||
1030 | } | ||
1031 | /* here we need to call cypress_set_termios to invoke the new settings */ | ||
1032 | cypress_set_termios(port, &priv->tmp_termios); | ||
1033 | return (0); | ||
1034 | break; | ||
1035 | /* This code comes from drivers/char/serial.c and ftdi_sio.c */ | 968 | /* This code comes from drivers/char/serial.c and ftdi_sio.c */ |
1036 | case TIOCMIWAIT: | 969 | case TIOCMIWAIT: |
1037 | while (priv != NULL) { | 970 | while (priv != NULL) { |
@@ -1079,7 +1012,7 @@ static void cypress_set_termios (struct usb_serial_port *port, | |||
1079 | struct cypress_private *priv = usb_get_serial_port_data(port); | 1012 | struct cypress_private *priv = usb_get_serial_port_data(port); |
1080 | struct tty_struct *tty; | 1013 | struct tty_struct *tty; |
1081 | int data_bits, stop_bits, parity_type, parity_enable; | 1014 | int data_bits, stop_bits, parity_type, parity_enable; |
1082 | unsigned cflag, iflag, baud_mask; | 1015 | unsigned cflag, iflag; |
1083 | unsigned long flags; | 1016 | unsigned long flags; |
1084 | __u8 oldlines; | 1017 | __u8 oldlines; |
1085 | int linechange = 0; | 1018 | int linechange = 0; |
@@ -1087,10 +1020,6 @@ static void cypress_set_termios (struct usb_serial_port *port, | |||
1087 | dbg("%s - port %d", __FUNCTION__, port->number); | 1020 | dbg("%s - port %d", __FUNCTION__, port->number); |
1088 | 1021 | ||
1089 | tty = port->tty; | 1022 | tty = port->tty; |
1090 | if ((!tty) || (!tty->termios)) { | ||
1091 | dbg("%s - no tty structures", __FUNCTION__); | ||
1092 | return; | ||
1093 | } | ||
1094 | 1023 | ||
1095 | spin_lock_irqsave(&priv->lock, flags); | 1024 | spin_lock_irqsave(&priv->lock, flags); |
1096 | if (!priv->termios_initialized) { | 1025 | if (!priv->termios_initialized) { |
@@ -1098,40 +1027,37 @@ static void cypress_set_termios (struct usb_serial_port *port, | |||
1098 | *(tty->termios) = tty_std_termios; | 1027 | *(tty->termios) = tty_std_termios; |
1099 | tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL | | 1028 | tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL | |
1100 | CLOCAL; | 1029 | CLOCAL; |
1030 | tty->termios->c_ispeed = 4800; | ||
1031 | tty->termios->c_ospeed = 4800; | ||
1101 | } else if (priv->chiptype == CT_CYPHIDCOM) { | 1032 | } else if (priv->chiptype == CT_CYPHIDCOM) { |
1102 | *(tty->termios) = tty_std_termios; | 1033 | *(tty->termios) = tty_std_termios; |
1103 | tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | | 1034 | tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | |
1104 | CLOCAL; | 1035 | CLOCAL; |
1036 | tty->termios->c_ispeed = 9600; | ||
1037 | tty->termios->c_ospeed = 9600; | ||
1105 | } else if (priv->chiptype == CT_CA42V2) { | 1038 | } else if (priv->chiptype == CT_CA42V2) { |
1106 | *(tty->termios) = tty_std_termios; | 1039 | *(tty->termios) = tty_std_termios; |
1107 | tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | | 1040 | tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | |
1108 | CLOCAL; | 1041 | CLOCAL; |
1042 | tty->termios->c_ispeed = 9600; | ||
1043 | tty->termios->c_ospeed = 9600; | ||
1109 | } | 1044 | } |
1110 | priv->termios_initialized = 1; | 1045 | priv->termios_initialized = 1; |
1111 | } | 1046 | } |
1112 | spin_unlock_irqrestore(&priv->lock, flags); | 1047 | spin_unlock_irqrestore(&priv->lock, flags); |
1113 | 1048 | ||
1049 | /* Unsupported features need clearing */ | ||
1050 | tty->termios->c_cflag &= ~(CMSPAR|CRTSCTS); | ||
1051 | |||
1114 | cflag = tty->termios->c_cflag; | 1052 | cflag = tty->termios->c_cflag; |
1115 | iflag = tty->termios->c_iflag; | 1053 | iflag = tty->termios->c_iflag; |
1116 | 1054 | ||
1117 | /* check if there are new settings */ | 1055 | /* check if there are new settings */ |
1118 | if (old_termios) { | 1056 | if (old_termios) { |
1119 | if ((cflag != old_termios->c_cflag) || | 1057 | spin_lock_irqsave(&priv->lock, flags); |
1120 | (RELEVANT_IFLAG(iflag) != | 1058 | priv->tmp_termios = *(tty->termios); |
1121 | RELEVANT_IFLAG(old_termios->c_iflag))) { | 1059 | spin_unlock_irqrestore(&priv->lock, flags); |
1122 | dbg("%s - attempting to set new termios settings", | 1060 | } |
1123 | __FUNCTION__); | ||
1124 | /* should make a copy of this in case something goes | ||
1125 | * wrong in the function, we can restore it */ | ||
1126 | spin_lock_irqsave(&priv->lock, flags); | ||
1127 | priv->tmp_termios = *(tty->termios); | ||
1128 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1129 | } else { | ||
1130 | dbg("%s - nothing to do, exiting", __FUNCTION__); | ||
1131 | return; | ||
1132 | } | ||
1133 | } else | ||
1134 | return; | ||
1135 | 1061 | ||
1136 | /* set number of data bits, parity, stop bits */ | 1062 | /* set number of data bits, parity, stop bits */ |
1137 | /* when parity is disabled the parity type bit is ignored */ | 1063 | /* when parity is disabled the parity type bit is ignored */ |
@@ -1173,53 +1099,16 @@ static void cypress_set_termios (struct usb_serial_port *port, | |||
1173 | if ((cflag & CBAUD) == B0) { | 1099 | if ((cflag & CBAUD) == B0) { |
1174 | /* drop dtr and rts */ | 1100 | /* drop dtr and rts */ |
1175 | dbg("%s - dropping the lines, baud rate 0bps", __FUNCTION__); | 1101 | dbg("%s - dropping the lines, baud rate 0bps", __FUNCTION__); |
1176 | baud_mask = B0; | ||
1177 | priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); | 1102 | priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); |
1178 | } else { | 1103 | } else |
1179 | baud_mask = (cflag & CBAUD); | ||
1180 | switch(baud_mask) { | ||
1181 | case B300: | ||
1182 | dbg("%s - setting baud 300bps", __FUNCTION__); | ||
1183 | break; | ||
1184 | case B600: | ||
1185 | dbg("%s - setting baud 600bps", __FUNCTION__); | ||
1186 | break; | ||
1187 | case B1200: | ||
1188 | dbg("%s - setting baud 1200bps", __FUNCTION__); | ||
1189 | break; | ||
1190 | case B2400: | ||
1191 | dbg("%s - setting baud 2400bps", __FUNCTION__); | ||
1192 | break; | ||
1193 | case B4800: | ||
1194 | dbg("%s - setting baud 4800bps", __FUNCTION__); | ||
1195 | break; | ||
1196 | case B9600: | ||
1197 | dbg("%s - setting baud 9600bps", __FUNCTION__); | ||
1198 | break; | ||
1199 | case B19200: | ||
1200 | dbg("%s - setting baud 19200bps", __FUNCTION__); | ||
1201 | break; | ||
1202 | case B38400: | ||
1203 | dbg("%s - setting baud 38400bps", __FUNCTION__); | ||
1204 | break; | ||
1205 | case B57600: | ||
1206 | dbg("%s - setting baud 57600bps", __FUNCTION__); | ||
1207 | break; | ||
1208 | case B115200: | ||
1209 | dbg("%s - setting baud 115200bps", __FUNCTION__); | ||
1210 | break; | ||
1211 | default: | ||
1212 | dbg("%s - unknown masked baud rate", __FUNCTION__); | ||
1213 | } | ||
1214 | priv->line_control = (CONTROL_DTR | CONTROL_RTS); | 1104 | priv->line_control = (CONTROL_DTR | CONTROL_RTS); |
1215 | } | ||
1216 | spin_unlock_irqrestore(&priv->lock, flags); | 1105 | spin_unlock_irqrestore(&priv->lock, flags); |
1217 | 1106 | ||
1218 | dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, " | 1107 | dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, " |
1219 | "%d data_bits (+5)", __FUNCTION__, stop_bits, | 1108 | "%d data_bits (+5)", __FUNCTION__, stop_bits, |
1220 | parity_enable, parity_type, data_bits); | 1109 | parity_enable, parity_type, data_bits); |
1221 | 1110 | ||
1222 | cypress_serial_control(port, baud_mask, data_bits, stop_bits, | 1111 | cypress_serial_control(port, tty_get_baud_rate(tty), data_bits, stop_bits, |
1223 | parity_enable, parity_type, 0, CYPRESS_SET_CONFIG); | 1112 | parity_enable, parity_type, 0, CYPRESS_SET_CONFIG); |
1224 | 1113 | ||
1225 | /* we perform a CYPRESS_GET_CONFIG so that the current settings are | 1114 | /* we perform a CYPRESS_GET_CONFIG so that the current settings are |