cp210x.c (715a1284d89a740b197b3bad5eb20d36a397382f) | cp210x.c (7748feffcd80f3ee25dae5e6acd3cf90e8e838d8) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Silicon Laboratories CP210x USB to RS232 serial adaptor driver 4 * 5 * Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk) 6 * 7 * Support to set flow control line levels using TIOCMGET and TIOCMSET 8 * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow --- 363 unchanged lines hidden (view full) --- 372#define CONTROL_RTS 0x0002 373#define CONTROL_CTS 0x0010 374#define CONTROL_DSR 0x0020 375#define CONTROL_RING 0x0040 376#define CONTROL_DCD 0x0080 377#define CONTROL_WRITE_DTR 0x0100 378#define CONTROL_WRITE_RTS 0x0200 379 | 1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Silicon Laboratories CP210x USB to RS232 serial adaptor driver 4 * 5 * Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk) 6 * 7 * Support to set flow control line levels using TIOCMGET and TIOCMSET 8 * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow --- 363 unchanged lines hidden (view full) --- 372#define CONTROL_RTS 0x0002 373#define CONTROL_CTS 0x0010 374#define CONTROL_DSR 0x0020 375#define CONTROL_RING 0x0040 376#define CONTROL_DCD 0x0080 377#define CONTROL_WRITE_DTR 0x0100 378#define CONTROL_WRITE_RTS 0x0200 379 |
380/* CP210X_(GET|SET)_CHARS */ 381struct cp210x_special_chars { 382 u8 bEofChar; 383 u8 bErrorChar; 384 u8 bBreakChar; 385 u8 bEventChar; 386 u8 bXonChar; 387 u8 bXoffChar; 388}; 389 |
|
380/* CP210X_VENDOR_SPECIFIC values */ 381#define CP210X_READ_2NCONFIG 0x000E 382#define CP210X_READ_LATCH 0x00C2 383#define CP210X_GET_PARTNUM 0x370B 384#define CP210X_GET_PORTCONFIG 0x370C 385#define CP210X_GET_DEVICEMODE 0x3711 386#define CP210X_WRITE_LATCH 0x37E1 387 --- 681 unchanged lines hidden (view full) --- 1069 if (ret) { 1070 dev_err(&port->dev, "failed to disable events: %d\n", ret); 1071 return; 1072 } 1073 1074 port_priv->event_mode = false; 1075} 1076 | 390/* CP210X_VENDOR_SPECIFIC values */ 391#define CP210X_READ_2NCONFIG 0x000E 392#define CP210X_READ_LATCH 0x00C2 393#define CP210X_GET_PARTNUM 0x370B 394#define CP210X_GET_PORTCONFIG 0x370C 395#define CP210X_GET_DEVICEMODE 0x3711 396#define CP210X_WRITE_LATCH 0x37E1 397 --- 681 unchanged lines hidden (view full) --- 1079 if (ret) { 1080 dev_err(&port->dev, "failed to disable events: %d\n", ret); 1081 return; 1082 } 1083 1084 port_priv->event_mode = false; 1085} 1086 |
1087static int cp210x_set_chars(struct usb_serial_port *port, 1088 struct cp210x_special_chars *chars) 1089{ 1090 struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); 1091 struct usb_serial *serial = port->serial; 1092 void *dmabuf; 1093 int result; 1094 1095 dmabuf = kmemdup(chars, sizeof(*chars), GFP_KERNEL); 1096 if (!dmabuf) 1097 return -ENOMEM; 1098 1099 result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 1100 CP210X_SET_CHARS, REQTYPE_HOST_TO_INTERFACE, 0, 1101 port_priv->bInterfaceNumber, 1102 dmabuf, sizeof(*chars), USB_CTRL_SET_TIMEOUT); 1103 1104 kfree(dmabuf); 1105 1106 if (result < 0) { 1107 dev_err(&port->dev, "failed to set special chars: %d\n", result); 1108 return result; 1109 } 1110 1111 return 0; 1112} 1113 |
|
1077static bool cp210x_termios_change(const struct ktermios *a, const struct ktermios *b) 1078{ 1079 bool iflag_change; 1080 | 1114static bool cp210x_termios_change(const struct ktermios *a, const struct ktermios *b) 1115{ 1116 bool iflag_change; 1117 |
1081 iflag_change = ((a->c_iflag ^ b->c_iflag) & INPCK); | 1118 iflag_change = ((a->c_iflag ^ b->c_iflag) & (INPCK | IXON | IXOFF)); |
1082 1083 return tty_termios_hw_change(a, b) || iflag_change; 1084} 1085 1086static void cp210x_set_flow_control(struct tty_struct *tty, 1087 struct usb_serial_port *port, struct ktermios *old_termios) 1088{ | 1119 1120 return tty_termios_hw_change(a, b) || iflag_change; 1121} 1122 1123static void cp210x_set_flow_control(struct tty_struct *tty, 1124 struct usb_serial_port *port, struct ktermios *old_termios) 1125{ |
1126 struct cp210x_special_chars chars; |
|
1089 struct cp210x_flow_ctl flow_ctl; 1090 u32 flow_repl; 1091 u32 ctl_hs; 1092 int ret; 1093 | 1127 struct cp210x_flow_ctl flow_ctl; 1128 u32 flow_repl; 1129 u32 ctl_hs; 1130 int ret; 1131 |
1094 if (old_termios && C_CRTSCTS(tty) == (old_termios->c_cflag & CRTSCTS)) | 1132 if (old_termios && 1133 C_CRTSCTS(tty) == (old_termios->c_cflag & CRTSCTS) && 1134 I_IXON(tty) == (old_termios->c_iflag & IXON) && 1135 I_IXOFF(tty) == (old_termios->c_iflag & IXOFF)) { |
1095 return; | 1136 return; |
1137 } |
|
1096 | 1138 |
1139 if (I_IXON(tty) || I_IXOFF(tty)) { 1140 memset(&chars, 0, sizeof(chars)); 1141 1142 chars.bXonChar = START_CHAR(tty); 1143 chars.bXoffChar = STOP_CHAR(tty); 1144 1145 ret = cp210x_set_chars(port, &chars); 1146 if (ret) 1147 return; 1148 } 1149 |
|
1097 ret = cp210x_read_reg_block(port, CP210X_GET_FLOW, &flow_ctl, 1098 sizeof(flow_ctl)); 1099 if (ret) 1100 return; 1101 1102 ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake); 1103 flow_repl = le32_to_cpu(flow_ctl.ulFlowReplace); 1104 --- 8 unchanged lines hidden (view full) --- 1113 flow_repl &= ~CP210X_SERIAL_RTS_MASK; 1114 flow_repl |= CP210X_SERIAL_RTS_SHIFT(CP210X_SERIAL_RTS_FLOW_CTL); 1115 } else { 1116 ctl_hs &= ~CP210X_SERIAL_CTS_HANDSHAKE; 1117 flow_repl &= ~CP210X_SERIAL_RTS_MASK; 1118 flow_repl |= CP210X_SERIAL_RTS_SHIFT(CP210X_SERIAL_RTS_ACTIVE); 1119 } 1120 | 1150 ret = cp210x_read_reg_block(port, CP210X_GET_FLOW, &flow_ctl, 1151 sizeof(flow_ctl)); 1152 if (ret) 1153 return; 1154 1155 ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake); 1156 flow_repl = le32_to_cpu(flow_ctl.ulFlowReplace); 1157 --- 8 unchanged lines hidden (view full) --- 1166 flow_repl &= ~CP210X_SERIAL_RTS_MASK; 1167 flow_repl |= CP210X_SERIAL_RTS_SHIFT(CP210X_SERIAL_RTS_FLOW_CTL); 1168 } else { 1169 ctl_hs &= ~CP210X_SERIAL_CTS_HANDSHAKE; 1170 flow_repl &= ~CP210X_SERIAL_RTS_MASK; 1171 flow_repl |= CP210X_SERIAL_RTS_SHIFT(CP210X_SERIAL_RTS_ACTIVE); 1172 } 1173 |
1174 if (I_IXOFF(tty)) 1175 flow_repl |= CP210X_SERIAL_AUTO_RECEIVE; 1176 else 1177 flow_repl &= ~CP210X_SERIAL_AUTO_RECEIVE; 1178 1179 if (I_IXON(tty)) 1180 flow_repl |= CP210X_SERIAL_AUTO_TRANSMIT; 1181 else 1182 flow_repl &= ~CP210X_SERIAL_AUTO_TRANSMIT; 1183 |
|
1121 dev_dbg(&port->dev, "%s - ulControlHandshake=0x%08x, ulFlowReplace=0x%08x\n", 1122 __func__, ctl_hs, flow_repl); 1123 1124 flow_ctl.ulControlHandshake = cpu_to_le32(ctl_hs); 1125 flow_ctl.ulFlowReplace = cpu_to_le32(flow_repl); 1126 1127 cp210x_write_reg_block(port, CP210X_SET_FLOW, &flow_ctl, 1128 sizeof(flow_ctl)); --- 694 unchanged lines hidden --- | 1184 dev_dbg(&port->dev, "%s - ulControlHandshake=0x%08x, ulFlowReplace=0x%08x\n", 1185 __func__, ctl_hs, flow_repl); 1186 1187 flow_ctl.ulControlHandshake = cpu_to_le32(ctl_hs); 1188 flow_ctl.ulFlowReplace = cpu_to_le32(flow_repl); 1189 1190 cp210x_write_reg_block(port, CP210X_SET_FLOW, &flow_ctl, 1191 sizeof(flow_ctl)); --- 694 unchanged lines hidden --- |