Hello,

I previously submitted a driver for Garmin GPS that used its own minor
number interface. Greg suggested using the usb-serial interface
instead. I thought the usb-serial interface made sense after
investigating it a little. The following patch is a usb-serial
interface version of the Garmin GPS driver. It was borrowed from the
palm OS PDA drivers (visor.c).

Thanks,

Marty

cd /usr/src/linux; patch -p0 -b < patchfile

Files /usr/src/linux-2.6.9_default/drivers/usb/serial/.garmin_usb_tty.h.swp
and ./drivers/usb/serial/.garmin_usb_tty.h.swp differ
diff -u -r -N /usr/src/linux-2.6.9_default/drivers/usb/serial/Kconfig
./drivers/usb/serial/Kconfig
--- /usr/src/linux-2.6.9_default/drivers/usb/serial/Kconfig     2004-11-02
23:35:30.000000000 +0000
+++ ./drivers/usb/serial/Kconfig        2004-11-07 23:26:38.000000000 +0000
@@ -387,11 +387,22 @@
 
          To compile this driver as a module, choose M here: the
          module will be called omninet.
-
+      
 config USB_EZUSB
        bool
        depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM ||
USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT
        default y
 
+config USB_SERIAL_GARMIN
+       tristate "USB to serial conversion for Garmin GPS (EXPERIMENTAL)"
+       depends on USB_SERIAL && EXPERIMENTAL
+       help
+         Say Y here is you want to use an USB Garmin gps through 
+         the serial port.
+
+         To compile this driver as a module, choose M here: the
+         module will be called garmin_usb_tty.
+
+
 endmenu
 
diff -u -r -N /usr/src/linux-2.6.9_default/drivers/usb/serial/Makefile
./drivers/usb/serial/Makefile
--- /usr/src/linux-2.6.9_default/drivers/usb/serial/Makefile    2004-11-02
23:35:30.000000000 +0000
+++ ./drivers/usb/serial/Makefile       2004-11-04 22:49:01.000000000 +0000
@@ -31,4 +31,4 @@
 obj-$(CONFIG_USB_SERIAL_VISOR)                 += visor.o
 obj-$(CONFIG_USB_SERIAL_WHITEHEAT)             += whiteheat.o
 obj-$(CONFIG_USB_SERIAL_XIRCOM)                        += keyspan_pda.o
