| From b4026c4584cd70858d4d3450abfb1cd0714d4f32 Mon Sep 17 00:00:00 2001 |
| From: Hermann Kneissel <herkne@gmx.de> |
| Date: Fri, 29 Apr 2011 08:58:43 +0200 |
| Subject: USB: gamin_gps: Fix for data transfer problems in native |
| mode |
| |
| From: Hermann Kneissel <herkne@gmx.de> |
| |
| commit b4026c4584cd70858d4d3450abfb1cd0714d4f32 upstream. |
| |
| This patch fixes a problem where data received from the gps is sometimes |
| transferred incompletely to the serial port. If used in native mode now |
| all data received via the bulk queue will be forwarded to the serial |
| port. |
| |
| Signed-off-by: Hermann Kneissel <herkne@gmx.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/usb/serial/garmin_gps.c | 20 +++++++++++++------- |
| 1 file changed, 13 insertions(+), 7 deletions(-) |
| |
| --- a/drivers/usb/serial/garmin_gps.c |
| +++ b/drivers/usb/serial/garmin_gps.c |
| @@ -1,7 +1,7 @@ |
| /* |
| * Garmin GPS driver |
| * |
| - * Copyright (C) 2006-2009 Hermann Kneissel herkne@users.sourceforge.net |
| + * Copyright (C) 2006-2011 Hermann Kneissel herkne@gmx.de |
| * |
| * The latest version of the driver can be found at |
| * http://sourceforge.net/projects/garmin-gps/ |
| @@ -51,7 +51,7 @@ static int debug; |
| */ |
| |
| #define VERSION_MAJOR 0 |
| -#define VERSION_MINOR 33 |
| +#define VERSION_MINOR 36 |
| |
| #define _STR(s) #s |
| #define _DRIVER_VERSION(a, b) "v" _STR(a) "." _STR(b) |
| @@ -411,6 +411,7 @@ static int gsp_send_ack(struct garmin_da |
| */ |
| static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count) |
| { |
| + unsigned long flags; |
| const __u8 *recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET; |
| __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer; |
| |
| @@ -459,7 +460,9 @@ static int gsp_rec_packet(struct garmin_ |
| /* if this was an abort-transfer command, flush all |
| queued data. */ |
| if (isAbortTrfCmnd(garmin_data_p->inbuffer)) { |
| + spin_lock_irqsave(&garmin_data_p->lock, flags); |
| garmin_data_p->flags |= FLAGS_DROP_DATA; |
| + spin_unlock_irqrestore(&garmin_data_p->lock, flags); |
| pkt_clear(garmin_data_p); |
| } |
| |
| @@ -944,7 +947,7 @@ static int garmin_open(struct tty_struct |
| spin_lock_irqsave(&garmin_data_p->lock, flags); |
| garmin_data_p->mode = initial_mode; |
| garmin_data_p->count = 0; |
| - garmin_data_p->flags = 0; |
| + garmin_data_p->flags &= FLAGS_SESSION_REPLY1_SEEN; |
| spin_unlock_irqrestore(&garmin_data_p->lock, flags); |
| |
| /* shutdown any bulk reads that might be going on */ |
| @@ -1179,7 +1182,8 @@ static int garmin_write_room(struct tty_ |
| |
| |
| static void garmin_read_process(struct garmin_data *garmin_data_p, |
| - unsigned char *data, unsigned data_length) |
| + unsigned char *data, unsigned data_length, |
| + int bulk_data) |
| { |
| unsigned long flags; |
| |
| @@ -1194,7 +1198,8 @@ static void garmin_read_process(struct g |
| send it directly to the tty port */ |
| if (garmin_data_p->flags & FLAGS_QUEUING) { |
| pkt_add(garmin_data_p, data, data_length); |
| - } else if (getLayerId(data) == GARMIN_LAYERID_APPL) { |
| + } else if (bulk_data || |
| + getLayerId(data) == GARMIN_LAYERID_APPL) { |
| |
| spin_lock_irqsave(&garmin_data_p->lock, flags); |
| garmin_data_p->flags |= APP_RESP_SEEN; |
| @@ -1238,7 +1243,7 @@ static void garmin_read_bulk_callback(st |
| usb_serial_debug_data(debug, &port->dev, |
| __func__, urb->actual_length, data); |
| |
| - garmin_read_process(garmin_data_p, data, urb->actual_length); |
| + garmin_read_process(garmin_data_p, data, urb->actual_length, 1); |
| |
| if (urb->actual_length == 0 && |
| 0 != (garmin_data_p->flags & FLAGS_BULK_IN_RESTART)) { |
| @@ -1348,7 +1353,7 @@ static void garmin_read_int_callback(str |
| __func__, garmin_data_p->serial_num); |
| } |
| |
| - garmin_read_process(garmin_data_p, data, urb->actual_length); |
| + garmin_read_process(garmin_data_p, data, urb->actual_length, 0); |
| |
| port->interrupt_in_urb->dev = port->serial->dev; |
| retval = usb_submit_urb(urb, GFP_ATOMIC); |
| @@ -1463,6 +1468,7 @@ static int garmin_attach(struct usb_seri |
| garmin_data_p->timer.function = timeout_handler; |
| garmin_data_p->port = port; |
| garmin_data_p->state = 0; |
| + garmin_data_p->flags = 0; |
| garmin_data_p->count = 0; |
| usb_set_serial_port_data(port, garmin_data_p); |
| |