diff options
Diffstat (limited to 'drivers/usb/serial/garmin_gps.c')
-rw-r--r-- | drivers/usb/serial/garmin_gps.c | 214 |
1 files changed, 86 insertions, 128 deletions
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index ee25a3fe3b09..8839f1c70b7f 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Garmin GPS driver | 2 | * Garmin GPS driver |
3 | * | 3 | * |
4 | * Copyright (C) 2006,2007 Hermann Kneissel herkne@users.sourceforge.net | 4 | * Copyright (C) 2006-2009 Hermann Kneissel herkne@users.sourceforge.net |
5 | * | 5 | * |
6 | * The latest version of the driver can be found at | 6 | * The latest version of the driver can be found at |
7 | * http://sourceforge.net/projects/garmin-gps/ | 7 | * http://sourceforge.net/projects/garmin-gps/ |
@@ -51,7 +51,7 @@ static int debug; | |||
51 | */ | 51 | */ |
52 | 52 | ||
53 | #define VERSION_MAJOR 0 | 53 | #define VERSION_MAJOR 0 |
54 | #define VERSION_MINOR 31 | 54 | #define VERSION_MINOR 33 |
55 | 55 | ||
56 | #define _STR(s) #s | 56 | #define _STR(s) #s |
57 | #define _DRIVER_VERSION(a, b) "v" _STR(a) "." _STR(b) | 57 | #define _DRIVER_VERSION(a, b) "v" _STR(a) "." _STR(b) |
@@ -129,7 +129,6 @@ struct garmin_data { | |||
129 | __u8 state; | 129 | __u8 state; |
130 | __u16 flags; | 130 | __u16 flags; |
131 | __u8 mode; | 131 | __u8 mode; |
132 | __u8 ignorePkts; | ||
133 | __u8 count; | 132 | __u8 count; |
134 | __u8 pkt_id; | 133 | __u8 pkt_id; |
135 | __u32 serial_num; | 134 | __u32 serial_num; |
@@ -141,8 +140,6 @@ struct garmin_data { | |||
141 | __u8 inbuffer [GPS_IN_BUFSIZ]; /* tty -> usb */ | 140 | __u8 inbuffer [GPS_IN_BUFSIZ]; /* tty -> usb */ |
142 | __u8 outbuffer[GPS_OUT_BUFSIZ]; /* usb -> tty */ | 141 | __u8 outbuffer[GPS_OUT_BUFSIZ]; /* usb -> tty */ |
143 | __u8 privpkt[4*6]; | 142 | __u8 privpkt[4*6]; |
144 | atomic_t req_count; | ||
145 | atomic_t resp_count; | ||
146 | spinlock_t lock; | 143 | spinlock_t lock; |
147 | struct list_head pktlist; | 144 | struct list_head pktlist; |
148 | }; | 145 | }; |
@@ -170,6 +167,8 @@ struct garmin_data { | |||
170 | #define FLAGS_BULK_IN_ACTIVE 0x0020 | 167 | #define FLAGS_BULK_IN_ACTIVE 0x0020 |
171 | #define FLAGS_BULK_IN_RESTART 0x0010 | 168 | #define FLAGS_BULK_IN_RESTART 0x0010 |
172 | #define FLAGS_THROTTLED 0x0008 | 169 | #define FLAGS_THROTTLED 0x0008 |
170 | #define APP_REQ_SEEN 0x0004 | ||
171 | #define APP_RESP_SEEN 0x0002 | ||
173 | #define CLEAR_HALT_REQUIRED 0x0001 | 172 | #define CLEAR_HALT_REQUIRED 0x0001 |
174 | 173 | ||
175 | #define FLAGS_QUEUING 0x0100 | 174 | #define FLAGS_QUEUING 0x0100 |
@@ -184,20 +183,16 @@ struct garmin_data { | |||
184 | 183 | ||
185 | 184 | ||
186 | /* function prototypes */ | 185 | /* function prototypes */ |
187 | static void gsp_next_packet(struct garmin_data *garmin_data_p); | 186 | static int gsp_next_packet(struct garmin_data *garmin_data_p); |
188 | static int garmin_write_bulk(struct usb_serial_port *port, | 187 | static int garmin_write_bulk(struct usb_serial_port *port, |
189 | const unsigned char *buf, int count, | 188 | const unsigned char *buf, int count, |
190 | int dismiss_ack); | 189 | int dismiss_ack); |
191 | 190 | ||
192 | /* some special packets to be send or received */ | 191 | /* some special packets to be send or received */ |
193 | static unsigned char const GARMIN_START_SESSION_REQ[] | 192 | static unsigned char const GARMIN_START_SESSION_REQ[] |
194 | = { 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0 }; | 193 | = { 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0 }; |
195 | static unsigned char const GARMIN_START_SESSION_REQ2[] | ||
196 | = { 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 }; | ||
197 | static unsigned char const GARMIN_START_SESSION_REPLY[] | 194 | static unsigned char const GARMIN_START_SESSION_REPLY[] |
198 | = { 0, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0 }; | 195 | = { 0, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0 }; |
199 | static unsigned char const GARMIN_SESSION_ACTIVE_REPLY[] | ||
200 | = { 0, 0, 0, 0, 17, 0, 0, 0, 4, 0, 0, 0, 0, 16, 0, 0 }; | ||
201 | static unsigned char const GARMIN_BULK_IN_AVAIL_REPLY[] | 196 | static unsigned char const GARMIN_BULK_IN_AVAIL_REPLY[] |
202 | = { 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 }; | 197 | = { 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 }; |
203 | static unsigned char const GARMIN_APP_LAYER_REPLY[] | 198 | static unsigned char const GARMIN_APP_LAYER_REPLY[] |
@@ -233,13 +228,6 @@ static struct usb_driver garmin_driver = { | |||
233 | }; | 228 | }; |
234 | 229 | ||
235 | 230 | ||
236 | static inline int noResponseFromAppLayer(struct garmin_data *garmin_data_p) | ||
237 | { | ||
238 | return atomic_read(&garmin_data_p->req_count) == | ||
239 | atomic_read(&garmin_data_p->resp_count); | ||
240 | } | ||
241 | |||
242 | |||
243 | static inline int getLayerId(const __u8 *usbPacket) | 231 | static inline int getLayerId(const __u8 *usbPacket) |
244 | { | 232 | { |
245 | return __le32_to_cpup((__le32 *)(usbPacket)); | 233 | return __le32_to_cpup((__le32 *)(usbPacket)); |
@@ -325,8 +313,11 @@ static int pkt_add(struct garmin_data *garmin_data_p, | |||
325 | state = garmin_data_p->state; | 313 | state = garmin_data_p->state; |
326 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | 314 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); |
327 | 315 | ||
316 | dbg("%s - added: pkt: %d - %d bytes", | ||
317 | __func__, pkt->seq, data_length); | ||
318 | |||
328 | /* in serial mode, if someone is waiting for data from | 319 | /* in serial mode, if someone is waiting for data from |
329 | the device, iconvert and send the next packet to tty. */ | 320 | the device, convert and send the next packet to tty. */ |
330 | if (result && (state == STATE_GSP_WAIT_DATA)) | 321 | if (result && (state == STATE_GSP_WAIT_DATA)) |
331 | gsp_next_packet(garmin_data_p); | 322 | gsp_next_packet(garmin_data_p); |
332 | } | 323 | } |
@@ -411,7 +402,7 @@ static int gsp_send_ack(struct garmin_data *garmin_data_p, __u8 pkt_id) | |||
411 | /* | 402 | /* |
412 | * called for a complete packet received from tty layer | 403 | * called for a complete packet received from tty layer |
413 | * | 404 | * |
414 | * the complete packet (pkzid ... cksum) is in garmin_data_p->inbuf starting | 405 | * the complete packet (pktid ... cksum) is in garmin_data_p->inbuf starting |
415 | * at GSP_INITIAL_OFFSET. | 406 | * at GSP_INITIAL_OFFSET. |
416 | * | 407 | * |
417 | * count - number of bytes in the input buffer including space reserved for | 408 | * count - number of bytes in the input buffer including space reserved for |
@@ -501,7 +492,6 @@ static int gsp_receive(struct garmin_data *garmin_data_p, | |||
501 | unsigned long flags; | 492 | unsigned long flags; |
502 | int offs = 0; | 493 | int offs = 0; |
503 | int ack_or_nak_seen = 0; | 494 | int ack_or_nak_seen = 0; |
504 | int i = 0; | ||
505 | __u8 *dest; | 495 | __u8 *dest; |
506 | int size; | 496 | int size; |
507 | /* dleSeen: set if last byte read was a DLE */ | 497 | /* dleSeen: set if last byte read was a DLE */ |
@@ -519,8 +509,8 @@ static int gsp_receive(struct garmin_data *garmin_data_p, | |||
519 | skip = garmin_data_p->flags & FLAGS_GSP_SKIP; | 509 | skip = garmin_data_p->flags & FLAGS_GSP_SKIP; |
520 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | 510 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); |
521 | 511 | ||
522 | dbg("%s - dle=%d skip=%d size=%d count=%d", | 512 | /* dbg("%s - dle=%d skip=%d size=%d count=%d", |
523 | __func__, dleSeen, skip, size, count); | 513 | __func__, dleSeen, skip, size, count); */ |
524 | 514 | ||
525 | if (size == 0) | 515 | if (size == 0) |
526 | size = GSP_INITIAL_OFFSET; | 516 | size = GSP_INITIAL_OFFSET; |
@@ -568,7 +558,6 @@ static int gsp_receive(struct garmin_data *garmin_data_p, | |||
568 | } else if (!skip) { | 558 | } else if (!skip) { |
569 | 559 | ||
570 | if (dleSeen) { | 560 | if (dleSeen) { |
571 | dbg("non-masked DLE at %d - restarting", i); | ||
572 | size = GSP_INITIAL_OFFSET; | 561 | size = GSP_INITIAL_OFFSET; |
573 | dleSeen = 0; | 562 | dleSeen = 0; |
574 | } | 563 | } |
@@ -599,19 +588,19 @@ static int gsp_receive(struct garmin_data *garmin_data_p, | |||
599 | else | 588 | else |
600 | garmin_data_p->flags &= ~FLAGS_GSP_DLESEEN; | 589 | garmin_data_p->flags &= ~FLAGS_GSP_DLESEEN; |
601 | 590 | ||
602 | if (ack_or_nak_seen) | ||
603 | garmin_data_p->state = STATE_GSP_WAIT_DATA; | ||
604 | |||
605 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | 591 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); |
606 | 592 | ||
607 | if (ack_or_nak_seen) | 593 | if (ack_or_nak_seen) { |
608 | gsp_next_packet(garmin_data_p); | 594 | if (gsp_next_packet(garmin_data_p) > 0) |
595 | garmin_data_p->state = STATE_ACTIVE; | ||
596 | else | ||
597 | garmin_data_p->state = STATE_GSP_WAIT_DATA; | ||
598 | } | ||
609 | return count; | 599 | return count; |
610 | } | 600 | } |
611 | 601 | ||
612 | 602 | ||
613 | 603 | ||
614 | |||
615 | /* | 604 | /* |
616 | * Sends a usb packet to the tty | 605 | * Sends a usb packet to the tty |
617 | * | 606 | * |
@@ -733,29 +722,28 @@ static int gsp_send(struct garmin_data *garmin_data_p, | |||
733 | } | 722 | } |
734 | 723 | ||
735 | 724 | ||
736 | |||
737 | |||
738 | |||
739 | /* | 725 | /* |
740 | * Process the next pending data packet - if there is one | 726 | * Process the next pending data packet - if there is one |
741 | */ | 727 | */ |
742 | static void gsp_next_packet(struct garmin_data *garmin_data_p) | 728 | static int gsp_next_packet(struct garmin_data *garmin_data_p) |
743 | { | 729 | { |
730 | int result = 0; | ||
744 | struct garmin_packet *pkt = NULL; | 731 | struct garmin_packet *pkt = NULL; |
745 | 732 | ||
746 | while ((pkt = pkt_pop(garmin_data_p)) != NULL) { | 733 | while ((pkt = pkt_pop(garmin_data_p)) != NULL) { |
747 | dbg("%s - next pkt: %d", __func__, pkt->seq); | 734 | dbg("%s - next pkt: %d", __func__, pkt->seq); |
748 | if (gsp_send(garmin_data_p, pkt->data, pkt->size) > 0) { | 735 | result = gsp_send(garmin_data_p, pkt->data, pkt->size); |
736 | if (result > 0) { | ||
749 | kfree(pkt); | 737 | kfree(pkt); |
750 | return; | 738 | return result; |
751 | } | 739 | } |
752 | kfree(pkt); | 740 | kfree(pkt); |
753 | } | 741 | } |
742 | return result; | ||
754 | } | 743 | } |
755 | 744 | ||
756 | 745 | ||
757 | 746 | ||
758 | |||
759 | /****************************************************************************** | 747 | /****************************************************************************** |
760 | * garmin native mode | 748 | * garmin native mode |
761 | ******************************************************************************/ | 749 | ******************************************************************************/ |
@@ -888,14 +876,6 @@ static int garmin_clear(struct garmin_data *garmin_data_p) | |||
888 | unsigned long flags; | 876 | unsigned long flags; |
889 | int status = 0; | 877 | int status = 0; |
890 | 878 | ||
891 | struct usb_serial_port *port = garmin_data_p->port; | ||
892 | |||
893 | if (port != NULL && atomic_read(&garmin_data_p->resp_count)) { | ||
894 | /* send a terminate command */ | ||
895 | status = garmin_write_bulk(port, GARMIN_STOP_TRANSFER_REQ, | ||
896 | sizeof(GARMIN_STOP_TRANSFER_REQ), 1); | ||
897 | } | ||
898 | |||
899 | /* flush all queued data */ | 879 | /* flush all queued data */ |
900 | pkt_clear(garmin_data_p); | 880 | pkt_clear(garmin_data_p); |
901 | 881 | ||
@@ -908,16 +888,12 @@ static int garmin_clear(struct garmin_data *garmin_data_p) | |||
908 | } | 888 | } |
909 | 889 | ||
910 | 890 | ||
911 | |||
912 | |||
913 | |||
914 | |||
915 | static int garmin_init_session(struct usb_serial_port *port) | 891 | static int garmin_init_session(struct usb_serial_port *port) |
916 | { | 892 | { |
917 | unsigned long flags; | ||
918 | struct usb_serial *serial = port->serial; | 893 | struct usb_serial *serial = port->serial; |
919 | struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); | 894 | struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); |
920 | int status = 0; | 895 | int status = 0; |
896 | int i = 0; | ||
921 | 897 | ||
922 | if (status == 0) { | 898 | if (status == 0) { |
923 | usb_kill_urb(port->interrupt_in_urb); | 899 | usb_kill_urb(port->interrupt_in_urb); |
@@ -931,30 +907,25 @@ static int garmin_init_session(struct usb_serial_port *port) | |||
931 | __func__, status); | 907 | __func__, status); |
932 | } | 908 | } |
933 | 909 | ||
910 | /* | ||
911 | * using the initialization method from gpsbabel. See comments in | ||
912 | * gpsbabel/jeeps/gpslibusb.c gusb_reset_toggles() | ||
913 | */ | ||
934 | if (status == 0) { | 914 | if (status == 0) { |
935 | dbg("%s - starting session ...", __func__); | 915 | dbg("%s - starting session ...", __func__); |
936 | garmin_data_p->state = STATE_ACTIVE; | 916 | garmin_data_p->state = STATE_ACTIVE; |
937 | status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ, | ||
938 | sizeof(GARMIN_START_SESSION_REQ), 0); | ||
939 | |||
940 | if (status >= 0) { | ||
941 | |||
942 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
943 | garmin_data_p->ignorePkts++; | ||
944 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
945 | 917 | ||
946 | /* not needed, but the win32 driver does it too ... */ | 918 | for (i = 0; i < 3; i++) { |
947 | status = garmin_write_bulk(port, | 919 | status = garmin_write_bulk(port, |
948 | GARMIN_START_SESSION_REQ2, | 920 | GARMIN_START_SESSION_REQ, |
949 | sizeof(GARMIN_START_SESSION_REQ2), 0); | 921 | sizeof(GARMIN_START_SESSION_REQ), 0); |
950 | if (status >= 0) { | 922 | |
951 | status = 0; | 923 | if (status < 0) |
952 | spin_lock_irqsave(&garmin_data_p->lock, flags); | 924 | break; |
953 | garmin_data_p->ignorePkts++; | ||
954 | spin_unlock_irqrestore(&garmin_data_p->lock, | ||
955 | flags); | ||
956 | } | ||
957 | } | 925 | } |
926 | |||
927 | if (status > 0) | ||
928 | status = 0; | ||
958 | } | 929 | } |
959 | 930 | ||
960 | return status; | 931 | return status; |
@@ -962,8 +933,6 @@ static int garmin_init_session(struct usb_serial_port *port) | |||
962 | 933 | ||
963 | 934 | ||
964 | 935 | ||
965 | |||
966 | |||
967 | static int garmin_open(struct tty_struct *tty, | 936 | static int garmin_open(struct tty_struct *tty, |
968 | struct usb_serial_port *port, struct file *filp) | 937 | struct usb_serial_port *port, struct file *filp) |
969 | { | 938 | { |
@@ -977,8 +946,6 @@ static int garmin_open(struct tty_struct *tty, | |||
977 | garmin_data_p->mode = initial_mode; | 946 | garmin_data_p->mode = initial_mode; |
978 | garmin_data_p->count = 0; | 947 | garmin_data_p->count = 0; |
979 | garmin_data_p->flags = 0; | 948 | garmin_data_p->flags = 0; |
980 | atomic_set(&garmin_data_p->req_count, 0); | ||
981 | atomic_set(&garmin_data_p->resp_count, 0); | ||
982 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | 949 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); |
983 | 950 | ||
984 | /* shutdown any bulk reads that might be going on */ | 951 | /* shutdown any bulk reads that might be going on */ |
@@ -1006,6 +973,7 @@ static void garmin_close(struct usb_serial_port *port) | |||
1006 | return; | 973 | return; |
1007 | 974 | ||
1008 | mutex_lock(&port->serial->disc_mutex); | 975 | mutex_lock(&port->serial->disc_mutex); |
976 | |||
1009 | if (!port->serial->disconnected) | 977 | if (!port->serial->disconnected) |
1010 | garmin_clear(garmin_data_p); | 978 | garmin_clear(garmin_data_p); |
1011 | 979 | ||
@@ -1013,25 +981,17 @@ static void garmin_close(struct usb_serial_port *port) | |||
1013 | usb_kill_urb(port->read_urb); | 981 | usb_kill_urb(port->read_urb); |
1014 | usb_kill_urb(port->write_urb); | 982 | usb_kill_urb(port->write_urb); |
1015 | 983 | ||
1016 | if (!port->serial->disconnected) { | 984 | /* keep reset state so we know that we must start a new session */ |
1017 | if (noResponseFromAppLayer(garmin_data_p) || | 985 | if (garmin_data_p->state != STATE_RESET) |
1018 | ((garmin_data_p->flags & CLEAR_HALT_REQUIRED) != 0)) { | ||
1019 | process_resetdev_request(port); | ||
1020 | garmin_data_p->state = STATE_RESET; | ||
1021 | } else { | ||
1022 | garmin_data_p->state = STATE_DISCONNECTED; | ||
1023 | } | ||
1024 | } else { | ||
1025 | garmin_data_p->state = STATE_DISCONNECTED; | 986 | garmin_data_p->state = STATE_DISCONNECTED; |
1026 | } | 987 | |
1027 | mutex_unlock(&port->serial->disc_mutex); | 988 | mutex_unlock(&port->serial->disc_mutex); |
1028 | } | 989 | } |
1029 | 990 | ||
991 | |||
1030 | static void garmin_write_bulk_callback(struct urb *urb) | 992 | static void garmin_write_bulk_callback(struct urb *urb) |
1031 | { | 993 | { |
1032 | unsigned long flags; | ||
1033 | struct usb_serial_port *port = urb->context; | 994 | struct usb_serial_port *port = urb->context; |
1034 | int status = urb->status; | ||
1035 | 995 | ||
1036 | if (port) { | 996 | if (port) { |
1037 | struct garmin_data *garmin_data_p = | 997 | struct garmin_data *garmin_data_p = |
@@ -1039,20 +999,13 @@ static void garmin_write_bulk_callback(struct urb *urb) | |||
1039 | 999 | ||
1040 | dbg("%s - port %d", __func__, port->number); | 1000 | dbg("%s - port %d", __func__, port->number); |
1041 | 1001 | ||
1042 | if (GARMIN_LAYERID_APPL == getLayerId(urb->transfer_buffer) | 1002 | if (GARMIN_LAYERID_APPL == getLayerId(urb->transfer_buffer)) { |
1043 | && (garmin_data_p->mode == MODE_GARMIN_SERIAL)) { | ||
1044 | gsp_send_ack(garmin_data_p, | ||
1045 | ((__u8 *)urb->transfer_buffer)[4]); | ||
1046 | } | ||
1047 | 1003 | ||
1048 | if (status) { | 1004 | if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { |
1049 | dbg("%s - nonzero write bulk status received: %d", | 1005 | gsp_send_ack(garmin_data_p, |
1050 | __func__, status); | 1006 | ((__u8 *)urb->transfer_buffer)[4]); |
1051 | spin_lock_irqsave(&garmin_data_p->lock, flags); | 1007 | } |
1052 | garmin_data_p->flags |= CLEAR_HALT_REQUIRED; | ||
1053 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1054 | } | 1008 | } |
1055 | |||
1056 | usb_serial_port_softint(port); | 1009 | usb_serial_port_softint(port); |
1057 | } | 1010 | } |
1058 | 1011 | ||
@@ -1108,7 +1061,11 @@ static int garmin_write_bulk(struct usb_serial_port *port, | |||
1108 | urb->transfer_flags |= URB_ZERO_PACKET; | 1061 | urb->transfer_flags |= URB_ZERO_PACKET; |
1109 | 1062 | ||
1110 | if (GARMIN_LAYERID_APPL == getLayerId(buffer)) { | 1063 | if (GARMIN_LAYERID_APPL == getLayerId(buffer)) { |
1111 | atomic_inc(&garmin_data_p->req_count); | 1064 | |
1065 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1066 | garmin_data_p->flags |= APP_REQ_SEEN; | ||
1067 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1068 | |||
1112 | if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { | 1069 | if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { |
1113 | pkt_clear(garmin_data_p); | 1070 | pkt_clear(garmin_data_p); |
1114 | garmin_data_p->state = STATE_GSP_WAIT_DATA; | 1071 | garmin_data_p->state = STATE_GSP_WAIT_DATA; |
@@ -1140,6 +1097,9 @@ static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
1140 | 1097 | ||
1141 | usb_serial_debug_data(debug, &port->dev, __func__, count, buf); | 1098 | usb_serial_debug_data(debug, &port->dev, __func__, count, buf); |
1142 | 1099 | ||
1100 | if (garmin_data_p->state == STATE_RESET) | ||
1101 | return -EIO; | ||
1102 | |||
1143 | /* check for our private packets */ | 1103 | /* check for our private packets */ |
1144 | if (count >= GARMIN_PKTHDR_LENGTH) { | 1104 | if (count >= GARMIN_PKTHDR_LENGTH) { |
1145 | len = PRIVPKTSIZ; | 1105 | len = PRIVPKTSIZ; |
@@ -1184,7 +1144,7 @@ static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
1184 | break; | 1144 | break; |
1185 | 1145 | ||
1186 | case PRIV_PKTID_RESET_REQ: | 1146 | case PRIV_PKTID_RESET_REQ: |
1187 | atomic_inc(&garmin_data_p->req_count); | 1147 | process_resetdev_request(port); |
1188 | break; | 1148 | break; |
1189 | 1149 | ||
1190 | case PRIV_PKTID_SET_DEF_MODE: | 1150 | case PRIV_PKTID_SET_DEF_MODE: |
@@ -1200,8 +1160,6 @@ static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
1200 | } | 1160 | } |
1201 | } | 1161 | } |
1202 | 1162 | ||
1203 | garmin_data_p->ignorePkts = 0; | ||
1204 | |||
1205 | if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { | 1163 | if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { |
1206 | return gsp_receive(garmin_data_p, buf, count); | 1164 | return gsp_receive(garmin_data_p, buf, count); |
1207 | } else { /* MODE_NATIVE */ | 1165 | } else { /* MODE_NATIVE */ |
@@ -1224,31 +1182,33 @@ static int garmin_write_room(struct tty_struct *tty) | |||
1224 | static void garmin_read_process(struct garmin_data *garmin_data_p, | 1182 | static void garmin_read_process(struct garmin_data *garmin_data_p, |
1225 | unsigned char *data, unsigned data_length) | 1183 | unsigned char *data, unsigned data_length) |
1226 | { | 1184 | { |
1185 | unsigned long flags; | ||
1186 | |||
1227 | if (garmin_data_p->flags & FLAGS_DROP_DATA) { | 1187 | if (garmin_data_p->flags & FLAGS_DROP_DATA) { |
1228 | /* abort-transfer cmd is actice */ | 1188 | /* abort-transfer cmd is actice */ |
1229 | dbg("%s - pkt dropped", __func__); | 1189 | dbg("%s - pkt dropped", __func__); |
1230 | } else if (garmin_data_p->state != STATE_DISCONNECTED && | 1190 | } else if (garmin_data_p->state != STATE_DISCONNECTED && |
1231 | garmin_data_p->state != STATE_RESET) { | 1191 | garmin_data_p->state != STATE_RESET) { |
1232 | 1192 | ||
1233 | /* remember any appl.layer packets, so we know | ||
1234 | if a reset is required or not when closing | ||
1235 | the device */ | ||
1236 | if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY, | ||
1237 | sizeof(GARMIN_APP_LAYER_REPLY))) { | ||
1238 | atomic_inc(&garmin_data_p->resp_count); | ||
1239 | } | ||
1240 | |||
1241 | /* if throttling is active or postprecessing is required | 1193 | /* if throttling is active or postprecessing is required |
1242 | put the received data in the input queue, otherwise | 1194 | put the received data in the input queue, otherwise |
1243 | send it directly to the tty port */ | 1195 | send it directly to the tty port */ |
1244 | if (garmin_data_p->flags & FLAGS_QUEUING) { | 1196 | if (garmin_data_p->flags & FLAGS_QUEUING) { |
1245 | pkt_add(garmin_data_p, data, data_length); | 1197 | pkt_add(garmin_data_p, data, data_length); |
1246 | } else if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { | 1198 | } else if (getLayerId(data) == GARMIN_LAYERID_APPL) { |
1247 | if (getLayerId(data) == GARMIN_LAYERID_APPL) | 1199 | |
1200 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1201 | garmin_data_p->flags |= APP_RESP_SEEN; | ||
1202 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1203 | |||
1204 | if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { | ||
1248 | pkt_add(garmin_data_p, data, data_length); | 1205 | pkt_add(garmin_data_p, data, data_length); |
1249 | } else { | 1206 | } else { |
1250 | send_to_tty(garmin_data_p->port, data, data_length); | 1207 | send_to_tty(garmin_data_p->port, data, |
1208 | data_length); | ||
1209 | } | ||
1251 | } | 1210 | } |
1211 | /* ignore system layer packets ... */ | ||
1252 | } | 1212 | } |
1253 | } | 1213 | } |
1254 | 1214 | ||
@@ -1363,8 +1323,6 @@ static void garmin_read_int_callback(struct urb *urb) | |||
1363 | } else { | 1323 | } else { |
1364 | spin_lock_irqsave(&garmin_data_p->lock, flags); | 1324 | spin_lock_irqsave(&garmin_data_p->lock, flags); |
1365 | garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE; | 1325 | garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE; |
1366 | /* do not send this packet to the user */ | ||
1367 | garmin_data_p->ignorePkts = 1; | ||
1368 | spin_unlock_irqrestore(&garmin_data_p->lock, | 1326 | spin_unlock_irqrestore(&garmin_data_p->lock, |
1369 | flags); | 1327 | flags); |
1370 | } | 1328 | } |
@@ -1391,17 +1349,7 @@ static void garmin_read_int_callback(struct urb *urb) | |||
1391 | __func__, garmin_data_p->serial_num); | 1349 | __func__, garmin_data_p->serial_num); |
1392 | } | 1350 | } |
1393 | 1351 | ||
1394 | if (garmin_data_p->ignorePkts) { | 1352 | garmin_read_process(garmin_data_p, data, urb->actual_length); |
1395 | /* this reply belongs to a request generated by the driver, | ||
1396 | ignore it. */ | ||
1397 | dbg("%s - pkt ignored (%d)", | ||
1398 | __func__, garmin_data_p->ignorePkts); | ||
1399 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1400 | garmin_data_p->ignorePkts--; | ||
1401 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1402 | } else { | ||
1403 | garmin_read_process(garmin_data_p, data, urb->actual_length); | ||
1404 | } | ||
1405 | 1353 | ||
1406 | port->interrupt_in_urb->dev = port->serial->dev; | 1354 | port->interrupt_in_urb->dev = port->serial->dev; |
1407 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 1355 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
@@ -1527,7 +1475,7 @@ static int garmin_attach(struct usb_serial *serial) | |||
1527 | } | 1475 | } |
1528 | 1476 | ||
1529 | 1477 | ||
1530 | static void garmin_shutdown(struct usb_serial *serial) | 1478 | static void garmin_disconnect(struct usb_serial *serial) |
1531 | { | 1479 | { |
1532 | struct usb_serial_port *port = serial->port[0]; | 1480 | struct usb_serial_port *port = serial->port[0]; |
1533 | struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); | 1481 | struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); |
@@ -1536,8 +1484,17 @@ static void garmin_shutdown(struct usb_serial *serial) | |||
1536 | 1484 | ||
1537 | usb_kill_urb(port->interrupt_in_urb); | 1485 | usb_kill_urb(port->interrupt_in_urb); |
1538 | del_timer_sync(&garmin_data_p->timer); | 1486 | del_timer_sync(&garmin_data_p->timer); |
1487 | } | ||
1488 | |||
1489 | |||
1490 | static void garmin_release(struct usb_serial *serial) | ||
1491 | { | ||
1492 | struct usb_serial_port *port = serial->port[0]; | ||
1493 | struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); | ||
1494 | |||
1495 | dbg("%s", __func__); | ||
1496 | |||
1539 | kfree(garmin_data_p); | 1497 | kfree(garmin_data_p); |
1540 | usb_set_serial_port_data(port, NULL); | ||
1541 | } | 1498 | } |
1542 | 1499 | ||
1543 | 1500 | ||
@@ -1556,7 +1513,8 @@ static struct usb_serial_driver garmin_device = { | |||
1556 | .throttle = garmin_throttle, | 1513 | .throttle = garmin_throttle, |
1557 | .unthrottle = garmin_unthrottle, | 1514 | .unthrottle = garmin_unthrottle, |
1558 | .attach = garmin_attach, | 1515 | .attach = garmin_attach, |
1559 | .shutdown = garmin_shutdown, | 1516 | .disconnect = garmin_disconnect, |
1517 | .release = garmin_release, | ||
1560 | .write = garmin_write, | 1518 | .write = garmin_write, |
1561 | .write_room = garmin_write_room, | 1519 | .write_room = garmin_write_room, |
1562 | .write_bulk_callback = garmin_write_bulk_callback, | 1520 | .write_bulk_callback = garmin_write_bulk_callback, |