-
+obj-$(CONFIG_USB_SERIAL_GARMIN)                        += garmin_usb_tty.o
diff -u -r -N /usr/src/linux-2.6.9_default/drivers/usb/serial/garmin_usb_tty.c
./drivers/usb/serial/garmin_usb_tty.c
--- /usr/src/linux-2.6.9_default/drivers/usb/serial/garmin_usb_tty.c    
1970-01-01
00:00:00.000000000 +0000
+++ ./drivers/usb/serial/garmin_usb_tty.c       2004-11-08 00:17:07.248247352 
+0000
@@ -0,0 +1,709 @@
+/*
+ * Garmin GPS USB to serial interface
+ *     Copyright (C) 2004 Martin Boos <[EMAIL PROTECTED]>
+ *
+ * Based on:
+ * USB HandSpring garmin, Palm m50x, and Sony Clie driver
+ * (supports all of the Palm OS USB devices)
+ *
+ *     Copyright (C) 1999 - 2004
+ *         Greg Kroah-Hartman ([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.
+ *
+ * See Documentation/usb/usb-serial.txt for more information on using
this driver
+ */
+
+#include <linux/config.h>
+#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>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <asm/uaccess.h>
+#include <linux/usb.h>
+#include "usb-serial.h"
+#include "garmin_usb_tty.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.01"
+#define DRIVER_AUTHOR "Martin Boos <[EMAIL PROTECTED]>"
+#define DRIVER_DESC "USB to serial for Garmin GPS"
+
+#define HEADER_SIZE sizeof( struct garmin_usb_header )
+
+/* States returned from packetize() */
+enum {
+    ACCUMULATE_PACKET,
+    VALID_PACKET,
+    INVALID_PACKET
+};
+
+/* function prototypes for usb-serial device */
+static int garmin_attach (struct usb_serial *serial);
+static int  garmin_open                (struct usb_serial_port *port, struct 
file *filp);
+static void garmin_close               (struct usb_serial_port *port, struct 
file *filp);
+static int  garmin_write               (struct usb_serial_port *port, int
from_user, const unsigned char *buf, int count);
+static int  garmin_write_room          (struct usb_serial_port *port);
+static int  garmin_chars_in_buffer     (struct usb_serial_port *port);
+static void garmin_throttle    (struct usb_serial_port *port);
+static void garmin_unthrottle  (struct usb_serial_port *port);
+static int  garmin_probe               (struct usb_serial *serial, const struct
usb_device_id *id);
+static int  garmin_calc_num_ports(struct usb_serial *serial);
+static void garmin_shutdown    (struct usb_serial *serial);
+static int  garmin_ioctl               (struct usb_serial_port *port, struct 
file
* file, unsigned int cmd, unsigned long arg);
+static void garmin_set_termios (struct usb_serial_port *port, struct
termios *old_termios);
+static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
+static void garmin_read_bulk_callback  (struct urb *urb, struct pt_regs *regs);
+static void garmin_read_int_callback   (struct urb *urb, struct pt_regs *regs);
+
+/* local functions */
+static int packetize( char *data, int data_size, char *buffer, int
buffer_size, int *buffer_count );
+
+/* Parameters that may be passed into the module. */
+static int debug;
+
+
+static struct usb_device_id id_table [] = {
+       { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_GPSMAP_60_ID) },
+       { }                                     /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, id_table);
+
+static struct usb_driver garmin_driver = {
+       .owner =        THIS_MODULE,
+       .name =         "garmin_usb_tty",
+       .probe =        usb_serial_probe,
+       .disconnect =   usb_serial_disconnect,
+       .id_table =     id_table,
+};
+
+/* This should work will all USB garmin gps except the PDA units */
+static struct usb_serial_device_type generic_device = {
+       .owner =                THIS_MODULE,
+       .name =                 DRIVER_DESC,
+       .short_name =           "garmin",
+       .id_table =             id_table,
+       .num_interrupt_in =     1,
+       .num_bulk_in =          1,
+       .num_bulk_out =         1,
+       .num_ports =            1,
+       .open =                 garmin_open,
+       .close =                garmin_close,
+       .throttle =             garmin_throttle,
+       .unthrottle =           garmin_unthrottle,
+        .attach =               garmin_attach,
+       .probe =                garmin_probe,
+       .calc_num_ports =       garmin_calc_num_ports,
+       .shutdown =             garmin_shutdown,
+       .ioctl =                garmin_ioctl,
+       .set_termios =          garmin_set_termios,
+       .write =                garmin_write,
+       .write_room =           garmin_write_room,
+       .chars_in_buffer =      garmin_chars_in_buffer,
+       .write_bulk_callback =  garmin_write_bulk_callback,
+       .read_bulk_callback =   garmin_read_bulk_callback,
+       .read_int_callback =    garmin_read_int_callback,
+};
+
+static int bytes_in;
+static int bytes_out;
+
+
+void inline send_tty_data( struct tty_struct * tty, unsigned char *
data, int length )
+{
+       int i;
+       for (i = 0; i < 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);
+}
+
+/******************************************************************************
+ *  garmin specific driver functions
+ 
******************************************************************************/
+static int garmin_open (struct usb_serial_port *port, struct file *filp)
+{
+       struct usb_serial *serial = port->serial;
+       struct garmin_serial * pd;  /* private data */
+       unsigned char start_session_data[] = {  TRANSPORT_TYPE, 0, 0, 0, 
+                                               START_SESSION_ID, 0, 0, 0, 
+                                               0, 0, 0, 0 };
+       int result = -1;
+       int written = 0;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       bytes_in = 0;
+       bytes_out = 0;
+       /*
+       * Force low_latency on so that our tty_push actually forces the data
+       * through, otherwise it is scheduled, and with high data rates (like
+       * with OHCI) data can get lost.
+       */
+       if (port->tty)
+               port->tty->low_latency = 1;
+    
+       /* allocate and setup driver private data */
+       pd = ( struct garmin_serial * )kmalloc( sizeof( struct garmin_serial
), GFP_KERNEL );
+       if( pd == NULL )
+               goto exit;
+
+       pd->int_buffer_count = 0;
+       pd->int_buffer_size = 1024 * 4;
+       pd->int_buffer = kmalloc( pd->int_buffer_size, GFP_KERNEL );
+       if( pd->int_buffer == NULL )
+               goto exit_free_pd;
+
+       pd->bulk_buffer_count = 0;
+       pd->bulk_buffer_size = 1024 * 4;
+       pd->bulk_buffer = kmalloc( pd->bulk_buffer_size, GFP_KERNEL );
+       if( pd->bulk_buffer == NULL )
+               goto exit_free_int;
+   
+       pd->session_started = 0;
+       usb_set_serial_data( serial, pd );
+    
+       /* Start reading from the device */
+       usb_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,
+                          garmin_read_bulk_callback, port);
+       result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+       if (result) {
+            dev_err(&port->dev, "%s - failed submitting read urb, error %d\n",
+               __FUNCTION__, result);
+            goto exit_free_all;
+       }
+       
+       if (port->interrupt_in_urb) {
+            dbg("%s - adding interrupt input", __FUNCTION__);
+            result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+            if (result){
+                dev_err(&port->dev, "%s - failed submitting interrupt
urb, error %d\n",
+                        __FUNCTION__, result);
+            goto exit_free_all;
+            }
+       }
+    
+       /* start session with device */
+       written = garmin_write( port, 0, start_session_data, sizeof(
start_session_data ) );
+       if( written != sizeof( start_session_data ) ){
+               dbg("couldn't write start session");
+               result = -1;
+               goto exit_free_all;
+       }
+       
+       return 0;
+
+exit_free_all:
+       kfree( pd->bulk_buffer );
+exit_free_int:
+       kfree( pd->int_buffer );
+exit_free_pd:
+       kfree( pd );
+exit:  
+       return result;
+}
+
+static void garmin_close (struct usb_serial_port *port, struct file * filp)
+{
+       struct usb_serial *serial = port->serial;
+       struct garmin_serial * pd;  /* private data */
+        
+       /* shutdown our urbs */
+       usb_unlink_urb (port->read_urb);
+       if (port->interrupt_in_urb)
+               usb_unlink_urb (port->interrupt_in_urb);
+
+       /* free driver private data */
+       pd = ( struct garmin_serial* )usb_get_serial_data( serial );
+       if( pd ){
+               kfree( pd->int_buffer );
+               kfree( pd->bulk_buffer );
+               kfree( pd );    
+       }
+
+       /* Uncomment the following line if you want to see some statistics
in your syslog */
+       /* dev_info (&port->dev, "Bytes In = %d  Bytes Out = %d\n",
bytes_in, bytes_out); */
+}
+
+
+static int garmin_write (struct usb_serial_port *port, int from_user,
const unsigned char *buf, int count)
+{
+       struct usb_serial *serial = port->serial;
+       struct urb *urb;
+       unsigned char *buffer;
+       int status;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       buffer = kmalloc (count, GFP_ATOMIC);
+       if (!buffer) {
+               dev_err(&port->dev, "out of memory\n");
+               return -ENOMEM;
+       }
+
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               dev_err(&port->dev, "no more free urbs\n");
+               kfree (buffer);
+               return -ENOMEM;
+       }
+
+       if (from_user) {
+               if (copy_from_user (buffer, buf, count)) {
+                       kfree (buffer);
+                       usb_free_urb (urb);
+                       return -EFAULT;
+               }
+       } else {
+               memcpy (buffer, buf, count);
+       }
+
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
+
+        usb_fill_bulk_urb (urb, serial->dev,
+                          usb_sndbulkpipe (serial->dev,
+                                           port->bulk_out_endpointAddress),
+                          buffer, count, 
+                          garmin_write_bulk_callback, port);
+
+       /* send it down the pipe */
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (status) {
+               dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with
status = %d\n",
+                       __FUNCTION__, status);
+               count = status;
+               kfree (buffer);
+       } else {
+               bytes_out += count;
+       }
+
+       /* we are done with this urb, so let the host driver
+        * really free it when it is finished with it */
+       usb_free_urb (urb);
+
+       return count;
+}
+
+
+static int garmin_write_room (struct usb_serial_port *port)
+{
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /*
+        * We really can take anything the user throws at us
+        * but let's pick a nice big number to tell the tty
+        * layer that we have lots of free space
+        */
+       return (4*1024);
+}
+
+
+static int garmin_chars_in_buffer (struct usb_serial_port *port)
+{
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /* 
+        * We can't really account for how much data we
+        * have sent out, but hasn't made it through to the
+        * device, so just tell the tty layer that everything
+        * is flushed.
+        */
+       return 0;
+}
+
+
+static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+
+       /* free up the transfer buffer, as usb_free_urb() does not do this */
+       kfree (urb->transfer_buffer);
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+       
+       if (urb->status)
+               dbg("%s - nonzero write bulk status received: %d",
+                   __FUNCTION__, urb->status);
+
+       schedule_work(&port->work);
+}
+
+
+static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct tty_struct *tty;
+       unsigned char *data = urb->transfer_buffer;
+       int result;
+       int state;
+       struct garmin_serial * pd;  /* private data */
+
+       pd = ( struct garmin_serial* )usb_get_serial_data( port->serial );
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       if (urb->status) {
+               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, 
urb->status);
+               return;
+       }
+
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
urb->actual_length, data);
+    
+       state = packetize( urb->transfer_buffer,
+                          urb->actual_length,
+                          pd->bulk_buffer,
+                          pd->bulk_buffer_size,
+                          &pd->bulk_buffer_count );
+    
+       if( state == INVALID_PACKET ){
+               pd->bulk_buffer_count = 0;
+       } else if( state == VALID_PACKET ){
+               tty = port->tty;
+               if (tty) {
+                       send_tty_data( tty, pd->bulk_buffer, 
pd->bulk_buffer_count );
+               }
+               pd->bulk_buffer_count = 0;
+       }
+       bytes_in += urb->actual_length;
+
+       /* Continue trying to always read  */
+       usb_fill_bulk_urb (port->read_urb, port->serial->dev,
+                          usb_rcvbulkpipe(port->serial->dev,
+                                          port->bulk_in_endpointAddress),
+                          port->read_urb->transfer_buffer,
+                          port->read_urb->transfer_buffer_length,
+                          garmin_read_bulk_callback, port);
+       result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+       if (result)
+               dev_err(&port->dev, "%s - failed resubmitting read urb, error
%d\n", __FUNCTION__, result);
+       return;
+}
+
+static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct tty_struct *tty;
+       struct garmin_usb_header header;
+       int result;
+       int state;
+       struct garmin_serial * pd;  /* private data */
+        
+       pd = ( struct garmin_serial* )usb_get_serial_data( port->serial );
+      
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dbg("%s - urb shutting down with status: %d",
+                   __FUNCTION__, urb->status);
+               return;
+       default:
+               dbg("%s - nonzero urb status received: %d",
+                   __FUNCTION__, urb->status);
+               goto exit;
+       }
+    
+       state = packetize( urb->transfer_buffer,
+                          urb->actual_length,
+                          pd->int_buffer,
+                          pd->int_buffer_size,
+                          &pd->int_buffer_count );
+    
+       if( state == INVALID_PACKET ){
+               dbg("Invalid packet interrupt in");
+               pd->int_buffer_count = 0;
+       } else if( state == VALID_PACKET ){
+               /* memcpy to avoid alignment issues */
+               memcpy( &header, pd->int_buffer, HEADER_SIZE );
+               switch( header.type ){
+               case TRANSPORT_TYPE:
+                       switch( header.id ){
+                       case BULK_DATA_READY_ID:
+                               dbg("Bulk data ready");
+                               /* we are already reading bulk pipe,
+                                  so do nothing */
+                                        break;
+                       case SESSION_STARTED_ID:
+                                       /* received the session started reply 
to 
+                                  the request sent in garmin_open() */
+                               dbg("Session started");
+                               pd->session_started = 1;
+                       break;
+                       default:
+                                       dbg("Unknown TRANSPORT_TYPE id %d", 
header.id );
+                       } /* switch( id ) */
+               case APPLICATION_TYPE:
+                       tty = port->tty;
+                       if (tty) {
+                                       dbg("int send tty");
+                                       send_tty_data( tty, pd->int_buffer, 
pd->int_buffer_count );
+                       }
+                       break;
+               default:
+                       dbg("Unknown Packet type %d", header.type );
+               } /* switch( type ) */  
+       /* reset buffer count */
+       pd->int_buffer_count = 0;
+       }
+    
+exit:
+       result = usb_submit_urb (urb, GFP_ATOMIC);
+       if (result)
+               dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt 
urb\n",
+                       __FUNCTION__, result);
+}
+
+
+static void garmin_throttle (struct usb_serial_port *port)
+{
+       //TODO: could set this so that it will drop packets instead of push them
+       //on the tty buffer, but for now, do nothing
+       dbg("%s - port %d", __FUNCTION__, port->number);
+}
+
+
+static void garmin_unthrottle (struct usb_serial_port *port)
+{
+       //TODO: could start accepting packets again, but since throttle does
nothing, follow suit.
+       dbg("%s - port %d", __FUNCTION__, port->number);
+}
+
+
+static int garmin_probe (struct usb_serial *serial, const struct
usb_device_id *id)
+{
+       int retval = 0;
+       return retval;
+}
+
+static int garmin_calc_num_ports (struct usb_serial *serial)
+{
+       int num_ports = (int)(long)(usb_get_serial_data(serial));
+
+       if (num_ports)
+               usb_set_serial_data(serial, NULL);
+
+       return num_ports;
+}
+
+
+static int garmin_attach (struct usb_serial *serial)
+{
+       dbg("%s", __FUNCTION__);
+       return 0;
+}
+
+static void garmin_shutdown (struct usb_serial *serial)
+{
+       dbg("%s", __FUNCTION__);
+}
+
+static int garmin_ioctl (struct usb_serial_port *port, struct file *
file, unsigned int cmd, unsigned long arg)
+{      
+       dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
+       return -ENOIOCTLCMD;
+}
+
+
+/* This function is all nice and good, but we don't change anything
based on it :) */
+static void garmin_set_termios (struct usb_serial_port *port, struct
termios *old_termios)
+{
+       unsigned int cflag;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       if ((!port->tty) || (!port->tty->termios)) {
+               dbg("%s - no tty structures", __FUNCTION__);
+               return;
+       }
+
+       cflag = port->tty->termios->c_cflag;
+       /* check that they really want us to change something */
+       if (old_termios) {
+               if ((cflag == old_termios->c_cflag) &&
+                   (RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
RELEVANT_IFLAG(old_termios->c_iflag))) {
+                       dbg("%s - nothing to change...", __FUNCTION__);
+                       return;
+               }
+       }
+
+       /* get the byte size */
+       switch (cflag & CSIZE) {
+               case CS5:       dbg("%s - data bits = 5", __FUNCTION__);   
break;
+               case CS6:       dbg("%s - data bits = 6", __FUNCTION__);   
break;
+               case CS7:       dbg("%s - data bits = 7", __FUNCTION__);   
break;
+               default:
+               case CS8:       dbg("%s - data bits = 8", __FUNCTION__);   
break;
+       }
+       
+       /* determine the parity */
+       if (cflag & PARENB)
+               if (cflag & PARODD)
+                       dbg("%s - parity = odd", __FUNCTION__);
+               else
+                       dbg("%s - parity = even", __FUNCTION__);
+       else
+               dbg("%s - parity = none", __FUNCTION__);
+
+       /* figure out the stop bits requested */
+       if (cflag & CSTOPB)
+               dbg("%s - stop bits = 2", __FUNCTION__);
+       else
+               dbg("%s - stop bits = 1", __FUNCTION__);
+
+       
+       /* figure out the flow control settings */
+       if (cflag & CRTSCTS)
+               dbg("%s - RTS/CTS is enabled", __FUNCTION__);
+       else
+               dbg("%s - RTS/CTS is disabled", __FUNCTION__);
+       
+       /* determine software flow control */
+       if (I_IXOFF(port->tty))
+               dbg("%s - XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+                   __FUNCTION__, START_CHAR(port->tty), STOP_CHAR(port->tty));
+       else
+               dbg("%s - XON/XOFF is disabled", __FUNCTION__);
+
+       /* get the baud rate wanted */
+       dbg("%s - baud rate = %d", __FUNCTION__, tty_get_baud_rate(port->tty));
+
+       return;
+}
+
+
+/*
+ accumulate a full packet in buffer
+ return status of packet in buffer after adding data
+*/
+static int packetize( char *data, int data_size, char *buffer, int
buffer_size, int *buffer_count )
+{
+       int new_size;
+       struct garmin_usb_header header;
+
+       /* if new data will fit into buffer, copy it in */
+       new_size = *buffer_count + data_size;
+
+       if( new_size > buffer_size ){
+               dbg("total data size %d bytes is bigger than buffer %d bytes",
new_size, buffer_size );
+               return INVALID_PACKET;
+       }
+    
+       memcpy( &buffer[ *buffer_count ], data, data_size);
+
+       /* packet is large enough to have the header*/
+       if( new_size >= HEADER_SIZE ){
+               /* packet header sanity check */
+
+               /* copy the header to avoid any alignment issues */
+               memcpy( &header, buffer, HEADER_SIZE );
+               if( header.type != TRANSPORT_TYPE && header.type != 
APPLICATION_TYPE ){
+                       dbg("header unknown type %d", header.type );
+                       return INVALID_PACKET;
+               }
+
+               if( header.size > (buffer_size - HEADER_SIZE ) ){
+                               dbg("header data size too big for buffer, %u 
data bytes",
header.size );
+                               return INVALID_PACKET;
+               }
+
+               if( header.res1 != 0 ||
+                   header.res2 != 0 || 
+                   header.res3 != 0 ||
+                   header.res4 != 0 ){
+                       dbg("header non-zero reserved area");
+                       return INVALID_PACKET;
+               }
+     
+               /* passed sanity check, buffer count is now new_size */
+               *buffer_count = new_size;        
+    
+               /* now check to see if all the data is received  */
+               /* new_size =  size of data section of the packet received so 
far */
+               new_size -= HEADER_SIZE;
+               if( new_size > header.size ){
+                       dbg("Too much data: size %d, header size %d", new_size, 
header.size);
+                       return INVALID_PACKET;
+               }
+               else if( new_size == header.size ){
+                       return VALID_PACKET;
+               }
+               else{
+                       return ACCUMULATE_PACKET;
+               }    
+       }
+
+       /* not enough data for the full header, so just update 
+       count and return accumulate */
+       *buffer_count = new_size;
+       return ACCUMULATE_PACKET;    
+
+}   /* packetize() */
+
+
+
+static int __init garmin_init (void)
+{
+       int retval;
+
+       retval = usb_serial_register(&generic_device);
+       if (retval)
+               goto failed_serial_register;
+       retval = usb_register(&garmin_driver);
+       if (retval) 
+               goto failed_register;
+       info(DRIVER_DESC " " DRIVER_VERSION);
+
+       return 0;
+    
+failed_serial_register:
+       usb_serial_deregister(&generic_device);
+failed_register:
+       return retval;
+}
+
+
+static void __exit garmin_exit (void)
+{
+       usb_deregister (&garmin_driver);
+       usb_serial_deregister (&generic_device);
+}
+
+
+module_init(garmin_init);
+module_exit(garmin_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
diff -u -r -N /usr/src/linux-2.6.9_default/drivers/usb/serial/garmin_usb_tty.h
./drivers/usb/serial/garmin_usb_tty.h
--- /usr/src/linux-2.6.9_default/drivers/usb/serial/garmin_usb_tty.h    
1970-01-01
00:00:00.000000000 +0000
+++ ./drivers/usb/serial/garmin_usb_tty.h       2004-11-08 00:17:25.678445536 
+0000
@@ -0,0 +1,58 @@
+/*
+ * Garmin GPS USB to serial interface
+ * 
+ * Copyright (C) 2004 Martin Boos <[EMAIL PROTECTED]>
+ *
+ * Based on:
+ * USB HandSpring garmin, Palm m50x, and Sony Clie driver
+ * (supports all of the Palm OS USB devices)
+ *
+ *     Copyright (C) 1999 - 2004
+ *         Greg Kroah-Hartman ([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.
+ *
+ * See Documentation/usb/usb-serial.txt for more information on using
this driver
+ */
+
+#ifndef __LINUX_USB_SERIAL_GARMIN_H
+#define __LINUX_USB_SERIAL_GARMIN_H
+
+#define GARMIN_VENDOR_ID               0x091E
+#define GARMIN_GPSMAP_60_ID     0x0003
+
+/* USB packet types */
+#define TRANSPORT_TYPE    0
+#define APPLICATION_TYPE 20
+
+/* TRANSPORT_TYPE packet IDs */
+#define BULK_DATA_READY_ID      2
+#define START_SESSION_ID        5
+#define SESSION_STARTED_ID      6
+
+
+struct garmin_usb_header{
+       __u8    type;
+       __u8    res1;
+       __u8    res2;
+       __u8    res3;
+       __u16   id;
+       __u16   res4;
+       __u32   size;
+};
+
+struct garmin_serial {
+       char *  int_buffer;
+       int     int_buffer_count;
+       int     int_buffer_size;
+       char *  bulk_buffer;
+       int     bulk_buffer_count;
+       int     bulk_buffer_size;
+       int     session_started;
+};
+
+#endif
+


-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE
LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to