patch-2.4.0-test5 linux/drivers/usb/serial/visor.c
Next file: linux/drivers/usb/serial/whiteheat.c
Previous file: linux/drivers/usb/serial/usbserial.c
Back to the patch index
Back to the overall index
- Lines: 181
- Date:
Mon Jul 24 19:03:44 2000
- Orig file:
v2.4.0-test4/linux/drivers/usb/serial/visor.c
- Orig date:
Mon Jul 10 16:47:25 2000
diff -u --recursive --new-file v2.4.0-test4/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c
@@ -11,6 +11,13 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (07/23/2000) gkh
+ * Added pool of write urbs to speed up transfers to the visor.
+ *
+ * (07/19/2000) gkh
+ * Added module_init and module_exit functions to handle the fact that this
+ * driver is a loadable module now.
+ *
* (07/03/2000) gkh
* Added visor_set_ioctl and visor_set_termios functions (they don't do much
* of anything, but are good for debugging.)
@@ -60,11 +67,13 @@
/* 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 int visor_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
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);
static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static void visor_write_bulk_callback (struct urb *urb);
/* All of the device info needed for the Handspring Visor */
static __u16 handspring_vendor_id = HANDSPRING_VENDOR_ID;
@@ -87,9 +96,15 @@
startup: visor_startup,
ioctl: visor_ioctl,
set_termios: visor_set_termios,
+ write: visor_write,
+ write_bulk_callback: visor_write_bulk_callback,
};
+#define NUM_URBS 24
+static struct urb *write_urb_pool[NUM_URBS];
+
+
/******************************************************************************
* Handspring Visor specific driver functions
******************************************************************************/
@@ -135,6 +150,93 @@
}
+static int visor_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
+{
+ struct usb_serial *serial = port->serial;
+ struct urb *urb = NULL;
+ unsigned char *buffer = NULL;
+ int status;
+ int i;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ if (count == 0) {
+ dbg(__FUNCTION__ " - write request of 0 bytes");
+ return 0;
+ }
+
+ /* try to find a free urb in our list of them */
+ for (i = 0; i < NUM_URBS; ++i) {
+ if (write_urb_pool[i]->status != -EINPROGRESS) {
+ urb = write_urb_pool[i];
+ break;
+ }
+ }
+ if (urb == NULL) {
+ dbg (__FUNCTION__ " - no free urbs");
+ return 0;
+ }
+
+ count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+
+#ifdef DEBUG
+ printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", count);
+ for (i = 0; i < count; ++i) {
+ printk ("%.2x ", buf[i]);
+ }
+ printk ("\n");
+#endif
+
+ if (urb->transfer_buffer != NULL)
+ kfree(urb->transfer_buffer);
+ buffer = kmalloc (count, GFP_KERNEL);
+ if (buffer == NULL) {
+ err(__FUNCTION__" no more kernel memory...");
+ return 0;
+ }
+
+ if (from_user) {
+ copy_from_user(buffer, buf, count);
+ }
+ else {
+ memcpy (buffer, buf, count);
+ }
+
+ /* build up our urb */
+ FILL_BULK_URB (urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
+ buffer, count, visor_write_bulk_callback, port);
+ urb->transfer_flags |= USB_QUEUE_BULK;
+
+ /* send it down the pipe */
+ status = usb_submit_urb(urb);
+ if (status)
+ dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
+
+ return (count);
+}
+
+
+static void visor_write_bulk_callback (struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+
+ if (port_paranoia_check (port, __FUNCTION__))
+ return;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ if (urb->status) {
+ dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
+ return;
+ }
+
+ queue_task(&port->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+
+ return;
+}
+
+
static void visor_throttle (struct usb_serial_port *port)
{
dbg(__FUNCTION__ " - port %d", port->number);
@@ -293,4 +395,42 @@
}
+int visor_init (void)
+{
+ int i;
+
+ usb_serial_register (&handspring_device);
+
+ /* create our write urb pool */
+ for (i = 0; i < NUM_URBS; ++i) {
+ struct urb *urb = usb_alloc_urb(0);
+ if (urb == NULL) {
+ err("No more urbs???");
+ continue;
+ }
+ urb->transfer_buffer = NULL;
+ write_urb_pool[i] = urb;
+ }
+
+ return 0;
+}
+
+
+void visor_exit (void)
+{
+ int i;
+
+ usb_serial_deregister (&handspring_device);
+
+ for (i = 0; i < NUM_URBS; ++i) {
+ usb_unlink_urb(write_urb_pool[i]);
+ if (write_urb_pool[i]->transfer_buffer)
+ kfree(write_urb_pool[i]->transfer_buffer);
+ usb_free_urb (write_urb_pool[i]);
+ }
+}
+
+
+module_init(visor_init);
+module_exit(visor_exit);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)