0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #include <linux/module.h>
0022 #include <linux/slab.h>
0023 #include <linux/tty.h>
0024 #include <linux/usb.h>
0025 #include <linux/usb/serial.h>
0026
0027 #define DRIVER_DESC "Renesas uPD78F0730 USB to serial converter driver"
0028
0029 #define DRIVER_AUTHOR "Maksim Salau <maksim.salau@gmail.com>"
0030
0031 static const struct usb_device_id id_table[] = {
0032 { USB_DEVICE(0x0409, 0x0063) },
0033 { USB_DEVICE(0x045B, 0x0212) },
0034 { USB_DEVICE(0x064B, 0x7825) },
0035 {}
0036 };
0037
0038 MODULE_DEVICE_TABLE(usb, id_table);
0039
0040
0041
0042
0043
0044 struct upd78f0730_port_private {
0045 struct mutex lock;
0046 u8 line_signals;
0047 };
0048
0049
0050 #define UPD78F0730_CMD_LINE_CONTROL 0x00
0051 #define UPD78F0730_CMD_SET_DTR_RTS 0x01
0052 #define UPD78F0730_CMD_SET_XON_XOFF_CHR 0x02
0053 #define UPD78F0730_CMD_OPEN_CLOSE 0x03
0054 #define UPD78F0730_CMD_SET_ERR_CHR 0x04
0055
0056
0057 #define UPD78F0730_DATA_SIZE_7_BITS 0x00
0058 #define UPD78F0730_DATA_SIZE_8_BITS 0x01
0059 #define UPD78F0730_DATA_SIZE_MASK 0x01
0060
0061
0062 #define UPD78F0730_STOP_BIT_1_BIT 0x00
0063 #define UPD78F0730_STOP_BIT_2_BIT 0x02
0064 #define UPD78F0730_STOP_BIT_MASK 0x02
0065
0066
0067 #define UPD78F0730_PARITY_NONE 0x00
0068 #define UPD78F0730_PARITY_EVEN 0x04
0069 #define UPD78F0730_PARITY_ODD 0x08
0070 #define UPD78F0730_PARITY_MASK 0x0C
0071
0072
0073 #define UPD78F0730_FLOW_CONTROL_NONE 0x00
0074 #define UPD78F0730_FLOW_CONTROL_HW 0x10
0075 #define UPD78F0730_FLOW_CONTROL_SW 0x20
0076 #define UPD78F0730_FLOW_CONTROL_MASK 0x30
0077
0078
0079 #define UPD78F0730_RTS 0x01
0080 #define UPD78F0730_DTR 0x02
0081 #define UPD78F0730_BREAK 0x04
0082
0083
0084 #define UPD78F0730_PORT_CLOSE 0x00
0085 #define UPD78F0730_PORT_OPEN 0x01
0086
0087
0088 #define UPD78F0730_ERR_CHR_DISABLED 0x00
0089 #define UPD78F0730_ERR_CHR_ENABLED 0x01
0090
0091
0092
0093
0094
0095
0096 struct upd78f0730_line_control {
0097 u8 opcode;
0098 __le32 baud_rate;
0099 u8 params;
0100 } __packed;
0101
0102
0103 struct upd78f0730_set_dtr_rts {
0104 u8 opcode;
0105 u8 params;
0106 };
0107
0108
0109 struct upd78f0730_set_xon_xoff_chr {
0110 u8 opcode;
0111 u8 xon;
0112 u8 xoff;
0113 };
0114
0115
0116 struct upd78f0730_open_close {
0117 u8 opcode;
0118 u8 state;
0119 };
0120
0121
0122 struct upd78f0730_set_err_chr {
0123 u8 opcode;
0124 u8 state;
0125 u8 err_char;
0126 };
0127
0128 static int upd78f0730_send_ctl(struct usb_serial_port *port,
0129 const void *data, int size)
0130 {
0131 struct usb_device *usbdev = port->serial->dev;
0132 void *buf;
0133 int res;
0134
0135 if (size <= 0 || !data)
0136 return -EINVAL;
0137
0138 buf = kmemdup(data, size, GFP_KERNEL);
0139 if (!buf)
0140 return -ENOMEM;
0141
0142 res = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x00,
0143 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
0144 0x0000, 0x0000, buf, size, USB_CTRL_SET_TIMEOUT);
0145
0146 kfree(buf);
0147
0148 if (res < 0) {
0149 struct device *dev = &port->dev;
0150
0151 dev_err(dev, "failed to send control request %02x: %d\n",
0152 *(u8 *)data, res);
0153
0154 return res;
0155 }
0156
0157 return 0;
0158 }
0159
0160 static int upd78f0730_port_probe(struct usb_serial_port *port)
0161 {
0162 struct upd78f0730_port_private *private;
0163
0164 private = kzalloc(sizeof(*private), GFP_KERNEL);
0165 if (!private)
0166 return -ENOMEM;
0167
0168 mutex_init(&private->lock);
0169 usb_set_serial_port_data(port, private);
0170
0171 return 0;
0172 }
0173
0174 static void upd78f0730_port_remove(struct usb_serial_port *port)
0175 {
0176 struct upd78f0730_port_private *private;
0177
0178 private = usb_get_serial_port_data(port);
0179 mutex_destroy(&private->lock);
0180 kfree(private);
0181 }
0182
0183 static int upd78f0730_tiocmget(struct tty_struct *tty)
0184 {
0185 struct upd78f0730_port_private *private;
0186 struct usb_serial_port *port = tty->driver_data;
0187 int signals;
0188 int res;
0189
0190 private = usb_get_serial_port_data(port);
0191
0192 mutex_lock(&private->lock);
0193 signals = private->line_signals;
0194 mutex_unlock(&private->lock);
0195
0196 res = ((signals & UPD78F0730_DTR) ? TIOCM_DTR : 0) |
0197 ((signals & UPD78F0730_RTS) ? TIOCM_RTS : 0);
0198
0199 dev_dbg(&port->dev, "%s - res = %x\n", __func__, res);
0200
0201 return res;
0202 }
0203
0204 static int upd78f0730_tiocmset(struct tty_struct *tty,
0205 unsigned int set, unsigned int clear)
0206 {
0207 struct usb_serial_port *port = tty->driver_data;
0208 struct upd78f0730_port_private *private;
0209 struct upd78f0730_set_dtr_rts request;
0210 struct device *dev = &port->dev;
0211 int res;
0212
0213 private = usb_get_serial_port_data(port);
0214
0215 mutex_lock(&private->lock);
0216 if (set & TIOCM_DTR) {
0217 private->line_signals |= UPD78F0730_DTR;
0218 dev_dbg(dev, "%s - set DTR\n", __func__);
0219 }
0220 if (set & TIOCM_RTS) {
0221 private->line_signals |= UPD78F0730_RTS;
0222 dev_dbg(dev, "%s - set RTS\n", __func__);
0223 }
0224 if (clear & TIOCM_DTR) {
0225 private->line_signals &= ~UPD78F0730_DTR;
0226 dev_dbg(dev, "%s - clear DTR\n", __func__);
0227 }
0228 if (clear & TIOCM_RTS) {
0229 private->line_signals &= ~UPD78F0730_RTS;
0230 dev_dbg(dev, "%s - clear RTS\n", __func__);
0231 }
0232 request.opcode = UPD78F0730_CMD_SET_DTR_RTS;
0233 request.params = private->line_signals;
0234
0235 res = upd78f0730_send_ctl(port, &request, sizeof(request));
0236 mutex_unlock(&private->lock);
0237
0238 return res;
0239 }
0240
0241 static void upd78f0730_break_ctl(struct tty_struct *tty, int break_state)
0242 {
0243 struct upd78f0730_port_private *private;
0244 struct usb_serial_port *port = tty->driver_data;
0245 struct upd78f0730_set_dtr_rts request;
0246 struct device *dev = &port->dev;
0247
0248 private = usb_get_serial_port_data(port);
0249
0250 mutex_lock(&private->lock);
0251 if (break_state) {
0252 private->line_signals |= UPD78F0730_BREAK;
0253 dev_dbg(dev, "%s - set BREAK\n", __func__);
0254 } else {
0255 private->line_signals &= ~UPD78F0730_BREAK;
0256 dev_dbg(dev, "%s - clear BREAK\n", __func__);
0257 }
0258 request.opcode = UPD78F0730_CMD_SET_DTR_RTS;
0259 request.params = private->line_signals;
0260
0261 upd78f0730_send_ctl(port, &request, sizeof(request));
0262 mutex_unlock(&private->lock);
0263 }
0264
0265 static void upd78f0730_dtr_rts(struct usb_serial_port *port, int on)
0266 {
0267 struct tty_struct *tty = port->port.tty;
0268 unsigned int set = 0;
0269 unsigned int clear = 0;
0270
0271 if (on)
0272 set = TIOCM_DTR | TIOCM_RTS;
0273 else
0274 clear = TIOCM_DTR | TIOCM_RTS;
0275
0276 upd78f0730_tiocmset(tty, set, clear);
0277 }
0278
0279 static speed_t upd78f0730_get_baud_rate(struct tty_struct *tty)
0280 {
0281 const speed_t baud_rate = tty_get_baud_rate(tty);
0282 static const speed_t supported[] = {
0283 0, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 153600
0284 };
0285 int i;
0286
0287 for (i = ARRAY_SIZE(supported) - 1; i >= 0; i--) {
0288 if (baud_rate == supported[i])
0289 return baud_rate;
0290 }
0291
0292
0293 tty_encode_baud_rate(tty, 9600, 9600);
0294
0295 return tty_get_baud_rate(tty);
0296 }
0297
0298 static void upd78f0730_set_termios(struct tty_struct *tty,
0299 struct usb_serial_port *port,
0300 struct ktermios *old_termios)
0301 {
0302 struct device *dev = &port->dev;
0303 struct upd78f0730_line_control request;
0304 speed_t baud_rate;
0305
0306 if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios))
0307 return;
0308
0309 if (C_BAUD(tty) == B0)
0310 upd78f0730_dtr_rts(port, 0);
0311 else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
0312 upd78f0730_dtr_rts(port, 1);
0313
0314 baud_rate = upd78f0730_get_baud_rate(tty);
0315 request.opcode = UPD78F0730_CMD_LINE_CONTROL;
0316 request.baud_rate = cpu_to_le32(baud_rate);
0317 request.params = 0;
0318 dev_dbg(dev, "%s - baud rate = %d\n", __func__, baud_rate);
0319
0320 switch (C_CSIZE(tty)) {
0321 case CS7:
0322 request.params |= UPD78F0730_DATA_SIZE_7_BITS;
0323 dev_dbg(dev, "%s - 7 data bits\n", __func__);
0324 break;
0325 default:
0326 tty->termios.c_cflag &= ~CSIZE;
0327 tty->termios.c_cflag |= CS8;
0328 dev_warn(dev, "data size is not supported, using 8 bits\n");
0329 fallthrough;
0330 case CS8:
0331 request.params |= UPD78F0730_DATA_SIZE_8_BITS;
0332 dev_dbg(dev, "%s - 8 data bits\n", __func__);
0333 break;
0334 }
0335
0336 if (C_PARENB(tty)) {
0337 if (C_PARODD(tty)) {
0338 request.params |= UPD78F0730_PARITY_ODD;
0339 dev_dbg(dev, "%s - odd parity\n", __func__);
0340 } else {
0341 request.params |= UPD78F0730_PARITY_EVEN;
0342 dev_dbg(dev, "%s - even parity\n", __func__);
0343 }
0344
0345 if (C_CMSPAR(tty)) {
0346 tty->termios.c_cflag &= ~CMSPAR;
0347 dev_warn(dev, "MARK/SPACE parity is not supported\n");
0348 }
0349 } else {
0350 request.params |= UPD78F0730_PARITY_NONE;
0351 dev_dbg(dev, "%s - no parity\n", __func__);
0352 }
0353
0354 if (C_CSTOPB(tty)) {
0355 request.params |= UPD78F0730_STOP_BIT_2_BIT;
0356 dev_dbg(dev, "%s - 2 stop bits\n", __func__);
0357 } else {
0358 request.params |= UPD78F0730_STOP_BIT_1_BIT;
0359 dev_dbg(dev, "%s - 1 stop bit\n", __func__);
0360 }
0361
0362 if (C_CRTSCTS(tty)) {
0363 tty->termios.c_cflag &= ~CRTSCTS;
0364 dev_warn(dev, "RTSCTS flow control is not supported\n");
0365 }
0366 if (I_IXOFF(tty) || I_IXON(tty)) {
0367 tty->termios.c_iflag &= ~(IXOFF | IXON);
0368 dev_warn(dev, "XON/XOFF flow control is not supported\n");
0369 }
0370 request.params |= UPD78F0730_FLOW_CONTROL_NONE;
0371 dev_dbg(dev, "%s - no flow control\n", __func__);
0372
0373 upd78f0730_send_ctl(port, &request, sizeof(request));
0374 }
0375
0376 static int upd78f0730_open(struct tty_struct *tty, struct usb_serial_port *port)
0377 {
0378 static const struct upd78f0730_open_close request = {
0379 .opcode = UPD78F0730_CMD_OPEN_CLOSE,
0380 .state = UPD78F0730_PORT_OPEN
0381 };
0382 int res;
0383
0384 res = upd78f0730_send_ctl(port, &request, sizeof(request));
0385 if (res)
0386 return res;
0387
0388 if (tty)
0389 upd78f0730_set_termios(tty, port, NULL);
0390
0391 return usb_serial_generic_open(tty, port);
0392 }
0393
0394 static void upd78f0730_close(struct usb_serial_port *port)
0395 {
0396 static const struct upd78f0730_open_close request = {
0397 .opcode = UPD78F0730_CMD_OPEN_CLOSE,
0398 .state = UPD78F0730_PORT_CLOSE
0399 };
0400
0401 usb_serial_generic_close(port);
0402 upd78f0730_send_ctl(port, &request, sizeof(request));
0403 }
0404
0405 static struct usb_serial_driver upd78f0730_device = {
0406 .driver = {
0407 .owner = THIS_MODULE,
0408 .name = "upd78f0730",
0409 },
0410 .id_table = id_table,
0411 .num_ports = 1,
0412 .port_probe = upd78f0730_port_probe,
0413 .port_remove = upd78f0730_port_remove,
0414 .open = upd78f0730_open,
0415 .close = upd78f0730_close,
0416 .set_termios = upd78f0730_set_termios,
0417 .tiocmget = upd78f0730_tiocmget,
0418 .tiocmset = upd78f0730_tiocmset,
0419 .dtr_rts = upd78f0730_dtr_rts,
0420 .break_ctl = upd78f0730_break_ctl,
0421 };
0422
0423 static struct usb_serial_driver * const serial_drivers[] = {
0424 &upd78f0730_device,
0425 NULL
0426 };
0427
0428 module_usb_serial_driver(serial_drivers, id_table);
0429
0430 MODULE_DESCRIPTION(DRIVER_DESC);
0431 MODULE_AUTHOR(DRIVER_AUTHOR);
0432 MODULE_LICENSE("GPL v2");