*
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/usb.h>
#include <linux/serial_reg.h>
#include <linux/serial.h>
-
-#ifdef CONFIG_USB_SERIAL_DEBUG
- static int debug = 1;
-#else
- static int debug;
-#endif
-
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
#include "whiteheat_fw.h" /* firmware for the ConnectTech WhiteHEAT device */
#include "whiteheat.h" /* WhiteHEAT specific commands */
+static int debug;
+
#ifndef CMSPAR
#define CMSPAR 0
#endif
MODULE_DEVICE_TABLE (usb, id_table_combined);
static struct usb_driver whiteheat_driver = {
- .owner = THIS_MODULE,
.name = "whiteheat",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
+ .no_dynamic_id = 1,
};
/* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */
static void whiteheat_shutdown (struct usb_serial *serial);
static int whiteheat_open (struct usb_serial_port *port, struct file *filp);
static void whiteheat_close (struct usb_serial_port *port, struct file *filp);
-static int whiteheat_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+static int whiteheat_write (struct usb_serial_port *port, const unsigned char *buf, int count);
static int whiteheat_write_room (struct usb_serial_port *port);
static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void whiteheat_set_termios (struct usb_serial_port *port, struct termios * old);
+static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios * old);
static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file);
static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
static void whiteheat_break_ctl (struct usb_serial_port *port, int break_state);
static int whiteheat_chars_in_buffer (struct usb_serial_port *port);
static void whiteheat_throttle (struct usb_serial_port *port);
static void whiteheat_unthrottle (struct usb_serial_port *port);
-static void whiteheat_read_callback (struct urb *urb, struct pt_regs *regs);
-static void whiteheat_write_callback (struct urb *urb, struct pt_regs *regs);
-
-static struct usb_serial_device_type whiteheat_fake_device = {
- .owner = THIS_MODULE,
- .name = "Connect Tech - WhiteHEAT - (prerenumeration)",
- .short_name = "whiteheatnofirm",
+static void whiteheat_read_callback (struct urb *urb);
+static void whiteheat_write_callback (struct urb *urb);
+
+static struct usb_serial_driver whiteheat_fake_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "whiteheatnofirm",
+ },
+ .description = "Connect Tech - WhiteHEAT - (prerenumeration)",
.id_table = id_table_prerenumeration,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
.attach = whiteheat_firmware_attach,
};
-static struct usb_serial_device_type whiteheat_device = {
- .owner = THIS_MODULE,
- .name = "Connect Tech - WhiteHEAT",
- .short_name = "whiteheat",
+static struct usb_serial_driver whiteheat_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "whiteheat",
+ },
+ .description = "Connect Tech - WhiteHEAT",
.id_table = id_table_std,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
struct list_head rx_urbs_submitted;
struct list_head rx_urb_q;
struct work_struct rx_work;
+ struct usb_serial_port *port;
struct list_head tx_urbs_free;
struct list_head tx_urbs_submitted;
};
/* local function prototypes */
static int start_command_port(struct usb_serial *serial);
static void stop_command_port(struct usb_serial *serial);
-static void command_port_write_callback(struct urb *urb, struct pt_regs *regs);
-static void command_port_read_callback(struct urb *urb, struct pt_regs *regs);
+static void command_port_write_callback(struct urb *urb);
+static void command_port_read_callback(struct urb *urb);
static int start_port_read(struct usb_serial_port *port);
static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, struct list_head *head);
static struct list_head *list_first(struct list_head *head);
-static void rx_data_softint(void *private);
+static void rx_data_softint(struct work_struct *work);
static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize);
static int firm_open(struct usb_serial_port *port);
#define COMMAND_PORT 4
#define COMMAND_TIMEOUT (2*HZ) /* 2 second timeout for a command */
+#define COMMAND_TIMEOUT_MS 2000
#define CLOSING_DELAY (30 * HZ)
* unlinking bug in disguise. Same for the call below.
*/
usb_clear_halt(serial->dev, pipe);
- ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT);
+ ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT_MS);
if (ret) {
- err("%s: Couldn't send command [%d]", serial->type->name, ret);
+ err("%s: Couldn't send command [%d]", serial->type->description, ret);
goto no_firmware;
- } else if (alen != sizeof(command)) {
- err("%s: Send command incomplete [%d]", serial->type->name, alen);
+ } else if (alen != 2) {
+ err("%s: Send command incomplete [%d]", serial->type->description, alen);
goto no_firmware;
}
pipe = usb_rcvbulkpipe (serial->dev, command_port->bulk_in_endpointAddress);
/* See the comment on the usb_clear_halt() above */
usb_clear_halt(serial->dev, pipe);
- ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT);
+ ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS);
if (ret) {
- err("%s: Couldn't get results [%d]", serial->type->name, ret);
+ err("%s: Couldn't get results [%d]", serial->type->description, ret);
goto no_firmware;
- } else if (alen != sizeof(result)) {
- err("%s: Get results incomplete [%d]", serial->type->name, alen);
+ } else if (alen != sizeof(*hw_info) + 1) {
+ err("%s: Get results incomplete [%d]", serial->type->description, alen);
goto no_firmware;
} else if (result[0] != command[0]) {
- err("%s: Command failed [%d]", serial->type->name, result[0]);
+ err("%s: Command failed [%d]", serial->type->description, result[0]);
goto no_firmware;
}
hw_info = (struct whiteheat_hw_info *)&result[1];
- info("%s: Driver %s: Firmware v%d.%02d", serial->type->name,
+ info("%s: Driver %s: Firmware v%d.%02d", serial->type->description,
DRIVER_VERSION, hw_info->sw_major_rev, hw_info->sw_minor_rev);
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
- info = (struct whiteheat_private *)kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
+ info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
if (info == NULL) {
- err("%s: Out of memory for port structures\n", serial->type->name);
+ err("%s: Out of memory for port structures\n", serial->type->description);
goto no_private;
}
spin_lock_init(&info->lock);
info->flags = 0;
info->mcr = 0;
- INIT_WORK(&info->rx_work, rx_data_softint, port);
+ INIT_WORK(&info->rx_work, rx_data_softint);
+ info->port = port;
INIT_LIST_HEAD(&info->rx_urbs_free);
INIT_LIST_HEAD(&info->rx_urbs_submitted);
usb_set_serial_port_data(port, info);
}
- command_info = (struct whiteheat_command_private *)kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
+ command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
if (command_info == NULL) {
- err("%s: Out of memory for port structures\n", serial->type->name);
+ err("%s: Out of memory for port structures\n", serial->type->description);
goto no_command_private;
}
no_firmware:
/* Firmware likely not running */
- err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->name);
- err("%s: If the firmware is not running (status led not blinking)\n", serial->type->name);
- err("%s: please contact support@connecttech.com\n", serial->type->name);
+ err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->description);
+ err("%s: If the firmware is not running (status led not blinking)\n", serial->type->description);
+ err("%s: please contact support@connecttech.com\n", serial->type->description);
+ kfree(result);
return -ENODEV;
no_command_private:
static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
{
int retval = 0;
- struct termios old_term;
+ struct ktermios old_term;
dbg("%s - port %d", __FUNCTION__, port->number);
if (port->tty->driver->flush_buffer)
port->tty->driver->flush_buffer(port->tty);
- if (port->tty->ldisc.flush_buffer)
- port->tty->ldisc.flush_buffer(port->tty);
+ tty_ldisc_flush(port->tty);
firm_report_tx_done(port);
list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
urb = wrap->urb;
- usb_unlink_urb(urb);
- list_del(tmp);
- list_add(tmp, &info->rx_urbs_free);
- }
- list_for_each_safe(tmp, tmp2, &info->rx_urb_q) {
- list_del(tmp);
- list_add(tmp, &info->rx_urbs_free);
+ usb_kill_urb(urb);
+ list_move(tmp, &info->rx_urbs_free);
}
+ list_for_each_safe(tmp, tmp2, &info->rx_urb_q)
+ list_move(tmp, &info->rx_urbs_free);
+
list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) {
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
urb = wrap->urb;
- usb_unlink_urb(urb);
- list_del(tmp);
- list_add(tmp, &info->tx_urbs_free);
+ usb_kill_urb(urb);
+ list_move(tmp, &info->tx_urbs_free);
}
spin_unlock_irqrestore(&info->lock, flags);
}
-static int whiteheat_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
+static int whiteheat_write(struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
struct whiteheat_private *info = usb_get_serial_port_data(port);
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
urb = wrap->urb;
bytes = (count > port->bulk_out_size) ? port->bulk_out_size : count;
- if (from_user) {
- if (copy_from_user(urb->transfer_buffer, buf + sent, bytes))
- return -EFAULT;
- } else {
- memcpy (urb->transfer_buffer, buf + sent, bytes);
- }
+ memcpy (urb->transfer_buffer, buf + sent, bytes);
- usb_serial_debug_data (__FILE__, __FUNCTION__, bytes, urb->transfer_buffer);
+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, bytes, urb->transfer_buffer);
urb->dev = serial->dev;
urb->transfer_buffer_length = bytes;
}
-static void whiteheat_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
dbg("%s -port %d", __FUNCTION__, port->number);
spin_unlock_irqrestore(&info->lock, flags);
if (actually_throttled)
- rx_data_softint(port);
+ rx_data_softint(&info->rx_work);
return;
}
/*****************************************************************************
* Connect Tech's White Heat callback routines
*****************************************************************************/
-static void command_port_write_callback (struct urb *urb, struct pt_regs *regs)
+static void command_port_write_callback (struct urb *urb)
{
dbg("%s", __FUNCTION__);
dbg ("nonzero urb status: %d", urb->status);
return;
}
-
- usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
-
- return;
}
-static void command_port_read_callback (struct urb *urb, struct pt_regs *regs)
+static void command_port_read_callback (struct urb *urb)
{
struct usb_serial_port *command_port = (struct usb_serial_port *)urb->context;
struct whiteheat_command_private *command_info;
return;
}
- usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &command_port->dev, __FUNCTION__, urb->actual_length, data);
command_info = usb_get_serial_port_data(command_port);
if (!command_info) {
}
-static void whiteheat_read_callback(struct urb *urb, struct pt_regs *regs)
+static void whiteheat_read_callback(struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct whiteheat_urb_wrap *wrap;
return;
}
- usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
spin_lock(&info->lock);
list_add_tail(&wrap->list, &info->rx_urb_q);
}
-static void whiteheat_write_callback(struct urb *urb, struct pt_regs *regs)
+static void whiteheat_write_callback(struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct whiteheat_private *info = usb_get_serial_port_data(port);
err("%s - Not my urb!", __FUNCTION__);
return;
}
- list_del(&wrap->list);
- list_add(&wrap->list, &info->tx_urbs_free);
+ list_move(&wrap->list, &info->tx_urbs_free);
spin_unlock(&info->lock);
if (urb->status) {
return;
}
- usb_serial_port_softint((void *)port);
-
- schedule_work(&port->work);
+ usb_serial_port_softint(port);
}
command_port->write_urb->transfer_buffer_length = datasize + 1;
command_port->write_urb->dev = port->serial->dev;
retval = usb_submit_urb (command_port->write_urb, GFP_KERNEL);
- spin_unlock_irqrestore(&command_info->lock, flags);
if (retval) {
dbg("%s - submit urb failed", __FUNCTION__);
goto exit;
}
+ spin_unlock_irqrestore(&command_info->lock, flags);
/* wait for the command to complete */
wait_event_interruptible_timeout(command_info->wait_command,
spin_lock_irqsave(&command_info->lock, flags);
command_info->port_running--;
if (!command_info->port_running)
- usb_unlink_urb(command_port->read_urb);
+ usb_kill_urb(command_port->read_urb);
spin_unlock_irqrestore(&command_info->lock, flags);
}
list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
urb = wrap->urb;
- usb_unlink_urb(urb);
- list_del(tmp);
- list_add(tmp, &info->rx_urbs_free);
+ usb_kill_urb(urb);
+ list_move(tmp, &info->rx_urbs_free);
}
break;
}
}
-static void rx_data_softint(void *private)
+static void rx_data_softint(struct work_struct *work)
{
- struct usb_serial_port *port = (struct usb_serial_port *)private;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
+ struct whiteheat_private *info =
+ container_of(work, struct whiteheat_private, rx_work);
+ struct usb_serial_port *port = info->port;
struct tty_struct *tty = port->tty;
struct whiteheat_urb_wrap *wrap;
struct urb *urb;
urb = wrap->urb;
if (tty && urb->actual_length) {
- if (urb->actual_length > TTY_FLIPBUF_SIZE - tty->flip.count) {
+ int len = tty_buffer_request_room(tty, urb->actual_length);
+ /* This stuff can go away now I suspect */
+ if (unlikely(len < urb->actual_length)) {
spin_lock_irqsave(&info->lock, flags);
list_add(tmp, &info->rx_urb_q);
spin_unlock_irqrestore(&info->lock, flags);
schedule_work(&info->rx_work);
return;
}
-
- memcpy(tty->flip.char_buf_ptr, urb->transfer_buffer, urb->actual_length);
- tty->flip.char_buf_ptr += urb->actual_length;
- tty->flip.count += urb->actual_length;
- sent += urb->actual_length;
+ tty_insert_flip_string(tty, urb->transfer_buffer, len);
+ sent += len;
}
urb->dev = port->serial->dev;
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
-MODULE_PARM(urb_pool_size, "i");
+module_param(urb_pool_size, int, 0);
MODULE_PARM_DESC(urb_pool_size, "Number of urbs to use for buffering");
-MODULE_PARM(debug, "i");
+module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");