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