* Copyright (C) 2001 REINER SCT
* Author: Matthias Bruestle
*
- * Contact: linux-usb@sii.li (see MAINTAINERS)
+ * Contact: support@reiner-sct.com (see MAINTAINERS)
*
* This program is largely derived from work by the linux-usb group
* and associated source files. Please see the usb/serial files for
*
* In case of problems, please write to the contact e-mail address
* mentioned above.
+ *
+ * Please note that later models of the cyberjack reader family are
+ * supported by a libusb-based userspace device driver.
+ *
+ * Homepage: http://www.reiner-sct.de/support/treiber_cyberjack.php#linux
*/
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.0"
+#define DRIVER_VERSION "v1.01"
#define DRIVER_AUTHOR "Matthias Bruestle"
#define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver"
static void cyberjack_shutdown (struct usb_serial *serial);
static int cyberjack_open (struct usb_serial_port *port, struct file *filp);
static void cyberjack_close (struct usb_serial_port *port, struct file *filp);
-static int cyberjack_write (struct usb_serial_port *port, int from_user,
- const unsigned char *buf, int count);
+static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count);
static int cyberjack_write_room( struct usb_serial_port *port );
static void cyberjack_read_int_callback (struct urb *urb, struct pt_regs *regs);
static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_driver cyberjack_driver = {
- .owner = THIS_MODULE,
.name = "cyberjack",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
-static struct usb_serial_device_type cyberjack_device = {
- .owner = THIS_MODULE,
- .name = "Reiner SCT Cyberjack USB card reader",
- .short_name = "cyberjack",
+static struct usb_serial_driver cyberjack_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "cyberjack",
+ },
+ .description = "Reiner SCT Cyberjack USB card reader",
.id_table = id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
static int cyberjack_startup (struct usb_serial *serial)
{
struct cyberjack_private *priv;
+ int i;
dbg("%s", __FUNCTION__);
init_waitqueue_head(&serial->port[0]->write_wait);
+ for (i = 0; i < serial->num_ports; ++i) {
+ int result;
+ serial->port[i]->interrupt_in_urb->dev = serial->dev;
+ result = usb_submit_urb(serial->port[i]->interrupt_in_urb,
+ GFP_KERNEL);
+ if (result)
+ err(" usb_submit_urb(read int) failed");
+ dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
+ }
+
return( 0 );
}
dbg("%s", __FUNCTION__);
for (i=0; i < serial->num_ports; ++i) {
+ usb_kill_urb(serial->port[i]->interrupt_in_urb);
/* My special items, the standard routines free my urbs */
kfree(usb_get_serial_port_data(serial->port[i]));
usb_set_serial_port_data(serial->port[i], NULL);
priv->wrsent = 0;
spin_unlock_irqrestore(&priv->lock, flags);
- /* shutdown any bulk reads that might be going on */
- usb_unlink_urb (port->write_urb);
- usb_unlink_urb (port->read_urb);
- usb_unlink_urb (port->interrupt_in_urb);
-
- port->interrupt_in_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
- if (result)
- err(" usb_submit_urb(read int) failed");
- dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
-
return result;
}
if (port->serial->dev) {
/* shutdown any bulk reads that might be going on */
- usb_unlink_urb (port->write_urb);
- usb_unlink_urb (port->read_urb);
- usb_unlink_urb (port->interrupt_in_urb);
- dbg("%s - usb_clear_halt", __FUNCTION__ );
- usb_clear_halt(port->serial->dev, port->write_urb->pipe);
- usb_clear_halt(port->serial->dev, port->read_urb->pipe);
- usb_clear_halt(port->serial->dev, port->interrupt_in_urb->pipe);
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
}
}
-static int cyberjack_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
+static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
int wrexpected;
dbg("%s - port %d", __FUNCTION__, port->number);
- dbg("%s - from_user %d", __FUNCTION__, from_user);
if (count == 0) {
dbg("%s - write request of 0 bytes", __FUNCTION__);
return (0);
}
- if (port->write_urb->status == -EINPROGRESS) {
+ spin_lock(&port->lock);
+ if (port->write_urb_busy) {
+ spin_unlock(&port->lock);
dbg("%s - already writing", __FUNCTION__);
- return (0);
+ return 0;
}
+ port->write_urb_busy = 1;
+ spin_unlock(&port->lock);
spin_lock_irqsave(&priv->lock, flags);
/* To much data for buffer. Reset buffer. */
priv->wrfilled=0;
spin_unlock_irqrestore(&priv->lock, flags);
+ port->write_urb_busy = 0;
return (0);
}
/* Copy data */
- if (from_user) {
- if (copy_from_user(priv->wrbuf+priv->wrfilled, buf, count)) {
- spin_unlock_irqrestore(&priv->lock, flags);
- return -EFAULT;
- }
- } else {
- memcpy (priv->wrbuf+priv->wrfilled, buf, count);
- }
+ memcpy (priv->wrbuf+priv->wrfilled, buf, count);
usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
priv->wrbuf+priv->wrfilled);
priv->wrfilled=0;
priv->wrsent=0;
spin_unlock_irqrestore(&priv->lock, flags);
+ port->write_urb_busy = 0;
return 0;
}
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
short todo;
- int i;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
}
tty = port->tty;
+ if (!tty) {
+ dbg("%s - ignoring since device not open\n", __FUNCTION__);
+ return;
+ }
if (urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless tty->low_latency is set */
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
struct cyberjack_private *priv = usb_get_serial_port_data(port);
dbg("%s - port %d", __FUNCTION__, port->number);
-
+
+ port->write_urb_busy = 0;
if (urb->status) {
dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
return;
if( priv->wrfilled ) {
int length, blksize, result;
- if (port->write_urb->status == -EINPROGRESS) {
- dbg("%s - already writing", __FUNCTION__);
- spin_unlock(&priv->lock);
- return;
- }
-
dbg("%s - transmitting data (frame n)", __FUNCTION__);
length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ?
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_VERSION( DRIVER_VERSION );
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);