diff options
Diffstat (limited to 'drivers/usb/serial/iuu_phoenix.c')
| -rw-r--r-- | drivers/usb/serial/iuu_phoenix.c | 675 |
1 files changed, 344 insertions, 331 deletions
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index fde188e23ce..5ad4a0fb4b2 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -1,6 +1,8 @@ /* * Infinity Unlimited USB Phoenix driver * + * Copyright (C) 2010 James Courtier-Dutton (James@superbug.co.uk) + * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com) * * Original code taken from iuutool (Copyright (C) 2006 Juan Carlos Borrás) @@ -15,7 +17,6 @@ */ #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/tty.h> #include <linux/tty_driver.h> @@ -30,138 +31,114 @@ #include "iuu_phoenix.h" #include <linux/random.h> - -#ifdef CONFIG_USB_SERIAL_DEBUG -static int debug = 1; -#else -static int debug; -#endif - -/* - * Version Information - */ -#define DRIVER_VERSION "v0.5" #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" -static struct usb_device_id id_table[] = { +static const struct usb_device_id id_table[] = { {USB_DEVICE(IUU_USB_VENDOR_ID, IUU_USB_PRODUCT_ID)}, {} /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, id_table); -static struct usb_driver iuu_driver = { - .name = "iuu_phoenix", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = id_table, - .no_dynamic_id = 1, -}; - /* turbo parameter */ static int boost = 100; static int clockmode = 1; static int cdmode = 1; static int iuu_cardin; static int iuu_cardout; -static int xmas; +static bool xmas; +static int vcc_default = 5; +static int iuu_create_sysfs_attrs(struct usb_serial_port *port); +static int iuu_remove_sysfs_attrs(struct usb_serial_port *port); static void read_rxcmd_callback(struct urb *urb); struct iuu_private { spinlock_t lock; /* store irq state */ - wait_queue_head_t delta_msr_wait; - u8 line_control; u8 line_status; - u8 termios_initialized; int tiostatus; /* store IUART SIGNAL for tiocmget call */ u8 reset; /* if 1 reset is needed */ int poll; /* number of poll */ u8 *writebuf; /* buffer for writing to device */ int writelen; /* num of byte to write to device */ u8 *buf; /* used for initialize speed */ - u8 *dbgbuf; /* debug buffer */ u8 len; + int vcc; /* vcc (either 3 or 5 V) */ + u32 baud; + u32 boost; + u32 clk; }; - -static void iuu_free_buf(struct iuu_private *priv) +static int iuu_port_probe(struct usb_serial_port *port) { - kfree(priv->buf); - kfree(priv->dbgbuf); - kfree(priv->writebuf); -} + struct iuu_private *priv; + int ret; + + priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; -static int iuu_alloc_buf(struct iuu_private *priv) -{ priv->buf = kzalloc(256, GFP_KERNEL); - priv->dbgbuf = kzalloc(256, GFP_KERNEL); - priv->writebuf = kzalloc(256, GFP_KERNEL); - if (!priv->buf || !priv->dbgbuf || !priv->writebuf) { - iuu_free_buf(priv); - dbg("%s problem allocation buffer", __FUNCTION__); + if (!priv->buf) { + kfree(priv); return -ENOMEM; } - dbg("%s - Privates buffers allocation success", __FUNCTION__); - return 0; -} -static int iuu_startup(struct usb_serial *serial) -{ - struct iuu_private *priv; - priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL); - dbg("%s- priv allocation success", __FUNCTION__); - if (!priv) - return -ENOMEM; - if (iuu_alloc_buf(priv)) { + priv->writebuf = kzalloc(256, GFP_KERNEL); + if (!priv->writebuf) { + kfree(priv->buf); kfree(priv); return -ENOMEM; } + + priv->vcc = vcc_default; spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); - usb_set_serial_port_data(serial->port[0], priv); + + usb_set_serial_port_data(port, priv); + + ret = iuu_create_sysfs_attrs(port); + if (ret) { + kfree(priv->writebuf); + kfree(priv->buf); + kfree(priv); + return ret; + } + return 0; } -/* Shutdown function */ -static void iuu_shutdown(struct usb_serial *serial) +static int iuu_port_remove(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct iuu_private *priv = usb_get_serial_port_data(port); - if (!port) - return; - - dbg("%s", __FUNCTION__); - - if (priv) { - iuu_free_buf(priv); - dbg("%s - I will free all", __FUNCTION__); - usb_set_serial_port_data(port, NULL); - dbg("%s - priv is not anymore in port structure", __FUNCTION__); - kfree(priv); + iuu_remove_sysfs_attrs(port); + kfree(priv->writebuf); + kfree(priv->buf); + kfree(priv); - dbg("%s priv is now kfree", __FUNCTION__); - } + return 0; } -static int iuu_tiocmset(struct usb_serial_port *port, struct file *file, +static int iuu_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct iuu_private *priv = usb_get_serial_port_data(port); - struct tty_struct *tty; - tty = port->tty; + unsigned long flags; - dbg("%s (%d) msg : SET = 0x%04x, CLEAR = 0x%04x ", __FUNCTION__, - port->number, set, clear); - if (set & TIOCM_RTS) - priv->tiostatus = TIOCM_RTS; + /* FIXME: locking on tiomstatus */ + dev_dbg(&port->dev, "%s msg : SET = 0x%04x, CLEAR = 0x%04x\n", + __func__, set, clear); - if (!(set & TIOCM_RTS) && priv->tiostatus == TIOCM_RTS) { - dbg("%s TIOCMSET RESET called !!!", __FUNCTION__); + spin_lock_irqsave(&priv->lock, flags); + + if ((set & TIOCM_RTS) && !(priv->tiostatus == TIOCM_RTS)) { + dev_dbg(&port->dev, "%s TIOCMSET RESET called !!!\n", __func__); priv->reset = 1; - return 0; } + if (set & TIOCM_RTS) + priv->tiostatus = TIOCM_RTS; + spin_unlock_irqrestore(&priv->lock, flags); return 0; } @@ -170,20 +147,28 @@ static int iuu_tiocmset(struct usb_serial_port *port, struct file *file, * When no card , the reader respond with TIOCM_CD * This is known as CD autodetect mechanism */ -static int iuu_tiocmget(struct usb_serial_port *port, struct file *file) +static int iuu_tiocmget(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct iuu_private *priv = usb_get_serial_port_data(port); - return priv->tiostatus; + unsigned long flags; + int rc; + + spin_lock_irqsave(&priv->lock, flags); + rc = priv->tiostatus; + spin_unlock_irqrestore(&priv->lock, flags); + + return rc; } static void iuu_rxcmd(struct urb *urb) { - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial_port *port = urb->context; int result; - dbg("%s - enter", __FUNCTION__); + int status = urb->status; - if (urb->status) { - dbg("%s - urb->status = %d", __FUNCTION__, urb->status); + if (status) { + dev_dbg(&port->dev, "%s - status = %d\n", __func__, status); /* error stop all */ return; } @@ -203,7 +188,6 @@ static int iuu_reset(struct usb_serial_port *port, u8 wt) struct iuu_private *priv = usb_get_serial_port_data(port); int result; char *buf_ptr = port->write_urb->transfer_buffer; - dbg("%s - enter", __FUNCTION__); /* Prepare the reset sequence */ @@ -232,19 +216,19 @@ static int iuu_reset(struct usb_serial_port *port, u8 wt) */ static void iuu_update_status_callback(struct urb *urb) { - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial_port *port = urb->context; struct iuu_private *priv = usb_get_serial_port_data(port); u8 *st; - dbg("%s - enter", __FUNCTION__); + int status = urb->status; - if (urb->status) { - dbg("%s - urb->status = %d", __FUNCTION__, urb->status); + if (status) { + dev_dbg(&port->dev, "%s - status = %d\n", __func__, status); /* error stop all */ return; } st = urb->transfer_buffer; - dbg("%s - enter", __FUNCTION__); + dev_dbg(&port->dev, "%s - enter\n", __func__); if (urb->actual_length == 1) { switch (st[0]) { case 0x1: @@ -262,11 +246,11 @@ static void iuu_update_status_callback(struct urb *urb) static void iuu_status_callback(struct urb *urb) { - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial_port *port = urb->context; int result; - dbg("%s - enter", __FUNCTION__); + int status = urb->status; - dbg("%s - urb->status = %d", __FUNCTION__, urb->status); + dev_dbg(&port->dev, "%s - status = %d\n", __func__, status); usb_fill_bulk_urb(port->read_urb, port->serial->dev, usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), @@ -279,8 +263,6 @@ static int iuu_status(struct usb_serial_port *port) { int result; - dbg("%s - enter", __FUNCTION__); - memset(port->write_urb->transfer_buffer, IUU_GET_STATE_REGISTER, 1); usb_fill_bulk_urb(port->write_urb, port->serial->dev, usb_sndbulkpipe(port->serial->dev, @@ -298,21 +280,18 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count) struct usb_serial *serial = port->serial; int actual = 0; - dbg("%s - enter", __FUNCTION__); - /* send the data out the bulk port */ status = usb_bulk_msg(serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), buf, - count, &actual, HZ * 1); + count, &actual, 1000); - if (status != IUU_OPERATION_OK) { - dbg("%s - error = %2x", __FUNCTION__, status); - } else { - dbg("%s - write OK !", __FUNCTION__); - } + if (status != IUU_OPERATION_OK) + dev_dbg(&port->dev, "%s - error = %2x\n", __func__, status); + else + dev_dbg(&port->dev, "%s - write OK !\n", __func__); return status; } @@ -322,22 +301,17 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count) struct usb_serial *serial = port->serial; int actual = 0; - dbg("%s - enter", __FUNCTION__); - /* send the data out the bulk port */ - status = usb_bulk_msg(serial->dev, usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), buf, - count, &actual, HZ * 1); - - if (status != IUU_OPERATION_OK) { - dbg("%s - error = %2x", __FUNCTION__, status); - } else { - dbg("%s - read OK !", __FUNCTION__); - } + count, &actual, 1000); + if (status != IUU_OPERATION_OK) + dev_dbg(&port->dev, "%s - error = %2x\n", __func__, status); + else + dev_dbg(&port->dev, "%s - read OK !\n", __func__); return status; } @@ -350,8 +324,6 @@ static int iuu_led(struct usb_serial_port *port, unsigned int R, if (!buf) return -ENOMEM; - dbg("%s - enter", __FUNCTION__); - buf[0] = IUU_SET_LED; buf[1] = R & 0xFF; buf[2] = (R >> 8) & 0xFF; @@ -363,9 +335,9 @@ static int iuu_led(struct usb_serial_port *port, unsigned int R, status = bulk_immediate(port, buf, 8); kfree(buf); if (status != IUU_OPERATION_OK) - dbg("%s - led error status = %2x", __FUNCTION__, status); + dev_dbg(&port->dev, "%s - led error status = %2x\n", __func__, status); else - dbg("%s - led OK !", __FUNCTION__); + dev_dbg(&port->dev, "%s - led OK !\n", __func__); return IUU_OPERATION_OK; } @@ -384,7 +356,7 @@ static void iuu_rgbf_fill_buffer(u8 *buf, u8 r1, u8 r2, u8 g1, u8 g2, u8 b1, static void iuu_led_activity_on(struct urb *urb) { - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial_port *port = urb->context; int result; char *buf_ptr = port->write_urb->transfer_buffer; *buf_ptr++ = IUU_SET_LED; @@ -405,7 +377,7 @@ static void iuu_led_activity_on(struct urb *urb) static void iuu_led_activity_off(struct urb *urb) { - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial_port *port = urb->context; int result; char *buf_ptr = port->write_urb->transfer_buffer; if (xmas == 1) { @@ -443,8 +415,6 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq) unsigned int P2 = 0; int frq = (int)dwFrq; - dbg("%s - enter", __FUNCTION__); - if (frq == 0) { priv->buf[Count++] = IUU_UART_WRITE_I2C; priv->buf[Count++] = FrqGenAdr << 1; @@ -453,7 +423,7 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq) status = bulk_immediate(port, (u8 *) priv->buf, Count); if (status != 0) { - dbg("%s - write error ", __FUNCTION__); + dev_dbg(&port->dev, "%s - write error\n", __func__); return status; } } else if (frq == 3579000) { @@ -562,72 +532,67 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq) status = bulk_immediate(port, (u8 *) priv->buf, Count); if (status != IUU_OPERATION_OK) - dbg("%s - write error ", __FUNCTION__); + dev_dbg(&port->dev, "%s - write error\n", __func__); return status; } static int iuu_uart_flush(struct usb_serial_port *port) { + struct device *dev = &port->dev; int i; int status; u8 rxcmd = IUU_UART_RX; struct iuu_private *priv = usb_get_serial_port_data(port); - dbg("%s - enter", __FUNCTION__); - if (iuu_led(port, 0xF000, 0, 0, 0xFF) < 0) return -EIO; for (i = 0; i < 2; i++) { status = bulk_immediate(port, &rxcmd, 1); if (status != IUU_OPERATION_OK) { - dbg("%s - uart_flush_write error", __FUNCTION__); + dev_dbg(dev, "%s - uart_flush_write error\n", __func__); return status; } status = read_immediate(port, &priv->len, 1); if (status != IUU_OPERATION_OK) { - dbg("%s - uart_flush_read error", __FUNCTION__); + dev_dbg(dev, "%s - uart_flush_read error\n", __func__); return status; } if (priv->len > 0) { - dbg("%s - uart_flush datalen is : %i ", __FUNCTION__, - priv->len); + dev_dbg(dev, "%s - uart_flush datalen is : %i\n", __func__, priv->len); status = read_immediate(port, priv->buf, priv->len); if (status != IUU_OPERATION_OK) { - dbg("%s - uart_flush_read error", __FUNCTION__); + dev_dbg(dev, "%s - uart_flush_read error\n", __func__); return status; } } } - dbg("%s - uart_flush_read OK!", __FUNCTION__); + dev_dbg(dev, "%s - uart_flush_read OK!\n", __func__); iuu_led(port, 0, 0xF000, 0, 0xFF); return status; } static void read_buf_callback(struct urb *urb) { - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial_port *port = urb->context; unsigned char *data = urb->transfer_buffer; - struct tty_struct *tty; - dbg("%s - urb->status = %d", __FUNCTION__, urb->status); + int status = urb->status; - if (urb->status) { - dbg("%s - urb->status = %d", __FUNCTION__, urb->status); - if (urb->status == -EPROTO) { + if (status) { + if (status == -EPROTO) { /* reschedule needed */ } return; } - dbg("%s - %i chars to write", __FUNCTION__, urb->actual_length); - tty = port->tty; + dev_dbg(&port->dev, "%s - %i chars to write\n", __func__, urb->actual_length); if (data == NULL) - dbg("%s - data is NULL !!!", __FUNCTION__); - if (tty && urb->actual_length && data) { - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); + dev_dbg(&port->dev, "%s - data is NULL !!!\n", __func__); + if (urb->actual_length && data) { + tty_insert_flip_string(&port->port, data, urb->actual_length); + tty_flip_buffer_push(&port->port); } iuu_led_activity_on(urb); } @@ -635,35 +600,28 @@ static void read_buf_callback(struct urb *urb) static int iuu_bulk_write(struct usb_serial_port *port) { struct iuu_private *priv = usb_get_serial_port_data(port); - unsigned int flags; + unsigned long flags; int result; - int i; + int buf_len; char *buf_ptr = port->write_urb->transfer_buffer; - dbg("%s - enter", __FUNCTION__); + spin_lock_irqsave(&priv->lock, flags); *buf_ptr++ = IUU_UART_ESC; *buf_ptr++ = IUU_UART_TX; *buf_ptr++ = priv->writelen; - memcpy(buf_ptr, priv->writebuf, - priv->writelen); - if (debug == 1) { - for (i = 0; i < priv->writelen; i++) - sprintf(priv->dbgbuf + i*2 , - "%02X", priv->writebuf[i]); - priv->dbgbuf[priv->writelen+i*2] = 0; - dbg("%s - writing %i chars : %s", __FUNCTION__, - priv->writelen, priv->dbgbuf); - } + memcpy(buf_ptr, priv->writebuf, priv->writelen); + buf_len = priv->writelen; + priv->writelen = 0; + spin_unlock_irqrestore(&priv->lock, flags); + dev_dbg(&port->dev, "%s - writing %i chars : %*ph\n", __func__, + buf_len, buf_len, buf_ptr); usb_fill_bulk_urb(port->write_urb, port->serial->dev, usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress), - port->write_urb->transfer_buffer, priv->writelen + 3, + port->write_urb->transfer_buffer, buf_len + 3, iuu_rxcmd, port); result = usb_submit_urb(port->write_urb, GFP_ATOMIC); - spin_lock_irqsave(&priv->lock, flags); - priv->writelen = 0; - spin_unlock_irqrestore(&priv->lock, flags); usb_serial_port_softint(port); return result; } @@ -671,7 +629,6 @@ static int iuu_bulk_write(struct usb_serial_port *port) static int iuu_read_buf(struct usb_serial_port *port, int len) { int result; - dbg("%s - enter", __FUNCTION__); usb_fill_bulk_urb(port->read_urb, port->serial->dev, usb_rcvbulkpipe(port->serial->dev, @@ -684,30 +641,28 @@ static int iuu_read_buf(struct usb_serial_port *port, int len) static void iuu_uart_read_callback(struct urb *urb) { - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial_port *port = urb->context; struct iuu_private *priv = usb_get_serial_port_data(port); - unsigned int flags; - int status; + unsigned long flags; + int status = urb->status; int error = 0; int len = 0; unsigned char *data = urb->transfer_buffer; priv->poll++; - dbg("%s - enter", __FUNCTION__); - - if (urb->status) { - dbg("%s - urb->status = %d", __FUNCTION__, urb->status); + if (status) { + dev_dbg(&port->dev, "%s - status = %d\n", __func__, status); /* error stop all */ return; } if (data == NULL) - dbg("%s - data is NULL !!!", __FUNCTION__); + dev_dbg(&port->dev, "%s - data is NULL !!!\n", __func__); if (urb->actual_length == 1 && data != NULL) len = (int) data[0]; if (urb->actual_length > 1) { - dbg("%s - urb->actual_length = %i", __FUNCTION__, + dev_dbg(&port->dev, "%s - urb->actual_length = %i\n", __func__, urb->actual_length); error = 1; return; @@ -715,8 +670,8 @@ static void iuu_uart_read_callback(struct urb *urb) /* if len > 0 call readbuf */ if (len > 0 && error == 0) { - dbg("%s - call read buf - len to read is %i ", - __FUNCTION__, len); + dev_dbg(&port->dev, "%s - call read buf - len to read is %i\n", + __func__, len); status = iuu_read_buf(port, len); return; } @@ -742,45 +697,36 @@ static void iuu_uart_read_callback(struct urb *urb) } spin_unlock_irqrestore(&priv->lock, flags); /* if nothing to write call again rxcmd */ - dbg("%s - rxcmd recall", __FUNCTION__); + dev_dbg(&port->dev, "%s - rxcmd recall\n", __func__); iuu_led_activity_off(urb); - return; } -static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf, - int count) +static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port, + const u8 *buf, int count) { struct iuu_private *priv = usb_get_serial_port_data(port); - unsigned int flags; - dbg("%s - enter", __FUNCTION__); + unsigned long flags; if (count > 256) return -ENOMEM; spin_lock_irqsave(&priv->lock, flags); - if (priv->writelen > 0) { - /* buffer already filled but not commited */ - spin_unlock_irqrestore(&priv->lock, flags); - return (0); - } + /* fill the buffer */ - memcpy(priv->writebuf, buf, count); - priv->writelen = count; + memcpy(priv->writebuf + priv->writelen, buf, count); + priv->writelen += count; spin_unlock_irqrestore(&priv->lock, flags); - return (count); + return count; } static void read_rxcmd_callback(struct urb *urb) { - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial_port *port = urb->context; int result; - dbg("%s - enter", __FUNCTION__); + int status = urb->status; - dbg("%s - urb->status = %d", __FUNCTION__, urb->status); - - if (urb->status) { - dbg("%s - urb->status = %d", __FUNCTION__, urb->status); + if (status) { /* error stop all */ return; } @@ -791,8 +737,7 @@ static void read_rxcmd_callback(struct urb *urb) port->read_urb->transfer_buffer, 256, iuu_uart_read_callback, port); result = usb_submit_urb(port->read_urb, GFP_ATOMIC); - dbg("%s - submit result = %d", __FUNCTION__, result); - return; + dev_dbg(&port->dev, "%s - submit result = %d\n", __func__, result); } static int iuu_uart_on(struct usb_serial_port *port) @@ -808,23 +753,23 @@ static int iuu_uart_on(struct usb_serial_port *port) buf[0] = IUU_UART_ENABLE; buf[1] = (u8) ((IUU_BAUD_9600 >> 8) & 0x00FF); buf[2] = (u8) (0x00FF & IUU_BAUD_9600); - buf[3] = (u8) (0x0F0 & IUU_TWO_STOP_BITS) | (0x07 & IUU_PARITY_EVEN); + buf[3] = (u8) (0x0F0 & IUU_ONE_STOP_BIT) | (0x07 & IUU_PARITY_EVEN); status = bulk_immediate(port, buf, 4); if (status != IUU_OPERATION_OK) { - dbg("%s - uart_on error", __FUNCTION__); + dev_dbg(&port->dev, "%s - uart_on error\n", __func__); goto uart_enable_failed; } /* iuu_reset() the card after iuu_uart_on() */ status = iuu_uart_flush(port); if (status != IUU_OPERATION_OK) - dbg("%s - uart_flush error", __FUNCTION__); + dev_dbg(&port->dev, "%s - uart_flush error\n", __func__); uart_enable_failed: kfree(buf); return status; } -/* Diables the IUU UART (a.k.a. the Phoenix voiderface) */ +/* Disables the IUU UART (a.k.a. the Phoenix voiderface) */ static int iuu_uart_off(struct usb_serial_port *port) { int status; @@ -836,26 +781,30 @@ static int iuu_uart_off(struct usb_serial_port *port) status = bulk_immediate(port, buf, 1); if (status != IUU_OPERATION_OK) - dbg("%s - uart_off error", __FUNCTION__); + dev_dbg(&port->dev, "%s - uart_off error\n", __func__); kfree(buf); return status; } -static int iuu_uart_baud(struct usb_serial_port *port, u32 baud, +static int iuu_uart_baud(struct usb_serial_port *port, u32 baud_base, u32 *actual, u8 parity) { int status; + u32 baud; u8 *dataout; u8 DataCount = 0; u8 T1Frekvens = 0; u8 T1reload = 0; unsigned int T1FrekvensHZ = 0; + dev_dbg(&port->dev, "%s - enter baud_base=%d\n", __func__, baud_base); dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL); if (!dataout) return -ENOMEM; + /*baud = (((priv->clk / 35) * baud_base) / 100000); */ + baud = baud_base; if (baud < 1200 || baud > 230400) { kfree(dataout); @@ -930,67 +879,105 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud, status = bulk_immediate(port, dataout, DataCount); if (status != IUU_OPERATION_OK) - dbg("%s - uart_off error", __FUNCTION__); + dev_dbg(&port->dev, "%s - uart_off error\n", __func__); kfree(dataout); return status; } -static int set_control_lines(struct usb_device *dev, u8 value) +static void iuu_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { - return 0; + const u32 supported_mask = CMSPAR|PARENB|PARODD; + struct iuu_private *priv = usb_get_serial_port_data(port); + unsigned int cflag = tty->termios.c_cflag; + int status; + u32 actual; + u32 parity; + int csize = CS7; + int baud; + u32 newval = cflag & supported_mask; + + /* Just use the ospeed. ispeed should be the same. */ + baud = tty->termios.c_ospeed; + + dev_dbg(&port->dev, "%s - enter c_ospeed or baud=%d\n", __func__, baud); + + /* compute the parity parameter */ + parity = 0; + if (cflag & CMSPAR) { /* Using mark space */ + if (cflag & PARODD) + parity |= IUU_PARITY_SPACE; + else + parity |= IUU_PARITY_MARK; + } else if (!(cflag & PARENB)) { + parity |= IUU_PARITY_NONE; + csize = CS8; + } else if (cflag & PARODD) + parity |= IUU_PARITY_ODD; + else + parity |= IUU_PARITY_EVEN; + + parity |= (cflag & CSTOPB ? IUU_TWO_STOP_BITS : IUU_ONE_STOP_BIT); + + /* set it */ + status = iuu_uart_baud(port, + baud * priv->boost / 100, + &actual, parity); + + /* set the termios value to the real one, so the user now what has + * changed. We support few fields so its easies to copy the old hw + * settings back over and then adjust them + */ + if (old_termios) + tty_termios_copy_hw(&tty->termios, old_termios); + if (status != 0) /* Set failed - return old bits */ + return; + /* Re-encode speed, parity and csize */ + tty_encode_baud_rate(tty, baud, baud); + tty->termios.c_cflag &= ~(supported_mask|CSIZE); + tty->termios.c_cflag |= newval | csize; } -static void iuu_close(struct usb_serial_port *port, struct file *filp) +static void iuu_close(struct usb_serial_port *port) { /* iuu_led (port,255,0,0,0); */ - struct usb_serial *serial; - struct iuu_private *priv = usb_get_serial_port_data(port); - unsigned long flags; - unsigned int c_cflag; - serial = port->serial; - if (!serial) - return; + iuu_uart_off(port); - dbg("%s - port %d", __FUNCTION__, port->number); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); - iuu_uart_off(port); - if (serial->dev) { - if (port->tty) { - c_cflag = port->tty->termios->c_cflag; - if (c_cflag & HUPCL) { - /* drop DTR and RTS */ - priv = usb_get_serial_port_data(port); - spin_lock_irqsave(&priv->lock, flags); - priv->line_control = 0; - spin_unlock_irqrestore(&priv->lock, flags); - set_control_lines(port->serial->dev, 0); - } - } - /* free writebuf */ - /* shutdown our urbs */ - dbg("%s - shutting down urbs", __FUNCTION__); - usb_kill_urb(port->write_urb); - usb_kill_urb(port->read_urb); - usb_kill_urb(port->interrupt_in_urb); - msleep(1000); - /* wait one second to free all buffers */ - iuu_led(port, 0, 0, 0xF000, 0xFF); - msleep(1000); - usb_reset_device(port->serial->dev); - } + iuu_led(port, 0, 0, 0xF000, 0xFF); +} + +static void iuu_init_termios(struct tty_struct *tty) +{ + tty->termios = tty_std_termios; + tty->termios.c_cflag = CLOCAL | CREAD | CS8 | B9600 + | TIOCM_CTS | CSTOPB | PARENB; + tty->termios.c_ispeed = 9600; + tty->termios.c_ospeed = 9600; + tty->termios.c_lflag = 0; + tty->termios.c_oflag = 0; + tty->termios.c_iflag = 0; } -static int iuu_open(struct usb_serial_port *port, struct file *filp) +static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) { struct usb_serial *serial = port->serial; + struct device *dev = &port->dev; u8 *buf; int result; + int baud; u32 actual; - unsigned long flags; struct iuu_private *priv = usb_get_serial_port_data(port); - dbg("%s - port %d", __FUNCTION__, port->number); + baud = tty->termios.c_ospeed; + tty->termios.c_ispeed = baud; + /* Re-encode speed */ + tty_encode_baud_rate(tty, baud, baud); + + dev_dbg(dev, "%s - baud %d\n", __func__, baud); usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); @@ -998,62 +985,21 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp) if (buf == NULL) return -ENOMEM; - /* fixup the endpoint buffer size */ - kfree(port->bulk_out_buffer); - port->bulk_out_buffer = kmalloc(512, GFP_KERNEL); - port->bulk_out_size = 512; - kfree(port->bulk_in_buffer); - port->bulk_in_buffer = kmalloc(512, GFP_KERNEL); - port->bulk_in_size = 512; - - if (!port->bulk_out_buffer || !port->bulk_in_buffer) { - kfree(port->bulk_out_buffer); - kfree(port->bulk_in_buffer); - kfree(buf); - return -ENOMEM; - } - - usb_fill_bulk_urb(port->write_urb, port->serial->dev, - usb_sndbulkpipe(port->serial->dev, - port->bulk_out_endpointAddress), - port->bulk_out_buffer, 512, - NULL, NULL); - - - usb_fill_bulk_urb(port->read_urb, port->serial->dev, - usb_rcvbulkpipe(port->serial->dev, - port->bulk_in_endpointAddress), - port->bulk_in_buffer, 512, - NULL, NULL); - - /* set the termios structure */ - spin_lock_irqsave(&priv->lock, flags); - if (!priv->termios_initialized) { - *(port->tty->termios) = tty_std_termios; - port->tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600 - | TIOCM_CTS | CSTOPB | PARENB; - port->tty->termios->c_lflag = 0; - port->tty->termios->c_oflag = 0; - port->tty->termios->c_iflag = 0; - priv->termios_initialized = 1; - port->tty->low_latency = 1; - priv->poll = 0; - } - spin_unlock_irqrestore(&priv->lock, flags); + priv->poll = 0; /* initialize writebuf */ #define FISH(a, b, c, d) do { \ result = usb_control_msg(port->serial->dev, \ usb_rcvctrlpipe(port->serial->dev, 0), \ b, a, c, d, buf, 1, 1000); \ - dbg("0x%x:0x%x:0x%x:0x%x %d - %x", a, b, c, d, result, \ + dev_dbg(dev, "0x%x:0x%x:0x%x:0x%x %d - %x\n", a, b, c, d, result, \ buf[0]); } while (0); #define SOUP(a, b, c, d) do { \ result = usb_control_msg(port->serial->dev, \ usb_sndctrlpipe(port->serial->dev, 0), \ b, a, c, d, NULL, 0, 1000); \ - dbg("0x%x:0x%x:0x%x:0x%x %d", a, b, c, d, result); } while (0) + dev_dbg(dev, "0x%x:0x%x:0x%x:0x%x %d\n", a, b, c, d, result); } while (0) /* This is not UART related but IUU USB driver related or something */ /* like that. Basically no IUU will accept any commands from the USB */ @@ -1066,23 +1012,29 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp) iuu_uart_on(port); if (boost < 100) boost = 100; + priv->boost = boost; + priv->baud = baud; switch (clockmode) { case 2: /* 3.680 Mhz */ + priv->clk = IUU_CLK_3680000; iuu_clk(port, IUU_CLK_3680000 * boost / 100); result = - iuu_uart_baud(port, 9600 * boost / 100, &actual, + iuu_uart_baud(port, baud * boost / 100, &actual, IUU_PARITY_EVEN); break; case 3: /* 6.00 Mhz */ iuu_clk(port, IUU_CLK_6000000 * boost / 100); + priv->clk = IUU_CLK_6000000; + /* Ratio of 6000000 to 3500000 for baud 9600 */ result = iuu_uart_baud(port, 16457 * boost / 100, &actual, IUU_PARITY_EVEN); break; default: /* 3.579 Mhz */ iuu_clk(port, IUU_CLK_3579000 * boost / 100); + priv->clk = IUU_CLK_3579000; result = - iuu_uart_baud(port, 9600 * boost / 100, &actual, + iuu_uart_baud(port, baud * boost / 100, &actual, IUU_PARITY_EVEN); } @@ -1127,7 +1079,7 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp) iuu_uart_flush(port); - dbg("%s - initialization done", __FUNCTION__); + dev_dbg(dev, "%s - initialization done\n", __func__); memset(port->write_urb->transfer_buffer, IUU_UART_RX, 1); usb_fill_bulk_urb(port->write_urb, port->serial->dev, @@ -1136,82 +1088,143 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp) port->write_urb->transfer_buffer, 1, read_rxcmd_callback, port); result = usb_submit_urb(port->write_urb, GFP_KERNEL); - if (result) { - dev_err(&port->dev, "%s - failed submitting read urb," - " error %d\n", __FUNCTION__, result); - iuu_close(port, NULL); - return -EPROTO; + dev_err(dev, "%s - failed submitting read urb, error %d\n", __func__, result); + iuu_close(port); } else { - dbg("%s - rxcmd OK", __FUNCTION__); + dev_dbg(dev, "%s - rxcmd OK\n", __func__); } + return result; } +/* how to change VCC */ +static int iuu_vcc_set(struct usb_serial_port *port, unsigned int vcc) +{ + int status; + u8 *buf; + + buf = kmalloc(5, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + buf[0] = IUU_SET_VCC; + buf[1] = vcc & 0xFF; + buf[2] = (vcc >> 8) & 0xFF; + buf[3] = (vcc >> 16) & 0xFF; + buf[4] = (vcc >> 24) & 0xFF; + + status = bulk_immediate(port, buf, 5); + kfree(buf); + + if (status != IUU_OPERATION_OK) + dev_dbg(&port->dev, "%s - vcc error status = %2x\n", __func__, status); + else + dev_dbg(&port->dev, "%s - vcc OK !\n", __func__); + + return status; +} + +/* + * Sysfs Attributes + */ + +static ssize_t vcc_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_serial_port *port = to_usb_serial_port(dev); + struct iuu_private *priv = usb_get_serial_port_data(port); + + return sprintf(buf, "%d\n", priv->vcc); +} + +static ssize_t vcc_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct usb_serial_port *port = to_usb_serial_port(dev); + struct iuu_private *priv = usb_get_serial_port_data(port); + unsigned long v; + + if (kstrtoul(buf, 10, &v)) { + dev_err(dev, "%s - vcc_mode: %s is not a unsigned long\n", + __func__, buf); + goto fail_store_vcc_mode; + } + + dev_dbg(dev, "%s: setting vcc_mode = %ld\n", __func__, v); + + if ((v != 3) && (v != 5)) { + dev_err(dev, "%s - vcc_mode %ld is invalid\n", __func__, v); + } else { + iuu_vcc_set(port, v); + priv->vcc = v; + } +fail_store_vcc_mode: + return count; +} +static DEVICE_ATTR_RW(vcc_mode); + +static int iuu_create_sysfs_attrs(struct usb_serial_port *port) +{ + return device_create_file(&port->dev, &dev_attr_vcc_mode); +} + +static int iuu_remove_sysfs_attrs(struct usb_serial_port *port) +{ + device_remove_file(&port->dev, &dev_attr_vcc_mode); + return 0; +} + +/* + * End Sysfs Attributes + */ + static struct usb_serial_driver iuu_device = { .driver = { .owner = THIS_MODULE, .name = "iuu_phoenix", }, .id_table = id_table, - .num_interrupt_in = NUM_DONT_CARE, - .num_bulk_in = 1, - .num_bulk_out = 1, .num_ports = 1, + .bulk_in_size = 512, + .bulk_out_size = 512, .open = iuu_open, .close = iuu_close, .write = iuu_uart_write, .read_bulk_callback = iuu_uart_read_callback, .tiocmget = iuu_tiocmget, .tiocmset = iuu_tiocmset, - .attach = iuu_startup, - .shutdown = iuu_shutdown, + .set_termios = iuu_set_termios, + .init_termios = iuu_init_termios, + .port_probe = iuu_port_probe, + .port_remove = iuu_port_remove, }; -static int __init iuu_init(void) -{ - int retval; - retval = usb_serial_register(&iuu_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&iuu_driver); - if (retval) - goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); - return 0; -failed_usb_register: - usb_serial_deregister(&iuu_device); -failed_usb_serial_register: - return retval; -} - -static void __exit iuu_exit(void) -{ - usb_deregister(&iuu_driver); - usb_serial_deregister(&iuu_device); -} +static struct usb_serial_driver * const serial_drivers[] = { + &iuu_device, NULL +}; -module_init(iuu_init); -module_exit(iuu_exit); +module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR("Alain Degreffe eczema@ecze.com"); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRIVER_VERSION); -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - module_param(xmas, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(xmas, "xmas color enabled or not"); +MODULE_PARM_DESC(xmas, "Xmas colors enabled or not"); module_param(boost, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(boost, "overclock boost percent 100 to 500"); +MODULE_PARM_DESC(boost, "Card overclock boost (in percent 100-500)"); module_param(clockmode, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(clockmode, "1=3Mhz579,2=3Mhz680,3=6Mhz"); +MODULE_PARM_DESC(clockmode, "Card clock mode (1=3.579 MHz, 2=3.680 MHz, " + "3=6 Mhz)"); module_param(cdmode, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(cdmode, "Card detect mode 0=none, 1=CD, 2=!CD, 3=DSR, " - "4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING"); +MODULE_PARM_DESC(cdmode, "Card detect mode (0=none, 1=CD, 2=!CD, 3=DSR, " + "4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING)"); + +module_param(vcc_default, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(vcc_default, "Set default VCC (either 3 for 3.3V or 5 " + "for 5V). Default to 5."); |
