]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/usb/serial/cyberjack.c
USB: serial: simple: add libtransistor console
[mirror_ubuntu-bionic-kernel.git] / drivers / usb / serial / cyberjack.c
CommitLineData
5fd54ace 1// SPDX-License-Identifier: GPL-2.0+
1da177e4
LT
2/*
3 * REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver
4 *
5 * Copyright (C) 2001 REINER SCT
6 * Author: Matthias Bruestle
7 *
8 * Contact: support@reiner-sct.com (see MAINTAINERS)
9 *
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
12 * individual credits and copyrights.
13 *
1da177e4
LT
14 * Thanks to Greg Kroah-Hartman (greg@kroah.com) for his help and
15 * patience.
16 *
17 * In case of problems, please write to the contact e-mail address
18 * mentioned above.
19 *
20 * Please note that later models of the cyberjack reader family are
21 * supported by a libusb-based userspace device driver.
22 *
23 * Homepage: http://www.reiner-sct.de/support/treiber_cyberjack.php#linux
24 */
25
26
1da177e4
LT
27#include <linux/kernel.h>
28#include <linux/errno.h>
1da177e4
LT
29#include <linux/slab.h>
30#include <linux/tty.h>
31#include <linux/tty_driver.h>
32#include <linux/tty_flip.h>
33#include <linux/module.h>
34#include <linux/spinlock.h>
b9c52f15 35#include <linux/uaccess.h>
1da177e4 36#include <linux/usb.h>
a969888c 37#include <linux/usb/serial.h>
1da177e4
LT
38
39#define CYBERJACK_LOCAL_BUF_SIZE 32
40
1da177e4
LT
41#define DRIVER_AUTHOR "Matthias Bruestle"
42#define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver"
43
44
45#define CYBERJACK_VENDOR_ID 0x0C4B
46#define CYBERJACK_PRODUCT_ID 0x0100
47
48/* Function prototypes */
a9556040
JH
49static int cyberjack_port_probe(struct usb_serial_port *port);
50static int cyberjack_port_remove(struct usb_serial_port *port);
95da310e 51static int cyberjack_open(struct tty_struct *tty,
a509a7e4 52 struct usb_serial_port *port);
335f8514 53static void cyberjack_close(struct usb_serial_port *port);
95da310e
AC
54static int cyberjack_write(struct tty_struct *tty,
55 struct usb_serial_port *port, const unsigned char *buf, int count);
b9c52f15 56static int cyberjack_write_room(struct tty_struct *tty);
95da310e
AC
57static void cyberjack_read_int_callback(struct urb *urb);
58static void cyberjack_read_bulk_callback(struct urb *urb);
59static void cyberjack_write_bulk_callback(struct urb *urb);
1da177e4 60
7d40d7e8 61static const struct usb_device_id id_table[] = {
1da177e4
LT
62 { USB_DEVICE(CYBERJACK_VENDOR_ID, CYBERJACK_PRODUCT_ID) },
63 { } /* Terminating entry */
64};
65
b9c52f15 66MODULE_DEVICE_TABLE(usb, id_table);
1da177e4 67
ea65370d 68static struct usb_serial_driver cyberjack_device = {
18fcac35
GKH
69 .driver = {
70 .owner = THIS_MODULE,
269bda1c 71 .name = "cyberjack",
18fcac35 72 },
269bda1c 73 .description = "Reiner SCT Cyberjack USB card reader",
1da177e4 74 .id_table = id_table,
1da177e4 75 .num_ports = 1,
d183b9b4 76 .num_bulk_out = 1,
a9556040
JH
77 .port_probe = cyberjack_port_probe,
78 .port_remove = cyberjack_port_remove,
1da177e4
LT
79 .open = cyberjack_open,
80 .close = cyberjack_close,
81 .write = cyberjack_write,
d9b1b787 82 .write_room = cyberjack_write_room,
1da177e4
LT
83 .read_int_callback = cyberjack_read_int_callback,
84 .read_bulk_callback = cyberjack_read_bulk_callback,
85 .write_bulk_callback = cyberjack_write_bulk_callback,
86};
87
08a4f6bc
AS
88static struct usb_serial_driver * const serial_drivers[] = {
89 &cyberjack_device, NULL
90};
91
1da177e4
LT
92struct cyberjack_private {
93 spinlock_t lock; /* Lock for SMP */
94 short rdtodo; /* Bytes still to read */
95 unsigned char wrbuf[5*64]; /* Buffer for collecting data to write */
96 short wrfilled; /* Overall data size we already got */
97 short wrsent; /* Data already sent */
98};
99
a9556040 100static int cyberjack_port_probe(struct usb_serial_port *port)
1da177e4
LT
101{
102 struct cyberjack_private *priv;
a9556040 103 int result;
1da177e4 104
1da177e4
LT
105 priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
106 if (!priv)
107 return -ENOMEM;
108
1da177e4
LT
109 spin_lock_init(&priv->lock);
110 priv->rdtodo = 0;
111 priv->wrfilled = 0;
112 priv->wrsent = 0;
a9556040
JH
113
114 usb_set_serial_port_data(port, priv);
115
116 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
117 if (result)
118 dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
1da177e4 119
b9c52f15 120 return 0;
1da177e4
LT
121}
122
a9556040 123static int cyberjack_port_remove(struct usb_serial_port *port)
1da177e4 124{
a9556040 125 struct cyberjack_private *priv;
b9c52f15 126
30d9d42e
JH
127 usb_kill_urb(port->interrupt_in_urb);
128
a9556040
JH
129 priv = usb_get_serial_port_data(port);
130 kfree(priv);
131
132 return 0;
f9c99bb8
AS
133}
134
95da310e 135static int cyberjack_open(struct tty_struct *tty,
a509a7e4 136 struct usb_serial_port *port)
1da177e4
LT
137{
138 struct cyberjack_private *priv;
139 unsigned long flags;
1da177e4 140
96fc8e8d 141 dev_dbg(&port->dev, "%s - usb_clear_halt\n", __func__);
1da177e4
LT
142 usb_clear_halt(port->serial->dev, port->write_urb->pipe);
143
1da177e4
LT
144 priv = usb_get_serial_port_data(port);
145 spin_lock_irqsave(&priv->lock, flags);
146 priv->rdtodo = 0;
147 priv->wrfilled = 0;
148 priv->wrsent = 0;
149 spin_unlock_irqrestore(&priv->lock, flags);
150
0f3083af 151 return 0;
1da177e4
LT
152}
153
335f8514 154static void cyberjack_close(struct usb_serial_port *port)
1da177e4 155{
1bc77f4d
JH
156 usb_kill_urb(port->write_urb);
157 usb_kill_urb(port->read_urb);
1da177e4
LT
158}
159
95da310e
AC
160static int cyberjack_write(struct tty_struct *tty,
161 struct usb_serial_port *port, const unsigned char *buf, int count)
1da177e4 162{
96fc8e8d 163 struct device *dev = &port->dev;
1da177e4
LT
164 struct cyberjack_private *priv = usb_get_serial_port_data(port);
165 unsigned long flags;
166 int result;
167 int wrexpected;
168
1da177e4 169 if (count == 0) {
96fc8e8d 170 dev_dbg(dev, "%s - write request of 0 bytes\n", __func__);
a5b6f60c 171 return 0;
1da177e4
LT
172 }
173
c1cac10c 174 if (!test_and_clear_bit(0, &port->write_urbs_free)) {
96fc8e8d 175 dev_dbg(dev, "%s - already writing\n", __func__);
507ca9bc 176 return 0;
1da177e4
LT
177 }
178
179 spin_lock_irqsave(&priv->lock, flags);
180
b9c52f15 181 if (count+priv->wrfilled > sizeof(priv->wrbuf)) {
1da177e4 182 /* To much data for buffer. Reset buffer. */
a5b6f60c 183 priv->wrfilled = 0;
a5b6f60c 184 spin_unlock_irqrestore(&priv->lock, flags);
c1cac10c 185 set_bit(0, &port->write_urbs_free);
a5b6f60c 186 return 0;
1da177e4
LT
187 }
188
189 /* Copy data */
b9c52f15 190 memcpy(priv->wrbuf + priv->wrfilled, buf, count);
1da177e4 191
59d33f2f 192 usb_serial_debug_data(dev, __func__, count, priv->wrbuf + priv->wrfilled);
1da177e4
LT
193 priv->wrfilled += count;
194
b9c52f15 195 if (priv->wrfilled >= 3) {
1da177e4 196 wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
96fc8e8d 197 dev_dbg(dev, "%s - expected data: %d\n", __func__, wrexpected);
b9c52f15 198 } else
1da177e4 199 wrexpected = sizeof(priv->wrbuf);
1da177e4 200
b9c52f15 201 if (priv->wrfilled >= wrexpected) {
1da177e4
LT
202 /* We have enough data to begin transmission */
203 int length;
204
96fc8e8d 205 dev_dbg(dev, "%s - transmitting data (frame 1)\n", __func__);
b9c52f15
AC
206 length = (wrexpected > port->bulk_out_size) ?
207 port->bulk_out_size : wrexpected;
1da177e4 208
b9c52f15
AC
209 memcpy(port->write_urb->transfer_buffer, priv->wrbuf, length);
210 priv->wrsent = length;
1da177e4
LT
211
212 /* set up our urb */
fd11961a 213 port->write_urb->transfer_buffer_length = length;
1da177e4
LT
214
215 /* send the data out the bulk port */
216 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
217 if (result) {
194343d9 218 dev_err(&port->dev,
d9a38a87 219 "%s - failed submitting write urb, error %d\n",
194343d9 220 __func__, result);
1da177e4 221 /* Throw away data. No better idea what to do with it. */
a5b6f60c
AC
222 priv->wrfilled = 0;
223 priv->wrsent = 0;
1da177e4 224 spin_unlock_irqrestore(&priv->lock, flags);
c1cac10c 225 set_bit(0, &port->write_urbs_free);
1da177e4
LT
226 return 0;
227 }
228
96fc8e8d
GKH
229 dev_dbg(dev, "%s - priv->wrsent=%d\n", __func__, priv->wrsent);
230 dev_dbg(dev, "%s - priv->wrfilled=%d\n", __func__, priv->wrfilled);
1da177e4 231
b9c52f15 232 if (priv->wrsent >= priv->wrfilled) {
96fc8e8d 233 dev_dbg(dev, "%s - buffer cleaned\n", __func__);
b9c52f15 234 memset(priv->wrbuf, 0, sizeof(priv->wrbuf));
a5b6f60c
AC
235 priv->wrfilled = 0;
236 priv->wrsent = 0;
1da177e4
LT
237 }
238 }
239
240 spin_unlock_irqrestore(&priv->lock, flags);
241
b9c52f15
AC
242 return count;
243}
1da177e4 244
95da310e 245static int cyberjack_write_room(struct tty_struct *tty)
1da177e4 246{
a5b6f60c 247 /* FIXME: .... */
1da177e4
LT
248 return CYBERJACK_LOCAL_BUF_SIZE;
249}
250
95da310e 251static void cyberjack_read_int_callback(struct urb *urb)
1da177e4 252{
cdc97792 253 struct usb_serial_port *port = urb->context;
1da177e4 254 struct cyberjack_private *priv = usb_get_serial_port_data(port);
96fc8e8d 255 struct device *dev = &port->dev;
1da177e4 256 unsigned char *data = urb->transfer_buffer;
7dcc85cd 257 int status = urb->status;
1da177e4
LT
258 int result;
259
1da177e4 260 /* the urb might have been killed. */
7dcc85cd 261 if (status)
1da177e4
LT
262 return;
263
59d33f2f 264 usb_serial_debug_data(dev, __func__, urb->actual_length, data);
1da177e4
LT
265
266 /* React only to interrupts signaling a bulk_in transfer */
b9c52f15 267 if (urb->actual_length == 4 && data[0] == 0x01) {
1da177e4 268 short old_rdtodo;
1da177e4
LT
269
270 /* This is a announcement of coming bulk_ins. */
271 unsigned short size = ((unsigned short)data[3]<<8)+data[2]+3;
272
273 spin_lock(&priv->lock);
274
275 old_rdtodo = priv->rdtodo;
276
5287bf72 277 if (old_rdtodo > SHRT_MAX - size) {
96fc8e8d 278 dev_dbg(dev, "To many bulk_in urbs to do.\n");
1da177e4
LT
279 spin_unlock(&priv->lock);
280 goto resubmit;
281 }
282
cd8c5053 283 /* "+=" is probably more fault tolerant than "=" */
1da177e4
LT
284 priv->rdtodo += size;
285
96fc8e8d 286 dev_dbg(dev, "%s - rdtodo: %d\n", __func__, priv->rdtodo);
1da177e4
LT
287
288 spin_unlock(&priv->lock);
289
b9c52f15 290 if (!old_rdtodo) {
1da177e4 291 result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
b9c52f15 292 if (result)
96fc8e8d 293 dev_err(dev, "%s - failed resubmitting read urb, error %d\n",
194343d9 294 __func__, result);
96fc8e8d 295 dev_dbg(dev, "%s - usb_submit_urb(read urb)\n", __func__);
1da177e4
LT
296 }
297 }
298
299resubmit:
1da177e4
LT
300 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
301 if (result)
194343d9 302 dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
96fc8e8d 303 dev_dbg(dev, "%s - usb_submit_urb(int urb)\n", __func__);
1da177e4
LT
304}
305
95da310e 306static void cyberjack_read_bulk_callback(struct urb *urb)
1da177e4 307{
cdc97792 308 struct usb_serial_port *port = urb->context;
1da177e4 309 struct cyberjack_private *priv = usb_get_serial_port_data(port);
96fc8e8d 310 struct device *dev = &port->dev;
1da177e4
LT
311 unsigned char *data = urb->transfer_buffer;
312 short todo;
1da177e4 313 int result;
7dcc85cd 314 int status = urb->status;
1da177e4 315
59d33f2f 316 usb_serial_debug_data(dev, __func__, urb->actual_length, data);
7dcc85cd 317 if (status) {
96fc8e8d
GKH
318 dev_dbg(dev, "%s - nonzero read bulk status received: %d\n",
319 __func__, status);
1da177e4
LT
320 return;
321 }
322
1da177e4 323 if (urb->actual_length) {
05c7cd39 324 tty_insert_flip_string(&port->port, data, urb->actual_length);
2e124b4a 325 tty_flip_buffer_push(&port->port);
1da177e4
LT
326 }
327
328 spin_lock(&priv->lock);
329
330 /* Reduce urbs to do by one. */
b9c52f15 331 priv->rdtodo -= urb->actual_length;
1da177e4 332 /* Just to be sure */
b9c52f15
AC
333 if (priv->rdtodo < 0)
334 priv->rdtodo = 0;
1da177e4
LT
335 todo = priv->rdtodo;
336
337 spin_unlock(&priv->lock);
338
96fc8e8d 339 dev_dbg(dev, "%s - rdtodo: %d\n", __func__, todo);
1da177e4
LT
340
341 /* Continue to read if we have still urbs to do. */
b9c52f15 342 if (todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/) {
1da177e4
LT
343 result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
344 if (result)
96fc8e8d
GKH
345 dev_err(dev, "%s - failed resubmitting read urb, error %d\n",
346 __func__, result);
347 dev_dbg(dev, "%s - usb_submit_urb(read urb)\n", __func__);
1da177e4
LT
348 }
349}
350
95da310e 351static void cyberjack_write_bulk_callback(struct urb *urb)
1da177e4 352{
cdc97792 353 struct usb_serial_port *port = urb->context;
1da177e4 354 struct cyberjack_private *priv = usb_get_serial_port_data(port);
96fc8e8d 355 struct device *dev = &port->dev;
7dcc85cd 356 int status = urb->status;
1da177e4 357
c1cac10c 358 set_bit(0, &port->write_urbs_free);
7dcc85cd 359 if (status) {
96fc8e8d
GKH
360 dev_dbg(dev, "%s - nonzero write bulk status received: %d\n",
361 __func__, status);
1da177e4
LT
362 return;
363 }
364
365 spin_lock(&priv->lock);
366
367 /* only do something if we have more data to send */
b9c52f15 368 if (priv->wrfilled) {
1da177e4
LT
369 int length, blksize, result;
370
96fc8e8d 371 dev_dbg(dev, "%s - transmitting data (frame n)\n", __func__);
1da177e4
LT
372
373 length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ?
374 port->bulk_out_size : (priv->wrfilled - priv->wrsent);
375
b9c52f15
AC
376 memcpy(port->write_urb->transfer_buffer,
377 priv->wrbuf + priv->wrsent, length);
378 priv->wrsent += length;
1da177e4
LT
379
380 /* set up our urb */
fd11961a 381 port->write_urb->transfer_buffer_length = length;
1da177e4
LT
382
383 /* send the data out the bulk port */
384 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
385 if (result) {
96fc8e8d 386 dev_err(dev, "%s - failed submitting write urb, error %d\n",
194343d9 387 __func__, result);
1da177e4 388 /* Throw away data. No better idea what to do with it. */
a5b6f60c
AC
389 priv->wrfilled = 0;
390 priv->wrsent = 0;
1da177e4
LT
391 goto exit;
392 }
393
96fc8e8d
GKH
394 dev_dbg(dev, "%s - priv->wrsent=%d\n", __func__, priv->wrsent);
395 dev_dbg(dev, "%s - priv->wrfilled=%d\n", __func__, priv->wrfilled);
1da177e4
LT
396
397 blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
398
b9c52f15
AC
399 if (priv->wrsent >= priv->wrfilled ||
400 priv->wrsent >= blksize) {
96fc8e8d 401 dev_dbg(dev, "%s - buffer cleaned\n", __func__);
b9c52f15 402 memset(priv->wrbuf, 0, sizeof(priv->wrbuf));
a5b6f60c
AC
403 priv->wrfilled = 0;
404 priv->wrsent = 0;
1da177e4
LT
405 }
406 }
407
408exit:
409 spin_unlock(&priv->lock);
cf2c7481 410 usb_serial_port_softint(port);
1da177e4
LT
411}
412
68e24113 413module_usb_serial_driver(serial_drivers, id_table);
1da177e4 414
b9c52f15
AC
415MODULE_AUTHOR(DRIVER_AUTHOR);
416MODULE_DESCRIPTION(DRIVER_DESC);
1da177e4 417MODULE_LICENSE("GPL");