Greg, 

Where is the Makefile patch ? 

On Fri, 21 Dec 2001, Greg KH wrote:

> Hi,
> 
> Here's a patch against 2.4.17 that adds the usb-serial ipaq driver.  The
> patch is by Ganesh Varadarajan.
> 
> thanks,
> 
> greg k-h
> 
> 
> 
> diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
> --- /dev/null Wed Dec 31 16:00:00 1969
> +++ b/drivers/usb/serial/ipaq.c       Fri Dec 21 12:58:16 2001
> @@ -0,0 +1,532 @@
> +/*
> + * USB Compaq iPAQ driver
> + *
> + *   Copyright (C) 2001
> + *       Ganesh Varadarajan <[EMAIL PROTECTED]>
> + *
> + *   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.
> + *
> + */
> +
> +#include <linux/config.h>
> +#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/slab.h>
> +#include <linux/fcntl.h>
> +#include <linux/tty.h>
> +#include <linux/tty_driver.h>
> +#include <linux/tty_flip.h>
> +#include <linux/module.h>
> +#include <linux/spinlock.h>
> +#include <linux/usb.h>
> +
> +#ifdef CONFIG_USB_SERIAL_DEBUG
> +     static int debug = 1;
> +#else
> +     static int debug = 0;
> +#endif
> +
> +#include "usb-serial.h"
> +#include "ipaq.h"
> +
> +/*
> + * Version Information
> + */
> +#define DRIVER_VERSION "v0.1"
> +#define DRIVER_AUTHOR "Ganesh Varadarajan <[EMAIL PROTECTED]>"
> +#define DRIVER_DESC "USB Compaq iPAQ driver"
> +
> +/* Function prototypes for an ipaq */
> +static int  ipaq_open (struct usb_serial_port *port, struct file *filp);
> +static void ipaq_close (struct usb_serial_port *port, struct file *filp);
> +static int  ipaq_startup (struct usb_serial *serial);
> +static void ipaq_shutdown (struct usb_serial *serial);
> +static int ipaq_write(struct usb_serial_port *port, int from_user, const unsigned 
>char *buf,
> +                    int count);
> +static int ipaq_write_bulk(struct usb_serial_port *port, int from_user, const 
>unsigned char *buf,
> +                        int count);
> +static int ipaq_write_flush(struct usb_serial_port *port);
> +static void ipaq_read_bulk_callback (struct urb *urb);
> +static void ipaq_write_bulk_callback(struct urb *urb);
> +static int ipaq_write_room(struct usb_serial_port *port);
> +static int ipaq_chars_in_buffer(struct usb_serial_port *port);
> +static void ipaq_destroy_lists(struct usb_serial_port *port);
> +
> +
> +static __devinitdata struct usb_device_id ipaq_id_table [] = {
> +     { USB_DEVICE(IPAQ_VENDOR_ID, IPAQ_PRODUCT_ID) },
> +     { }                                     /* Terminating entry */
> +};
> +
> +MODULE_DEVICE_TABLE (usb, ipaq_id_table);
> +
> +/* All of the device info needed for the Compaq iPAQ */
> +struct usb_serial_device_type ipaq_device = {
> +     name:                   "Compaq iPAQ",
> +     id_table:               ipaq_id_table,
> +     needs_interrupt_in:     MUST_HAVE_NOT,
> +     needs_bulk_in:          MUST_HAVE,
> +     needs_bulk_out:         MUST_HAVE,
> +     num_interrupt_in:       0,
> +     num_bulk_in:            1,
> +     num_bulk_out:           1,
> +     num_ports:              1,
> +     open:                   ipaq_open,
> +     close:                  ipaq_close,
> +     startup:                ipaq_startup,
> +     shutdown:               ipaq_shutdown,
> +     write:                  ipaq_write,
> +     write_room:             ipaq_write_room,
> +     chars_in_buffer:        ipaq_chars_in_buffer,
> +     read_bulk_callback:     ipaq_read_bulk_callback,
> +     write_bulk_callback:    ipaq_write_bulk_callback,
> +};
> +
> +static spinlock_t    write_list_lock;
> +static int           bytes_in;
> +static int           bytes_out;
> +
> +static int ipaq_open(struct usb_serial_port *port, struct file *filp)
> +{
> +     struct usb_serial       *serial = port->serial;
> +     struct ipaq_private     *priv;
> +     struct ipaq_packet      *pkt;
> +     int                     i, result = 0;
> +
> +     if (port_paranoia_check(port, __FUNCTION__)) {
> +             return -ENODEV;
> +     }
> +     
> +     dbg(__FUNCTION__ " - port %d", port->number);
> +
> +     down(&port->sem);
> +     
> +     ++port->open_count;
> +     MOD_INC_USE_COUNT;
> +     
> +     if (!port->active) {
> +             port->active = 1;
> +             bytes_in = 0;
> +             bytes_out = 0;
> +             priv = (struct ipaq_private *)kmalloc(sizeof(struct ipaq_private), 
>GFP_KERNEL);
> +             if (priv == NULL) {
> +                     err(__FUNCTION__ " - Out of memory");
> +                     return -ENOMEM;
> +             }
> +             port->private = (void *)priv;
> +             priv->active = 0;
> +             priv->queue_len = 0;
> +             INIT_LIST_HEAD(&priv->queue);
> +             INIT_LIST_HEAD(&priv->freelist);
> +
> +             for (i = 0; i < URBDATA_QUEUE_MAX / PACKET_SIZE; i++) {
> +                     pkt = kmalloc(sizeof(struct ipaq_packet), GFP_KERNEL);
> +                     if (pkt == NULL) {
> +                             goto enomem;
> +                     }
> +                     pkt->data = kmalloc(PACKET_SIZE, GFP_KERNEL);
> +                     if (pkt->data == NULL) {
> +                             kfree(pkt);
> +                             goto enomem;
> +                     }
> +                     pkt->len = 0;
> +                     pkt->written = 0;
> +                     INIT_LIST_HEAD(&pkt->list);
> +                     list_add(&pkt->list, &priv->freelist);
> +                     priv->free_len += PACKET_SIZE;
> +             }
> +
> +             /*
> +              * Force low latency on. This will immediately push data to the line
> +              * discipline instead of queueing.
> +              */
> +
> +             port->tty->low_latency = 1;
> +
> +             /*
> +              * Lose the small buffers usbserial provides. Make larger ones.
> +              */
> +
> +             kfree(port->bulk_in_buffer);
> +             kfree(port->bulk_out_buffer);
> +             port->bulk_in_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
> +             if (port->bulk_in_buffer == NULL) {
> +                     goto enomem;
> +             }
> +             port->bulk_out_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
> +             if (port->bulk_out_buffer == NULL) {
> +                     kfree(port->bulk_in_buffer);
> +                     goto enomem;
> +             }
> +             port->read_urb->transfer_buffer = port->bulk_in_buffer;
> +             port->write_urb->transfer_buffer = port->bulk_out_buffer;
> +             port->read_urb->transfer_buffer_length = URBDATA_SIZE;
> +             port->bulk_out_size = port->write_urb->transfer_buffer_length = 
>URBDATA_SIZE;
> +             
> +             /* Start reading from the device */
> +             FILL_BULK_URB(port->read_urb, serial->dev, 
> +                           usb_rcvbulkpipe(serial->dev, 
>port->bulk_in_endpointAddress),
> +                           port->read_urb->transfer_buffer, 
>port->read_urb->transfer_buffer_length,
> +                           ipaq_read_bulk_callback, port);
> +             result = usb_submit_urb(port->read_urb);
> +             if (result) {
> +                     err(__FUNCTION__ " - failed submitting read urb, error %d", 
>result);
> +             }
> +
> +             /*
> +              * Send out two control messages observed in win98 sniffs. Not sure 
>what
> +              * they do.
> +              */
> +
> +             result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 
>0x22, 0x21,
> +                             0x1, 0, NULL, 0, 5 * HZ);
> +             if (result < 0) {
> +                     err(__FUNCTION__ " - failed doing control urb, error %d", 
>result);
> +             }
> +             result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 
>0x22, 0x21,
> +                             0x1, 0, NULL, 0, 5 * HZ);
> +             if (result < 0) {
> +                     err(__FUNCTION__ " - failed doing control urb, error %d", 
>result);
> +             }
> +     }
> +     
> +     up(&port->sem);
> +     
> +     return result;
> +
> +enomem:
> +     ipaq_destroy_lists(port);
> +     kfree(priv);
> +     err(__FUNCTION__ " - Out of memory");
> +     return -ENOMEM;
> +}
> +
> +
> +static void ipaq_close(struct usb_serial_port *port, struct file *filp)
> +{
> +     struct usb_serial       *serial;
> +     struct ipaq_private     *priv = port->private;
> +
> +     if (port_paranoia_check(port, __FUNCTION__)) {
> +             return; 
> +     }
> +     
> +     dbg(__FUNCTION__ " - port %d", port->number);
> +                      
> +     serial = get_usb_serial(port, __FUNCTION__);
> +     if (!serial)
> +             return;
> +     
> +     down (&port->sem);
> +
> +     --port->open_count;
> +
> +     if (port->open_count <= 0) {
> +
> +             /*
> +              * shut down bulk read and write
> +              */
> +
> +             usb_unlink_urb(port->write_urb);
> +             usb_unlink_urb(port->read_urb);
> +             ipaq_destroy_lists(port);
> +             kfree(priv);
> +             port->private = NULL;
> +             port->active = 0;
> +             port->open_count = 0;
> +
> +     }
> +     up (&port->sem);
> +
> +     /* Uncomment the following line if you want to see some statistics in your 
>syslog */
> +     /* info ("Bytes In = %d  Bytes Out = %d", bytes_in, bytes_out); */
> +
> +     MOD_DEC_USE_COUNT;
> +}
> +
> +static void ipaq_read_bulk_callback(struct urb *urb)
> +{
> +     struct usb_serial_port  *port = (struct usb_serial_port *)urb->context;
> +     struct usb_serial       *serial = get_usb_serial (port, __FUNCTION__);
> +     struct tty_struct       *tty;
> +     unsigned char           *data = urb->transfer_buffer;
> +     int                     i, result;
> +
> +     if (port_paranoia_check(port, __FUNCTION__))
> +             return;
> +
> +     dbg(__FUNCTION__ " - port %d", port->number);
> +
> +     if (!serial) {
> +             dbg(__FUNCTION__ " - bad serial pointer, exiting");
> +             return;
> +     }
> +
> +     if (urb->status) {
> +             dbg(__FUNCTION__ " - nonzero read bulk status received: %d", 
>urb->status);
> +             return;
> +     }
> +
> +     usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
> +
> +     tty = port->tty;
> +     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_flip_buffer_push(tty);
> +             bytes_in += urb->actual_length;
> +     }
> +
> +     /* Continue trying to always read  */
> +     FILL_BULK_URB(port->read_urb, serial->dev, 
> +                   usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
> +                   port->read_urb->transfer_buffer, 
>port->read_urb->transfer_buffer_length,
> +                   ipaq_read_bulk_callback, port);
> +     result = usb_submit_urb(port->read_urb);
> +     if (result)
> +             err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
> +     return;
> +}
> +
> +static int ipaq_write(struct usb_serial_port *port, int from_user, const unsigned 
>char *buf,
> +                    int count)
> +{
> +     const unsigned char     *current_position = buf;
> +     int                     bytes_sent = 0;
> +     int                     transfer_size;
> +
> +     dbg(__FUNCTION__ " - port %d", port->number);
> +
> +     usb_serial_debug_data(__FILE__, __FUNCTION__, count, buf);
> +     
> +     while (count > 0) {
> +             transfer_size = min(count, PACKET_SIZE);
> +             if (ipaq_write_bulk(port, from_user, current_position, transfer_size)) 
>{
> +                     break;
> +             }
> +             current_position += transfer_size;
> +             bytes_sent += transfer_size;
> +             count -= transfer_size;
> +             bytes_out += transfer_size;
> +     }
> +
> +     return bytes_sent;
> +} 
> +
> +static int ipaq_write_bulk(struct usb_serial_port *port, int from_user, const 
>unsigned char *buf,
> +                        int count)
> +{
> +     struct ipaq_private     *priv = port->private;
> +     struct ipaq_packet      *pkt = NULL;
> +     int                     result = 0;
> +     unsigned long           flags;
> +
> +     if (priv->free_len <= 0) {
> +             dbg(__FUNCTION__ " - we're stuffed");
> +             return -EAGAIN;
> +     }
> +
> +     spin_lock_irqsave(&write_list_lock, flags);
> +     if (!list_empty(&priv->freelist)) {
> +             pkt = list_entry(priv->freelist.next, struct ipaq_packet, list);
> +             list_del(&pkt->list);
> +             priv->free_len -= PACKET_SIZE;
> +     }
> +     spin_unlock_irqrestore(&write_list_lock, flags);
> +     if (pkt == NULL) {
> +             dbg(__FUNCTION__ " - we're stuffed");
> +             return -EAGAIN;
> +     }
> +
> +     if (from_user) {
> +             copy_from_user(pkt->data, buf, count);
> +     } else {
> +             memcpy(pkt->data, buf, count);
> +     }
> +     usb_serial_debug_data(__FILE__, __FUNCTION__, count, pkt->data);
> +
> +     pkt->len = count;
> +     pkt->written = 0;
> +     spin_lock_irqsave(&write_list_lock, flags);
> +     list_add_tail(&pkt->list, &priv->queue);
> +     priv->queue_len += count;
> +     if (priv->active == 0) {
> +             priv->active = 1;
> +             result = ipaq_write_flush(port);
> +     }
> +     spin_unlock_irqrestore(&write_list_lock, flags);
> +     return result;
> +}
> +
> +static int ipaq_write_flush(struct usb_serial_port *port)
> +{
> +     struct ipaq_private     *priv = (struct ipaq_private *)port->private;
> +     struct usb_serial       *serial = port->serial;
> +     int                     count, room, result;
> +     struct ipaq_packet      *pkt;
> +     struct urb              *urb = port->write_urb;
> +     struct list_head        *tmp;
> +
> +     if (urb->status == -EINPROGRESS) {
> +             /* Should never happen */
> +             err(__FUNCTION__ " - flushing while urb is active !");
> +             return -EAGAIN;
> +     }
> +     room = URBDATA_SIZE;
> +     for (tmp = priv->queue.next; tmp != &priv->queue;) {
> +             pkt = list_entry(tmp, struct ipaq_packet, list);
> +             tmp = tmp->next;
> +             count = min(room, (int)(pkt->len - pkt->written));
> +             memcpy(urb->transfer_buffer + (URBDATA_SIZE - room),
> +                    pkt->data + pkt->written, count);
> +             room -= count;
> +             pkt->written += count;
> +             priv->queue_len -= count;
> +             if (pkt->written == pkt->len) {
> +                     list_del(&pkt->list);
> +                     list_add(&pkt->list, &priv->freelist);
> +                     priv->free_len += PACKET_SIZE;
> +             }
> +             if (room == 0) {
> +                     break;
> +             }
> +     }
> +
> +     count = URBDATA_SIZE - room;
> +     FILL_BULK_URB(port->write_urb, serial->dev, 
> +                   usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
> +                   port->write_urb->transfer_buffer, count, 
>ipaq_write_bulk_callback,
> +                   port);
> +     result = usb_submit_urb(urb);
> +     if (result) {
> +             err(__FUNCTION__ " - failed submitting write urb, error %d", result);
> +     }
> +     return result;
> +}
> +
> +static void ipaq_write_bulk_callback(struct urb *urb)
> +{
> +     struct usb_serial_port  *port = (struct usb_serial_port *)urb->context;
> +     struct ipaq_private     *priv = (struct ipaq_private *)port->private;
> +     unsigned long           flags;
> +
> +     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);
> +     }
> +
> +     spin_lock_irqsave(&write_list_lock, flags);
> +     if (!list_empty(&priv->queue)) {
> +             ipaq_write_flush(port);
> +     } else {
> +             priv->active = 0;
> +     }
> +     spin_unlock_irqrestore(&write_list_lock, flags);
> +     queue_task(&port->tqueue, &tq_immediate);
> +     mark_bh(IMMEDIATE_BH);
> +     
> +     return;
> +}
> +
> +static int ipaq_write_room(struct usb_serial_port *port)
> +{
> +     struct ipaq_private     *priv = (struct ipaq_private *)port->private;
> +
> +     dbg(__FUNCTION__ " - freelen %d", priv->free_len);
> +     return priv->free_len;
> +}
> +
> +static int ipaq_chars_in_buffer(struct usb_serial_port *port)
> +{
> +     struct ipaq_private     *priv = (struct ipaq_private *)port->private;
> +
> +     dbg(__FUNCTION__ " - queuelen %d", priv->queue_len);
> +     return priv->queue_len;
> +}
> +
> +static void ipaq_destroy_lists(struct usb_serial_port *port)
> +{
> +     struct ipaq_private     *priv = (struct ipaq_private *)port->private;
> +     struct list_head        *tmp;
> +     struct ipaq_packet      *pkt;
> +
> +     for (tmp = priv->queue.next; tmp != &priv->queue;) {
> +             pkt = list_entry(tmp, struct ipaq_packet, list);
> +             tmp = tmp->next;
> +             kfree(pkt->data);
> +             kfree(pkt);
> +     }
> +     for (tmp = priv->freelist.next; tmp != &priv->freelist;) {
> +             pkt = list_entry(tmp, struct ipaq_packet, list);
> +             tmp = tmp->next;
> +             kfree(pkt->data);
> +             kfree(pkt);
> +     }
> +     return;
> +}
> +
> +
> +static int ipaq_startup(struct usb_serial *serial)
> +{
> +     dbg(__FUNCTION__);
> +     usb_set_configuration(serial->dev, 1);
> +     return 0;
> +}
> +
> +static void ipaq_shutdown(struct usb_serial *serial)
> +{
> +     int i;
> +
> +     dbg (__FUNCTION__);
> +
> +     /* stop reads and writes on all ports */
> +     for (i=0; i < serial->num_ports; ++i) {
> +             while (serial->port[i].open_count > 0) {
> +                     ipaq_close(&serial->port[i], NULL);
> +             }
> +     }
> +}
> +
> +static int __init ipaq_init(void)
> +{
> +     usb_serial_register(&ipaq_device);
> +     info(DRIVER_DESC " " DRIVER_VERSION);
> +
> +     return 0;
> +}
> +
> +
> +static void __exit ipaq_exit(void)
> +{
> +     usb_serial_deregister(&ipaq_device);
> +}
> +
> +
> +module_init(ipaq_init);
> +module_exit(ipaq_exit);
> +
> +MODULE_AUTHOR( DRIVER_AUTHOR );
> +MODULE_DESCRIPTION( DRIVER_DESC );
> +MODULE_LICENSE("GPL");
> +
> +MODULE_PARM(debug, "i");
> +MODULE_PARM_DESC(debug, "Debug enabled or not");
> +
> diff -Nru a/drivers/usb/serial/ipaq.h b/drivers/usb/serial/ipaq.h
> --- /dev/null Wed Dec 31 16:00:00 1969
> +++ b/drivers/usb/serial/ipaq.h       Fri Dec 21 12:58:16 2001
> @@ -0,0 +1,60 @@
> +/*
> + * USB Compaq iPAQ driver
> + *
> + *   Copyright (C) 2001
> + *       Ganesh Varadarajan <[EMAIL PROTECTED]>
> + *
> + *   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.
> + *
> + * 
> + */
> +
> +#ifndef __LINUX_USB_SERIAL_IPAQ_H
> +#define __LINUX_USB_SERIAL_IPAQ_H
> +
> +
> +#define IPAQ_VENDOR_ID                       0x049f
> +#define IPAQ_PRODUCT_ID                      0x0003
> +
> +/*
> + * Since we can't queue our bulk write urbs (don't know why - it just
> + * doesn't work), we can send down only one write urb at a time. The simplistic
> + * approach taken by the generic usbserial driver will work, but it's not good
> + * for performance. Therefore, we buffer upto URBDATA_QUEUE_MAX bytes of write
> + * requests coming from the line discipline. This is done by chaining them
> + * in lists of struct ipaq_packet, each packet holding a maximum of
> + * PACKET_SIZE bytes.
> + *
> + * ipaq_write() can be called from bottom half context; hence we can't
> + * allocate memory for packets there. So we initialize a pool of packets at
> + * the first open and maintain a freelist.
> + *
> + * The value of PACKET_SIZE was empirically determined by
> + * checking the maximum write sizes sent down by the ppp ldisc.
> + * URBDATA_QUEUE_MAX is set to 64K, which is the maximum TCP window size
> + * supported by the iPAQ.
> + */
> +
> +struct ipaq_packet {
> +     char                    *data;
> +     size_t                  len;
> +     size_t                  written;
> +     struct list_head        list;
> +};
> +
> +struct ipaq_private {
> +     int                     active;
> +     int                     queue_len;
> +     int                     free_len;
> +     struct list_head        queue;
> +     struct list_head        freelist;
> +};
> +
> +#define URBDATA_SIZE         4096
> +#define URBDATA_QUEUE_MAX    (64 * 1024)
> +#define PACKET_SIZE          256
> +
> +#endif
> 


_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to