diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-04-19 04:00:00 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-04-19 04:00:00 +0000 |
commit | 46e045034336a2cc90c1798cd7cc07af744ddfd6 (patch) | |
tree | 3b9b51fc482e729f663d25333e77fbed9aaa939a /drivers/usb/serial/visor.c | |
parent | 31dc59d503a02e84c4de98826452acaeb56dc15a (diff) |
Merge with Linux 2.3.99-pre4.
Diffstat (limited to 'drivers/usb/serial/visor.c')
-rw-r--r-- | drivers/usb/serial/visor.c | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c new file mode 100644 index 000000000..6832814da --- /dev/null +++ b/drivers/usb/serial/visor.c @@ -0,0 +1,209 @@ +/* + * USB HandSpring Visor driver + * + * (C) Copyright (C) 1999, 2000 + * Greg Kroah-Hartman (greg@kroah.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * See Documentation/usb/usb-serial.txt for more information on using this driver + * + * (03/26/2000) gkh + * Split driver up into device specific pieces. + * + */ + +#include <linux/config.h> + +#ifdef CONFIG_USB_SERIAL_VISOR + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/signal.h> +#include <linux/errno.h> +#include <linux/poll.h> +#include <linux/init.h> +#include <linux/malloc.h> +#include <linux/fcntl.h> +#include <linux/tty_driver.h> +#include <linux/tty_flip.h> +#include <linux/tty.h> +#include <linux/module.h> +#include <linux/spinlock.h> + +#ifdef CONFIG_USB_SERIAL_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif +#include <linux/usb.h> + +#include "usb-serial.h" + +#include "visor.h" + + +/* function prototypes for a handspring visor */ +static int visor_open (struct usb_serial_port *port, struct file *filp); +static void visor_close (struct usb_serial_port *port, struct file *filp); +static void visor_throttle (struct usb_serial_port *port); +static void visor_unthrottle (struct usb_serial_port *port); +static int visor_startup (struct usb_serial *serial); + +/* All of the device info needed for the Handspring Visor */ +static __u16 handspring_vendor_id = HANDSPRING_VENDOR_ID; +static __u16 handspring_product_id = HANDSPRING_VISOR_ID; +struct usb_serial_device_type handspring_device = { + name: "Handspring Visor", + idVendor: &handspring_vendor_id, /* the Handspring vendor ID */ + idProduct: &handspring_product_id, /* the Handspring Visor product id */ + needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */ + needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */ + needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */ + num_interrupt_in: 0, + num_bulk_in: 2, + num_bulk_out: 2, + num_ports: 2, + open: visor_open, + close: visor_close, + throttle: visor_throttle, + unthrottle: visor_unthrottle, + startup: visor_startup, +}; + + +/****************************************************************************** + * Handspring Visor specific driver functions + ******************************************************************************/ +static int visor_open (struct usb_serial_port *port, struct file *filp) +{ + dbg("visor_open port %d", port->number); + + if (port->active) { + dbg ("device already open"); + return -EINVAL; + } + + port->active = 1; + + /*Start reading from the device*/ + if (usb_submit_urb(port->read_urb)) + dbg("usb_submit_urb(read bulk) failed"); + + return (0); +} + + +static void visor_close (struct usb_serial_port *port, struct file * filp) +{ + struct usb_serial *serial = port->serial; + unsigned char *transfer_buffer = kmalloc (0x12, GFP_KERNEL); + + dbg("visor_close port %d", port->number); + + if (!transfer_buffer) { + err("visor_close: kmalloc(%d) failed.", 0x12); + } else { + /* send a shutdown message to the device */ + usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_CLOSE_NOTIFICATION, + 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300); + } + + /* shutdown our bulk reads and writes */ + usb_unlink_urb (port->write_urb); + usb_unlink_urb (port->read_urb); + port->active = 0; +} + + +static void visor_throttle (struct usb_serial_port *port) +{ + dbg("visor_throttle port %d", port->number); + + usb_unlink_urb (port->read_urb); + + return; +} + + +static void visor_unthrottle (struct usb_serial_port *port) +{ + dbg("visor_unthrottle port %d", port->number); + + if (usb_unlink_urb (port->read_urb)) + dbg("usb_submit_urb(read bulk) failed"); + + return; +} + + +static int visor_startup (struct usb_serial *serial) +{ + int response; + int i; + unsigned char *transfer_buffer = kmalloc (256, GFP_KERNEL); + + if (!transfer_buffer) { + err("visor_startup: kmalloc(%d) failed.", 256); + return -ENOMEM; + } + + dbg("visor_startup"); + + dbg("visor_setup: Set config to 1"); + usb_set_configuration (serial->dev, 1); + + /* send a get connection info request */ + response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_GET_CONNECTION_INFORMATION, + 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300); + if (response < 0) { + err("visor_startup: error getting connection information"); + } else { + struct visor_connection_info *connection_info = (struct visor_connection_info *)transfer_buffer; + char *string; + info("%s: Number of ports: %d", serial->type->name, connection_info->num_ports); + for (i = 0; i < connection_info->num_ports; ++i) { + switch (connection_info->connections[i].port_function_id) { + case VISOR_FUNCTION_GENERIC: + string = "Generic"; + break; + case VISOR_FUNCTION_DEBUGGER: + string = "Debugger"; + break; + case VISOR_FUNCTION_HOTSYNC: + string = "HotSync"; + break; + case VISOR_FUNCTION_CONSOLE: + string = "Console"; + break; + case VISOR_FUNCTION_REMOTE_FILE_SYS: + string = "Remote File System"; + break; + default: + string = "unknown"; + break; + } + info("%s: port %d, is for %s use and is bound to ttyUSB%d", serial->type->name, connection_info->connections[i].port, string, serial->minor + i); + } + } + + /* ask for the number of bytes available, but ignore the response as it is broken */ + response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE, + 0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300); + if (response < 0) { + err("visor_startup: error getting bytes available request"); + } + + kfree (transfer_buffer); + + /* continue on with initialization */ + return (0); +} + + +#endif /* CONFIG_USB_SERIAL_VISOR*/ + + |