Lines Matching +full:usb +full:- +full:to +full:- +full:serial
1 // SPDX-License-Identifier: GPL-2.0+
3 * KOBIL USB Smart Card Terminal Driver
10 * This program is largely derived from work by the linux-usb group
11 * and associated source files. Please see the usb/serial files for
14 * Thanks to Greg Kroah-Hartman (greg@kroah.com) for his help and
17 * Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus
31 #include <linux/usb.h>
32 #include <linux/usb/serial.h>
36 #define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com"
37 #define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)"
76 MODULE_DEVICE_TABLE(usb, id_table);
82 .description = "KOBIL USB smart card terminal",
106 unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */
108 int cur_pos; /* index of the next char to send in buf */
115 struct usb_serial *serial = port->serial; in kobil_port_probe() local
120 return -ENOMEM; in kobil_port_probe()
122 priv->filled = 0; in kobil_port_probe()
123 priv->cur_pos = 0; in kobil_port_probe()
124 priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct); in kobil_port_probe()
126 switch (priv->device_type) { in kobil_port_probe()
128 dev_dbg(&serial->dev->dev, "KOBIL B1 PRO / KAAN PRO detected\n"); in kobil_port_probe()
131 dev_dbg(&serial->dev->dev, "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n"); in kobil_port_probe()
134 dev_dbg(&serial->dev->dev, "KOBIL USBTWIN detected\n"); in kobil_port_probe()
137 dev_dbg(&serial->dev->dev, "KOBIL KAAN SIM detected\n"); in kobil_port_probe()
156 /* Default to echo off and other sane device settings */ in kobil_init_termios()
157 tty->termios.c_lflag = 0; in kobil_init_termios()
158 tty->termios.c_iflag = IGNBRK | IGNPAR | IXOFF; in kobil_init_termios()
159 /* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */ in kobil_init_termios()
160 tty->termios.c_oflag &= ~ONLCR; in kobil_init_termios()
165 struct device *dev = &port->dev; in kobil_open()
176 return -ENOMEM; in kobil_open()
179 result = usb_control_msg(port->serial->dev, in kobil_open()
180 usb_rcvctrlpipe(port->serial->dev, 0), in kobil_open()
189 dev_dbg(dev, "%s - Send get_HW_version URB returns: %i\n", __func__, result); in kobil_open()
196 result = usb_control_msg(port->serial->dev, in kobil_open()
197 usb_rcvctrlpipe(port->serial->dev, 0), in kobil_open()
206 dev_dbg(dev, "%s - Send get_FW_version URB returns: %i\n", __func__, result); in kobil_open()
212 if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || in kobil_open()
213 priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { in kobil_open()
215 result = usb_control_msg(port->serial->dev, in kobil_open()
216 usb_sndctrlpipe(port->serial->dev, 0), in kobil_open()
226 dev_dbg(dev, "%s - Send set_baudrate URB returns: %i\n", __func__, result); in kobil_open()
229 result = usb_control_msg(port->serial->dev, in kobil_open()
230 usb_sndctrlpipe(port->serial->dev, 0), in kobil_open()
239 dev_dbg(dev, "%s - Send reset_all_queues URB returns: %i\n", __func__, result); in kobil_open()
241 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || in kobil_open()
242 priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || in kobil_open()
243 priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { in kobil_open()
245 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); in kobil_open()
246 dev_dbg(dev, "%s - Send read URB returns: %i\n", __func__, result); in kobil_open()
257 usb_kill_urb(port->interrupt_out_urb); in kobil_close()
258 usb_kill_urb(port->interrupt_in_urb); in kobil_close()
265 struct usb_serial_port *port = urb->context; in kobil_read_int_callback()
266 unsigned char *data = urb->transfer_buffer; in kobil_read_int_callback()
267 int status = urb->status; in kobil_read_int_callback()
270 dev_dbg(&port->dev, "%s - Read int status not zero: %d\n", __func__, status); in kobil_read_int_callback()
274 if (urb->actual_length) { in kobil_read_int_callback()
275 usb_serial_debug_data(&port->dev, __func__, urb->actual_length, in kobil_read_int_callback()
277 tty_insert_flip_string(&port->port, data, urb->actual_length); in kobil_read_int_callback()
278 tty_flip_buffer_push(&port->port); in kobil_read_int_callback()
281 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); in kobil_read_int_callback()
282 dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result); in kobil_read_int_callback()
300 dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__); in kobil_write()
306 if (count > (KOBIL_BUF_LENGTH - priv->filled)) { in kobil_write()
307 dev_dbg(&port->dev, "%s - Error: write request bigger than buffer size\n", __func__); in kobil_write()
308 return -ENOMEM; in kobil_write()
311 /* Copy data to buffer */ in kobil_write()
312 memcpy(priv->buf + priv->filled, buf, count); in kobil_write()
313 usb_serial_debug_data(&port->dev, __func__, count, priv->buf + priv->filled); in kobil_write()
314 priv->filled = priv->filled + count; in kobil_write()
318 …if (((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (… in kobil_write()
319 …((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv… in kobil_write()
321 if ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) in kobil_write()
322 || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID)) in kobil_write()
323 usb_kill_urb(port->interrupt_in_urb); in kobil_write()
325 todo = priv->filled - priv->cur_pos; in kobil_write()
329 length = min(todo, port->interrupt_out_size); in kobil_write()
330 /* copy data to transfer buffer */ in kobil_write()
331 memcpy(port->interrupt_out_buffer, in kobil_write()
332 priv->buf + priv->cur_pos, length); in kobil_write()
333 port->interrupt_out_urb->transfer_buffer_length = length; in kobil_write()
335 priv->cur_pos = priv->cur_pos + length; in kobil_write()
336 result = usb_submit_urb(port->interrupt_out_urb, in kobil_write()
338 dev_dbg(&port->dev, "%s - Send write URB returns: %i\n", __func__, result); in kobil_write()
339 todo = priv->filled - priv->cur_pos; in kobil_write()
345 priv->filled = 0; in kobil_write()
346 priv->cur_pos = 0; in kobil_write()
349 if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || in kobil_write()
350 priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { in kobil_write()
351 result = usb_submit_urb(port->interrupt_in_urb, in kobil_write()
353 dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result); in kobil_write()
369 struct usb_serial_port *port = tty->driver_data; in kobil_tiocmget()
376 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID in kobil_tiocmget()
377 || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { in kobil_tiocmget()
379 return -EINVAL; in kobil_tiocmget()
385 return -ENOMEM; in kobil_tiocmget()
387 result = usb_control_msg(port->serial->dev, in kobil_tiocmget()
388 usb_rcvctrlpipe(port->serial->dev, 0), in kobil_tiocmget()
397 dev_dbg(&port->dev, "Send get_status_line_state URB returns: %i\n", in kobil_tiocmget()
401 result = -EIO; in kobil_tiocmget()
405 dev_dbg(&port->dev, "Statusline: %02x\n", transfer_buffer[0]); in kobil_tiocmget()
418 struct usb_serial_port *port = tty->driver_data; in kobil_tiocmset()
419 struct device *dev = &port->dev; in kobil_tiocmset()
427 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID in kobil_tiocmset()
428 || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { in kobil_tiocmset()
430 return -EINVAL; in kobil_tiocmset()
442 if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) { in kobil_tiocmset()
444 dev_dbg(dev, "%s - Setting DTR\n", __func__); in kobil_tiocmset()
446 dev_dbg(dev, "%s - Clearing DTR\n", __func__); in kobil_tiocmset()
447 result = usb_control_msg(port->serial->dev, in kobil_tiocmset()
448 usb_sndctrlpipe(port->serial->dev, 0), in kobil_tiocmset()
458 dev_dbg(dev, "%s - Setting RTS\n", __func__); in kobil_tiocmset()
460 dev_dbg(dev, "%s - Clearing RTS\n", __func__); in kobil_tiocmset()
461 result = usb_control_msg(port->serial->dev, in kobil_tiocmset()
462 usb_sndctrlpipe(port->serial->dev, 0), in kobil_tiocmset()
471 dev_dbg(dev, "%s - Send set_status_line URB returns: %i\n", __func__, result); in kobil_tiocmset()
482 int c_cflag = tty->termios.c_cflag; in kobil_set_termios()
486 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || in kobil_set_termios()
487 priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { in kobil_set_termios()
489 tty_termios_copy_hw(&tty->termios, old); in kobil_set_termios()
514 tty->termios.c_cflag &= ~CMSPAR; in kobil_set_termios()
517 result = usb_control_msg(port->serial->dev, in kobil_set_termios()
518 usb_sndctrlpipe(port->serial->dev, 0), in kobil_set_termios()
528 dev_err(&port->dev, "failed to update line settings: %d\n", in kobil_set_termios()
536 struct usb_serial_port *port = tty->driver_data; in kobil_ioctl()
540 if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || in kobil_ioctl()
541 priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) in kobil_ioctl()
543 return -ENOIOCTLCMD; in kobil_ioctl()
547 result = usb_control_msg(port->serial->dev, in kobil_ioctl()
548 usb_sndctrlpipe(port->serial->dev, 0), in kobil_ioctl()
558 dev_dbg(&port->dev, in kobil_ioctl()
559 "%s - Send reset_all_queues (FLUSH) URB returns: %i\n", in kobil_ioctl()
561 return (result < 0) ? -EIO: 0; in kobil_ioctl()
563 return -ENOIOCTLCMD; in kobil_ioctl()