aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/cypress_m8.c
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2008-03-10 17:59:28 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-04-25 00:16:41 -0400
commit8873aaa6e574d85c020a1c472d6d159cd1ec8aef (patch)
tree790e1b119dfa28ba2ce9ac5a38fe72fb88aa20a4 /drivers/usb/serial/cypress_m8.c
parent25b70a8665e9854504b9196c3098dadd37c721aa (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.c169
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);
183static void cypress_set_dead (struct usb_serial_port *port); 182static void cypress_set_dead (struct usb_serial_port *port);
184static void cypress_read_int_callback (struct urb *urb); 183static void cypress_read_int_callback (struct urb *urb);
185static void cypress_write_int_callback (struct urb *urb); 184static void cypress_write_int_callback (struct urb *urb);
186/* baud helper functions */
187static int mask_to_rate (unsigned mask);
188static unsigned rate_to_mask (int rate);
189/* write buffer functions */ 185/* write buffer functions */
190static struct cypress_buf *cypress_buf_alloc(unsigned int size); 186static struct cypress_buf *cypress_buf_alloc(unsigned int size);
191static void cypress_buf_free(struct cypress_buf *cb); 187static 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
294static int analyze_baud_rate(struct usb_serial_port *port, unsigned baud_mask) 290static 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 */
348static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_mask, int data_bits, int stop_bits, 337static 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 */
486static 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
509static 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