diff options
Diffstat (limited to 'drivers/usb/serial/garmin_gps.c')
-rw-r--r-- | drivers/usb/serial/garmin_gps.c | 219 |
1 files changed, 162 insertions, 57 deletions
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 727852634be9..4b1196a8b09e 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) 2004 Hermann Kneissel herkne@users.sourceforge.net | 4 | * Copyright (C) 2006 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/ |
@@ -37,6 +37,8 @@ | |||
37 | #include <linux/usb.h> | 37 | #include <linux/usb.h> |
38 | #include <linux/usb/serial.h> | 38 | #include <linux/usb/serial.h> |
39 | 39 | ||
40 | #include <linux/version.h> | ||
41 | |||
40 | /* the mode to be set when the port ist opened */ | 42 | /* the mode to be set when the port ist opened */ |
41 | static int initial_mode = 1; | 43 | static int initial_mode = 1; |
42 | 44 | ||
@@ -50,7 +52,7 @@ static int debug = 0; | |||
50 | */ | 52 | */ |
51 | 53 | ||
52 | #define VERSION_MAJOR 0 | 54 | #define VERSION_MAJOR 0 |
53 | #define VERSION_MINOR 23 | 55 | #define VERSION_MINOR 28 |
54 | 56 | ||
55 | #define _STR(s) #s | 57 | #define _STR(s) #s |
56 | #define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b) | 58 | #define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b) |
@@ -164,7 +166,8 @@ struct garmin_data { | |||
164 | #define FLAGS_SESSION_REPLY1_SEEN 0x0080 | 166 | #define FLAGS_SESSION_REPLY1_SEEN 0x0080 |
165 | #define FLAGS_SESSION_REPLY2_SEEN 0x0040 | 167 | #define FLAGS_SESSION_REPLY2_SEEN 0x0040 |
166 | #define FLAGS_BULK_IN_ACTIVE 0x0020 | 168 | #define FLAGS_BULK_IN_ACTIVE 0x0020 |
167 | #define FLAGS_THROTTLED 0x0010 | 169 | #define FLAGS_BULK_IN_RESTART 0x0010 |
170 | #define FLAGS_THROTTLED 0x0008 | ||
168 | #define CLEAR_HALT_REQUIRED 0x0001 | 171 | #define CLEAR_HALT_REQUIRED 0x0001 |
169 | 172 | ||
170 | #define FLAGS_QUEUING 0x0100 | 173 | #define FLAGS_QUEUING 0x0100 |
@@ -224,7 +227,7 @@ static struct usb_driver garmin_driver = { | |||
224 | .probe = usb_serial_probe, | 227 | .probe = usb_serial_probe, |
225 | .disconnect = usb_serial_disconnect, | 228 | .disconnect = usb_serial_disconnect, |
226 | .id_table = id_table, | 229 | .id_table = id_table, |
227 | .no_dynamic_id = 1, | 230 | .no_dynamic_id = 1, |
228 | }; | 231 | }; |
229 | 232 | ||
230 | 233 | ||
@@ -270,7 +273,7 @@ static inline int isAbortTrfCmnd(const unsigned char *buf) | |||
270 | 273 | ||
271 | 274 | ||
272 | static void send_to_tty(struct usb_serial_port *port, | 275 | static void send_to_tty(struct usb_serial_port *port, |
273 | char *data, unsigned int actual_length) | 276 | char *data, unsigned int actual_length) |
274 | { | 277 | { |
275 | struct tty_struct *tty = port->tty; | 278 | struct tty_struct *tty = port->tty; |
276 | 279 | ||
@@ -294,15 +297,15 @@ static void send_to_tty(struct usb_serial_port *port, | |||
294 | * queue a received (usb-)packet for later processing | 297 | * queue a received (usb-)packet for later processing |
295 | */ | 298 | */ |
296 | static int pkt_add(struct garmin_data * garmin_data_p, | 299 | static int pkt_add(struct garmin_data * garmin_data_p, |
297 | unsigned char *data, unsigned int data_length) | 300 | unsigned char *data, unsigned int data_length) |
298 | { | 301 | { |
302 | int state = 0; | ||
299 | int result = 0; | 303 | int result = 0; |
300 | unsigned long flags; | 304 | unsigned long flags; |
301 | struct garmin_packet *pkt; | 305 | struct garmin_packet *pkt; |
302 | 306 | ||
303 | /* process only packets containg data ... */ | 307 | /* process only packets containg data ... */ |
304 | if (data_length) { | 308 | if (data_length) { |
305 | garmin_data_p->flags |= FLAGS_QUEUING; | ||
306 | pkt = kmalloc(sizeof(struct garmin_packet)+data_length, | 309 | pkt = kmalloc(sizeof(struct garmin_packet)+data_length, |
307 | GFP_ATOMIC); | 310 | GFP_ATOMIC); |
308 | if (pkt == NULL) { | 311 | if (pkt == NULL) { |
@@ -313,14 +316,16 @@ static int pkt_add(struct garmin_data * garmin_data_p, | |||
313 | memcpy(pkt->data, data, data_length); | 316 | memcpy(pkt->data, data, data_length); |
314 | 317 | ||
315 | spin_lock_irqsave(&garmin_data_p->lock, flags); | 318 | spin_lock_irqsave(&garmin_data_p->lock, flags); |
319 | garmin_data_p->flags |= FLAGS_QUEUING; | ||
316 | result = list_empty(&garmin_data_p->pktlist); | 320 | result = list_empty(&garmin_data_p->pktlist); |
317 | pkt->seq = garmin_data_p->seq_counter++; | 321 | pkt->seq = garmin_data_p->seq_counter++; |
318 | list_add_tail(&pkt->list, &garmin_data_p->pktlist); | 322 | list_add_tail(&pkt->list, &garmin_data_p->pktlist); |
323 | state = garmin_data_p->state; | ||
319 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | 324 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); |
320 | 325 | ||
321 | /* in serial mode, if someone is waiting for data from | 326 | /* in serial mode, if someone is waiting for data from |
322 | the device, iconvert and send the next packet to tty. */ | 327 | the device, iconvert and send the next packet to tty. */ |
323 | if (result && (garmin_data_p->state == STATE_GSP_WAIT_DATA)) { | 328 | if (result && (state == STATE_GSP_WAIT_DATA)) { |
324 | gsp_next_packet(garmin_data_p); | 329 | gsp_next_packet(garmin_data_p); |
325 | } | 330 | } |
326 | } | 331 | } |
@@ -370,9 +375,9 @@ static void pkt_clear(struct garmin_data * garmin_data_p) | |||
370 | static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id) | 375 | static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id) |
371 | { | 376 | { |
372 | __u8 pkt[10]; | 377 | __u8 pkt[10]; |
373 | __u8 cksum = 0; | 378 | __u8 cksum = 0; |
374 | __u8 *ptr = pkt; | 379 | __u8 *ptr = pkt; |
375 | unsigned l = 0; | 380 | unsigned l = 0; |
376 | 381 | ||
377 | dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id); | 382 | dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id); |
378 | 383 | ||
@@ -416,7 +421,7 @@ static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id) | |||
416 | static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count) | 421 | static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count) |
417 | { | 422 | { |
418 | const __u8* recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET; | 423 | const __u8* recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET; |
419 | __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer; | 424 | __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer; |
420 | 425 | ||
421 | int cksum = 0; | 426 | int cksum = 0; |
422 | int n = 0; | 427 | int n = 0; |
@@ -447,11 +452,11 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count) | |||
447 | n++; | 452 | n++; |
448 | } | 453 | } |
449 | 454 | ||
450 | if ((0xff & (cksum + *recpkt)) != 0) { | 455 | if ((0xff & (cksum + *recpkt)) != 0) { |
451 | dbg("%s - invalid checksum, expected %02x, got %02x", | 456 | dbg("%s - invalid checksum, expected %02x, got %02x", |
452 | __FUNCTION__, 0xff & -cksum, 0xff & *recpkt); | 457 | __FUNCTION__, 0xff & -cksum, 0xff & *recpkt); |
453 | return -EINVPKT; | 458 | return -EINVPKT; |
454 | } | 459 | } |
455 | 460 | ||
456 | usbdata[0] = __cpu_to_le32(GARMIN_LAYERID_APPL); | 461 | usbdata[0] = __cpu_to_le32(GARMIN_LAYERID_APPL); |
457 | usbdata[1] = __cpu_to_le32(pktid); | 462 | usbdata[1] = __cpu_to_le32(pktid); |
@@ -491,20 +496,28 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count) | |||
491 | */ | 496 | */ |
492 | 497 | ||
493 | static int gsp_receive(struct garmin_data * garmin_data_p, | 498 | static int gsp_receive(struct garmin_data * garmin_data_p, |
494 | const unsigned char *buf, int count) | 499 | const unsigned char *buf, int count) |
495 | { | 500 | { |
501 | unsigned long flags; | ||
496 | int offs = 0; | 502 | int offs = 0; |
497 | int ack_or_nak_seen = 0; | 503 | int ack_or_nak_seen = 0; |
498 | int i = 0; | 504 | int i = 0; |
499 | __u8 *dest = garmin_data_p->inbuffer; | 505 | __u8 *dest; |
500 | int size = garmin_data_p->insize; | 506 | int size; |
501 | // dleSeen: set if last byte read was a DLE | 507 | // dleSeen: set if last byte read was a DLE |
502 | int dleSeen = garmin_data_p->flags & FLAGS_GSP_DLESEEN; | 508 | int dleSeen; |
503 | // skip: if set, skip incoming data until possible start of | 509 | // skip: if set, skip incoming data until possible start of |
504 | // new packet | 510 | // new packet |
505 | int skip = garmin_data_p->flags & FLAGS_GSP_SKIP; | 511 | int skip; |
506 | __u8 data; | 512 | __u8 data; |
507 | 513 | ||
514 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
515 | dest = garmin_data_p->inbuffer; | ||
516 | size = garmin_data_p->insize; | ||
517 | dleSeen = garmin_data_p->flags & FLAGS_GSP_DLESEEN; | ||
518 | skip = garmin_data_p->flags & FLAGS_GSP_SKIP; | ||
519 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
520 | |||
508 | dbg("%s - dle=%d skip=%d size=%d count=%d", | 521 | dbg("%s - dle=%d skip=%d size=%d count=%d", |
509 | __FUNCTION__, dleSeen, skip, size, count); | 522 | __FUNCTION__, dleSeen, skip, size, count); |
510 | 523 | ||
@@ -572,6 +585,8 @@ static int gsp_receive(struct garmin_data * garmin_data_p, | |||
572 | } | 585 | } |
573 | } | 586 | } |
574 | 587 | ||
588 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
589 | |||
575 | garmin_data_p->insize = size; | 590 | garmin_data_p->insize = size; |
576 | 591 | ||
577 | // copy flags back to structure | 592 | // copy flags back to structure |
@@ -587,6 +602,11 @@ static int gsp_receive(struct garmin_data * garmin_data_p, | |||
587 | 602 | ||
588 | if (ack_or_nak_seen) { | 603 | if (ack_or_nak_seen) { |
589 | garmin_data_p->state = STATE_GSP_WAIT_DATA; | 604 | garmin_data_p->state = STATE_GSP_WAIT_DATA; |
605 | } | ||
606 | |||
607 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
608 | |||
609 | if (ack_or_nak_seen) { | ||
590 | gsp_next_packet(garmin_data_p); | 610 | gsp_next_packet(garmin_data_p); |
591 | } | 611 | } |
592 | 612 | ||
@@ -676,7 +696,7 @@ static int gsp_send(struct garmin_data * garmin_data_p, | |||
676 | src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH; | 696 | src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH; |
677 | if (k > (GARMIN_PKTHDR_LENGTH-2)) { | 697 | if (k > (GARMIN_PKTHDR_LENGTH-2)) { |
678 | /* can't add stuffing DLEs in place, move data to end | 698 | /* can't add stuffing DLEs in place, move data to end |
679 | of buffer ... */ | 699 | of buffer ... */ |
680 | dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen; | 700 | dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen; |
681 | memcpy(dst, src, datalen); | 701 | memcpy(dst, src, datalen); |
682 | src = dst; | 702 | src = dst; |
@@ -755,8 +775,9 @@ static void gsp_next_packet(struct garmin_data * garmin_data_p) | |||
755 | * or even incomplete packets | 775 | * or even incomplete packets |
756 | */ | 776 | */ |
757 | static int nat_receive(struct garmin_data * garmin_data_p, | 777 | static int nat_receive(struct garmin_data * garmin_data_p, |
758 | const unsigned char *buf, int count) | 778 | const unsigned char *buf, int count) |
759 | { | 779 | { |
780 | unsigned long flags; | ||
760 | __u8 * dest; | 781 | __u8 * dest; |
761 | int offs = 0; | 782 | int offs = 0; |
762 | int result = count; | 783 | int result = count; |
@@ -803,7 +824,9 @@ static int nat_receive(struct garmin_data * garmin_data_p, | |||
803 | /* if this was an abort-transfer command, | 824 | /* if this was an abort-transfer command, |
804 | flush all queued data. */ | 825 | flush all queued data. */ |
805 | if (isAbortTrfCmnd(garmin_data_p->inbuffer)) { | 826 | if (isAbortTrfCmnd(garmin_data_p->inbuffer)) { |
827 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
806 | garmin_data_p->flags |= FLAGS_DROP_DATA; | 828 | garmin_data_p->flags |= FLAGS_DROP_DATA; |
829 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
807 | pkt_clear(garmin_data_p); | 830 | pkt_clear(garmin_data_p); |
808 | } | 831 | } |
809 | } | 832 | } |
@@ -839,12 +862,15 @@ static void priv_status_resp(struct usb_serial_port *port) | |||
839 | 862 | ||
840 | static int process_resetdev_request(struct usb_serial_port *port) | 863 | static int process_resetdev_request(struct usb_serial_port *port) |
841 | { | 864 | { |
865 | unsigned long flags; | ||
842 | int status; | 866 | int status; |
843 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 867 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
844 | 868 | ||
869 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
845 | garmin_data_p->flags &= ~(CLEAR_HALT_REQUIRED); | 870 | garmin_data_p->flags &= ~(CLEAR_HALT_REQUIRED); |
846 | garmin_data_p->state = STATE_RESET; | 871 | garmin_data_p->state = STATE_RESET; |
847 | garmin_data_p->serial_num = 0; | 872 | garmin_data_p->serial_num = 0; |
873 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
848 | 874 | ||
849 | usb_kill_urb (port->interrupt_in_urb); | 875 | usb_kill_urb (port->interrupt_in_urb); |
850 | dbg("%s - usb_reset_device", __FUNCTION__ ); | 876 | dbg("%s - usb_reset_device", __FUNCTION__ ); |
@@ -862,6 +888,7 @@ static int process_resetdev_request(struct usb_serial_port *port) | |||
862 | */ | 888 | */ |
863 | static int garmin_clear(struct garmin_data * garmin_data_p) | 889 | static int garmin_clear(struct garmin_data * garmin_data_p) |
864 | { | 890 | { |
891 | unsigned long flags; | ||
865 | int status = 0; | 892 | int status = 0; |
866 | 893 | ||
867 | struct usb_serial_port *port = garmin_data_p->port; | 894 | struct usb_serial_port *port = garmin_data_p->port; |
@@ -875,8 +902,10 @@ static int garmin_clear(struct garmin_data * garmin_data_p) | |||
875 | /* flush all queued data */ | 902 | /* flush all queued data */ |
876 | pkt_clear(garmin_data_p); | 903 | pkt_clear(garmin_data_p); |
877 | 904 | ||
905 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
878 | garmin_data_p->insize = 0; | 906 | garmin_data_p->insize = 0; |
879 | garmin_data_p->outsize = 0; | 907 | garmin_data_p->outsize = 0; |
908 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
880 | 909 | ||
881 | return status; | 910 | return status; |
882 | } | 911 | } |
@@ -888,6 +917,7 @@ static int garmin_clear(struct garmin_data * garmin_data_p) | |||
888 | 917 | ||
889 | static int garmin_init_session(struct usb_serial_port *port) | 918 | static int garmin_init_session(struct usb_serial_port *port) |
890 | { | 919 | { |
920 | unsigned long flags; | ||
891 | struct usb_serial *serial = port->serial; | 921 | struct usb_serial *serial = port->serial; |
892 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 922 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
893 | int status = 0; | 923 | int status = 0; |
@@ -913,7 +943,9 @@ static int garmin_init_session(struct usb_serial_port *port) | |||
913 | 943 | ||
914 | if (status >= 0) { | 944 | if (status >= 0) { |
915 | 945 | ||
946 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
916 | garmin_data_p->ignorePkts++; | 947 | garmin_data_p->ignorePkts++; |
948 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
917 | 949 | ||
918 | /* not needed, but the win32 driver does it too ... */ | 950 | /* not needed, but the win32 driver does it too ... */ |
919 | status = garmin_write_bulk(port, | 951 | status = garmin_write_bulk(port, |
@@ -921,7 +953,9 @@ static int garmin_init_session(struct usb_serial_port *port) | |||
921 | sizeof(GARMIN_START_SESSION_REQ2)); | 953 | sizeof(GARMIN_START_SESSION_REQ2)); |
922 | if (status >= 0) { | 954 | if (status >= 0) { |
923 | status = 0; | 955 | status = 0; |
956 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
924 | garmin_data_p->ignorePkts++; | 957 | garmin_data_p->ignorePkts++; |
958 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
925 | } | 959 | } |
926 | } | 960 | } |
927 | } | 961 | } |
@@ -935,6 +969,7 @@ static int garmin_init_session(struct usb_serial_port *port) | |||
935 | 969 | ||
936 | static int garmin_open (struct usb_serial_port *port, struct file *filp) | 970 | static int garmin_open (struct usb_serial_port *port, struct file *filp) |
937 | { | 971 | { |
972 | unsigned long flags; | ||
938 | int status = 0; | 973 | int status = 0; |
939 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 974 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
940 | 975 | ||
@@ -948,9 +983,11 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp) | |||
948 | if (port->tty) | 983 | if (port->tty) |
949 | port->tty->low_latency = 1; | 984 | port->tty->low_latency = 1; |
950 | 985 | ||
986 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
951 | garmin_data_p->mode = initial_mode; | 987 | garmin_data_p->mode = initial_mode; |
952 | garmin_data_p->count = 0; | 988 | garmin_data_p->count = 0; |
953 | garmin_data_p->flags = 0; | 989 | garmin_data_p->flags = 0; |
990 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
954 | 991 | ||
955 | /* shutdown any bulk reads that might be going on */ | 992 | /* shutdown any bulk reads that might be going on */ |
956 | usb_kill_urb (port->write_urb); | 993 | usb_kill_urb (port->write_urb); |
@@ -996,6 +1033,7 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp) | |||
996 | 1033 | ||
997 | static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | 1034 | static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs) |
998 | { | 1035 | { |
1036 | unsigned long flags; | ||
999 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 1037 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
1000 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1038 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1001 | 1039 | ||
@@ -1007,7 +1045,9 @@ static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
1007 | if (urb->status) { | 1045 | if (urb->status) { |
1008 | dbg("%s - nonzero write bulk status received: %d", | 1046 | dbg("%s - nonzero write bulk status received: %d", |
1009 | __FUNCTION__, urb->status); | 1047 | __FUNCTION__, urb->status); |
1048 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1010 | garmin_data_p->flags |= CLEAR_HALT_REQUIRED; | 1049 | garmin_data_p->flags |= CLEAR_HALT_REQUIRED; |
1050 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1011 | } | 1051 | } |
1012 | 1052 | ||
1013 | usb_serial_port_softint(port); | 1053 | usb_serial_port_softint(port); |
@@ -1015,8 +1055,9 @@ static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
1015 | 1055 | ||
1016 | 1056 | ||
1017 | static int garmin_write_bulk (struct usb_serial_port *port, | 1057 | static int garmin_write_bulk (struct usb_serial_port *port, |
1018 | const unsigned char *buf, int count) | 1058 | const unsigned char *buf, int count) |
1019 | { | 1059 | { |
1060 | unsigned long flags; | ||
1020 | struct usb_serial *serial = port->serial; | 1061 | struct usb_serial *serial = port->serial; |
1021 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1062 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1022 | struct urb *urb; | 1063 | struct urb *urb; |
@@ -1026,7 +1067,9 @@ static int garmin_write_bulk (struct usb_serial_port *port, | |||
1026 | dbg("%s - port %d, state %d", __FUNCTION__, port->number, | 1067 | dbg("%s - port %d, state %d", __FUNCTION__, port->number, |
1027 | garmin_data_p->state); | 1068 | garmin_data_p->state); |
1028 | 1069 | ||
1070 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1029 | garmin_data_p->flags &= ~FLAGS_DROP_DATA; | 1071 | garmin_data_p->flags &= ~FLAGS_DROP_DATA; |
1072 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1030 | 1073 | ||
1031 | buffer = kmalloc (count, GFP_ATOMIC); | 1074 | buffer = kmalloc (count, GFP_ATOMIC); |
1032 | if (!buffer) { | 1075 | if (!buffer) { |
@@ -1053,7 +1096,9 @@ static int garmin_write_bulk (struct usb_serial_port *port, | |||
1053 | urb->transfer_flags |= URB_ZERO_PACKET; | 1096 | urb->transfer_flags |= URB_ZERO_PACKET; |
1054 | 1097 | ||
1055 | if (GARMIN_LAYERID_APPL == getLayerId(buffer)) { | 1098 | if (GARMIN_LAYERID_APPL == getLayerId(buffer)) { |
1099 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1056 | garmin_data_p->flags |= FLAGS_APP_REQ_SEEN; | 1100 | garmin_data_p->flags |= FLAGS_APP_REQ_SEEN; |
1101 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1057 | if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { | 1102 | if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { |
1058 | pkt_clear(garmin_data_p); | 1103 | pkt_clear(garmin_data_p); |
1059 | garmin_data_p->state = STATE_GSP_WAIT_DATA; | 1104 | garmin_data_p->state = STATE_GSP_WAIT_DATA; |
@@ -1087,8 +1132,9 @@ static int garmin_write_bulk (struct usb_serial_port *port, | |||
1087 | 1132 | ||
1088 | 1133 | ||
1089 | static int garmin_write (struct usb_serial_port *port, | 1134 | static int garmin_write (struct usb_serial_port *port, |
1090 | const unsigned char *buf, int count) | 1135 | const unsigned char *buf, int count) |
1091 | { | 1136 | { |
1137 | unsigned long flags; | ||
1092 | int pktid, pktsiz, len; | 1138 | int pktid, pktsiz, len; |
1093 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1139 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1094 | __le32 *privpkt = (__le32 *)garmin_data_p->privpkt; | 1140 | __le32 *privpkt = (__le32 *)garmin_data_p->privpkt; |
@@ -1139,7 +1185,9 @@ static int garmin_write (struct usb_serial_port *port, | |||
1139 | break; | 1185 | break; |
1140 | 1186 | ||
1141 | case PRIV_PKTID_RESET_REQ: | 1187 | case PRIV_PKTID_RESET_REQ: |
1188 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1142 | garmin_data_p->flags |= FLAGS_APP_REQ_SEEN; | 1189 | garmin_data_p->flags |= FLAGS_APP_REQ_SEEN; |
1190 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1143 | break; | 1191 | break; |
1144 | 1192 | ||
1145 | case PRIV_PKTID_SET_DEF_MODE: | 1193 | case PRIV_PKTID_SET_DEF_MODE: |
@@ -1155,6 +1203,8 @@ static int garmin_write (struct usb_serial_port *port, | |||
1155 | } | 1203 | } |
1156 | } | 1204 | } |
1157 | 1205 | ||
1206 | garmin_data_p->ignorePkts = 0; | ||
1207 | |||
1158 | if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { | 1208 | if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { |
1159 | return gsp_receive(garmin_data_p, buf, count); | 1209 | return gsp_receive(garmin_data_p, buf, count); |
1160 | } else { /* MODE_NATIVE */ | 1210 | } else { /* MODE_NATIVE */ |
@@ -1177,10 +1227,10 @@ static int garmin_chars_in_buffer (struct usb_serial_port *port) | |||
1177 | { | 1227 | { |
1178 | /* | 1228 | /* |
1179 | * Report back the number of bytes currently in our input buffer. | 1229 | * Report back the number of bytes currently in our input buffer. |
1180 | * Will this lock up the driver - the buffer contains an incomplete | 1230 | * Will this lock up the driver - the buffer contains an incomplete |
1181 | * package which will not be written to the device until it | 1231 | * package which will not be written to the device until it |
1182 | * has been completed ? | 1232 | * has been completed ? |
1183 | */ | 1233 | */ |
1184 | //struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1234 | //struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1185 | //return garmin_data_p->insize; | 1235 | //return garmin_data_p->insize; |
1186 | return 0; | 1236 | return 0; |
@@ -1190,6 +1240,8 @@ static int garmin_chars_in_buffer (struct usb_serial_port *port) | |||
1190 | static void garmin_read_process(struct garmin_data * garmin_data_p, | 1240 | static void garmin_read_process(struct garmin_data * garmin_data_p, |
1191 | unsigned char *data, unsigned data_length) | 1241 | unsigned char *data, unsigned data_length) |
1192 | { | 1242 | { |
1243 | unsigned long flags; | ||
1244 | |||
1193 | if (garmin_data_p->flags & FLAGS_DROP_DATA) { | 1245 | if (garmin_data_p->flags & FLAGS_DROP_DATA) { |
1194 | /* abort-transfer cmd is actice */ | 1246 | /* abort-transfer cmd is actice */ |
1195 | dbg("%s - pkt dropped", __FUNCTION__); | 1247 | dbg("%s - pkt dropped", __FUNCTION__); |
@@ -1200,11 +1252,14 @@ static void garmin_read_process(struct garmin_data * garmin_data_p, | |||
1200 | if a reset is required or not when closing | 1252 | if a reset is required or not when closing |
1201 | the device */ | 1253 | the device */ |
1202 | if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY, | 1254 | if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY, |
1203 | sizeof(GARMIN_APP_LAYER_REPLY))) | 1255 | sizeof(GARMIN_APP_LAYER_REPLY))) { |
1256 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1204 | garmin_data_p->flags |= FLAGS_APP_RESP_SEEN; | 1257 | garmin_data_p->flags |= FLAGS_APP_RESP_SEEN; |
1258 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1259 | } | ||
1205 | 1260 | ||
1206 | /* if throttling is active or postprecessing is required | 1261 | /* if throttling is active or postprecessing is required |
1207 | put the received data in th input queue, otherwise | 1262 | put the received data in the input queue, otherwise |
1208 | send it directly to the tty port */ | 1263 | send it directly to the tty port */ |
1209 | if (garmin_data_p->flags & FLAGS_QUEUING) { | 1264 | if (garmin_data_p->flags & FLAGS_QUEUING) { |
1210 | pkt_add(garmin_data_p, data, data_length); | 1265 | pkt_add(garmin_data_p, data, data_length); |
@@ -1221,6 +1276,7 @@ static void garmin_read_process(struct garmin_data * garmin_data_p, | |||
1221 | 1276 | ||
1222 | static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | 1277 | static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs) |
1223 | { | 1278 | { |
1279 | unsigned long flags; | ||
1224 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 1280 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
1225 | struct usb_serial *serial = port->serial; | 1281 | struct usb_serial *serial = port->serial; |
1226 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1282 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
@@ -1245,19 +1301,30 @@ static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
1245 | 1301 | ||
1246 | garmin_read_process(garmin_data_p, data, urb->actual_length); | 1302 | garmin_read_process(garmin_data_p, data, urb->actual_length); |
1247 | 1303 | ||
1248 | /* Continue trying to read until nothing more is received */ | 1304 | if (urb->actual_length == 0 && |
1249 | if (urb->actual_length > 0) { | 1305 | 0 != (garmin_data_p->flags & FLAGS_BULK_IN_RESTART)) { |
1250 | usb_fill_bulk_urb (port->read_urb, serial->dev, | 1306 | spin_lock_irqsave(&garmin_data_p->lock, flags); |
1251 | usb_rcvbulkpipe (serial->dev, | 1307 | garmin_data_p->flags &= ~FLAGS_BULK_IN_RESTART; |
1252 | port->bulk_in_endpointAddress), | 1308 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); |
1253 | port->read_urb->transfer_buffer, | ||
1254 | port->read_urb->transfer_buffer_length, | ||
1255 | garmin_read_bulk_callback, port); | ||
1256 | status = usb_submit_urb(port->read_urb, GFP_ATOMIC); | 1309 | status = usb_submit_urb(port->read_urb, GFP_ATOMIC); |
1257 | if (status) | 1310 | if (status) |
1258 | dev_err(&port->dev, | 1311 | dev_err(&port->dev, |
1259 | "%s - failed resubmitting read urb, error %d\n", | 1312 | "%s - failed resubmitting read urb, error %d\n", |
1260 | __FUNCTION__, status); | 1313 | __FUNCTION__, status); |
1314 | } else if (urb->actual_length > 0) { | ||
1315 | /* Continue trying to read until nothing more is received */ | ||
1316 | if (0 == (garmin_data_p->flags & FLAGS_THROTTLED)) { | ||
1317 | status = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
1318 | if (status) | ||
1319 | dev_err(&port->dev, | ||
1320 | "%s - failed resubmitting read urb, error %d\n", | ||
1321 | __FUNCTION__, status); | ||
1322 | } | ||
1323 | } else { | ||
1324 | dbg("%s - end of bulk data", __FUNCTION__); | ||
1325 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1326 | garmin_data_p->flags &= ~FLAGS_BULK_IN_ACTIVE; | ||
1327 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1261 | } | 1328 | } |
1262 | return; | 1329 | return; |
1263 | } | 1330 | } |
@@ -1265,6 +1332,7 @@ static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
1265 | 1332 | ||
1266 | static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs) | 1333 | static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs) |
1267 | { | 1334 | { |
1335 | unsigned long flags; | ||
1268 | int status; | 1336 | int status; |
1269 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 1337 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
1270 | struct usb_serial *serial = port->serial; | 1338 | struct usb_serial *serial = port->serial; |
@@ -1297,25 +1365,41 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs) | |||
1297 | 1365 | ||
1298 | dbg("%s - bulk data available.", __FUNCTION__); | 1366 | dbg("%s - bulk data available.", __FUNCTION__); |
1299 | 1367 | ||
1300 | /* bulk data available */ | 1368 | if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) { |
1301 | usb_fill_bulk_urb (port->read_urb, serial->dev, | 1369 | |
1302 | usb_rcvbulkpipe (serial->dev, | 1370 | /* bulk data available */ |
1303 | port->bulk_in_endpointAddress), | 1371 | usb_fill_bulk_urb (port->read_urb, serial->dev, |
1304 | port->read_urb->transfer_buffer, | 1372 | usb_rcvbulkpipe (serial->dev, |
1305 | port->read_urb->transfer_buffer_length, | 1373 | port->bulk_in_endpointAddress), |
1306 | garmin_read_bulk_callback, port); | 1374 | port->read_urb->transfer_buffer, |
1307 | status = usb_submit_urb(port->read_urb, GFP_KERNEL); | 1375 | port->read_urb->transfer_buffer_length, |
1308 | if (status) { | 1376 | garmin_read_bulk_callback, port); |
1309 | dev_err(&port->dev, | 1377 | status = usb_submit_urb(port->read_urb, GFP_ATOMIC); |
1310 | "%s - failed submitting read urb, error %d\n", | 1378 | if (status) { |
1311 | __FUNCTION__, status); | 1379 | dev_err(&port->dev, |
1380 | "%s - failed submitting read urb, error %d\n", | ||
1381 | __FUNCTION__, status); | ||
1382 | } else { | ||
1383 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1384 | garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE; | ||
1385 | /* do not send this packet to the user */ | ||
1386 | garmin_data_p->ignorePkts = 1; | ||
1387 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1388 | } | ||
1389 | } else { | ||
1390 | /* bulk-in transfer still active */ | ||
1391 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1392 | garmin_data_p->flags |= FLAGS_BULK_IN_RESTART; | ||
1393 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1312 | } | 1394 | } |
1313 | 1395 | ||
1314 | } else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY)) | 1396 | } else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY)) |
1315 | && 0 == memcmp(data, GARMIN_START_SESSION_REPLY, | 1397 | && 0 == memcmp(data, GARMIN_START_SESSION_REPLY, |
1316 | sizeof(GARMIN_START_SESSION_REPLY))) { | 1398 | sizeof(GARMIN_START_SESSION_REPLY))) { |
1317 | 1399 | ||
1400 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1318 | garmin_data_p->flags |= FLAGS_SESSION_REPLY1_SEEN; | 1401 | garmin_data_p->flags |= FLAGS_SESSION_REPLY1_SEEN; |
1402 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1319 | 1403 | ||
1320 | /* save the serial number */ | 1404 | /* save the serial number */ |
1321 | garmin_data_p->serial_num | 1405 | garmin_data_p->serial_num |
@@ -1330,7 +1414,9 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs) | |||
1330 | ignore it. */ | 1414 | ignore it. */ |
1331 | dbg("%s - pkt ignored (%d)", | 1415 | dbg("%s - pkt ignored (%d)", |
1332 | __FUNCTION__, garmin_data_p->ignorePkts); | 1416 | __FUNCTION__, garmin_data_p->ignorePkts); |
1417 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1333 | garmin_data_p->ignorePkts--; | 1418 | garmin_data_p->ignorePkts--; |
1419 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1334 | } else { | 1420 | } else { |
1335 | garmin_read_process(garmin_data_p, data, urb->actual_length); | 1421 | garmin_read_process(garmin_data_p, data, urb->actual_length); |
1336 | } | 1422 | } |
@@ -1351,18 +1437,20 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs) | |||
1351 | */ | 1437 | */ |
1352 | static int garmin_flush_queue(struct garmin_data * garmin_data_p) | 1438 | static int garmin_flush_queue(struct garmin_data * garmin_data_p) |
1353 | { | 1439 | { |
1440 | unsigned long flags; | ||
1354 | struct garmin_packet *pkt; | 1441 | struct garmin_packet *pkt; |
1355 | 1442 | ||
1356 | if ((garmin_data_p->flags & FLAGS_THROTTLED) == 0) { | 1443 | if ((garmin_data_p->flags & FLAGS_THROTTLED) == 0) { |
1357 | pkt = pkt_pop(garmin_data_p); | 1444 | pkt = pkt_pop(garmin_data_p); |
1358 | if (pkt != NULL) { | 1445 | if (pkt != NULL) { |
1359 | |||
1360 | send_to_tty(garmin_data_p->port, pkt->data, pkt->size); | 1446 | send_to_tty(garmin_data_p->port, pkt->data, pkt->size); |
1361 | kfree(pkt); | 1447 | kfree(pkt); |
1362 | mod_timer(&garmin_data_p->timer, (1)+jiffies); | 1448 | mod_timer(&garmin_data_p->timer, (1)+jiffies); |
1363 | 1449 | ||
1364 | } else { | 1450 | } else { |
1451 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1365 | garmin_data_p->flags &= ~FLAGS_QUEUING; | 1452 | garmin_data_p->flags &= ~FLAGS_QUEUING; |
1453 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1366 | } | 1454 | } |
1367 | } | 1455 | } |
1368 | return 0; | 1456 | return 0; |
@@ -1371,26 +1459,41 @@ static int garmin_flush_queue(struct garmin_data * garmin_data_p) | |||
1371 | 1459 | ||
1372 | static void garmin_throttle (struct usb_serial_port *port) | 1460 | static void garmin_throttle (struct usb_serial_port *port) |
1373 | { | 1461 | { |
1462 | unsigned long flags; | ||
1374 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1463 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1375 | 1464 | ||
1376 | dbg("%s - port %d", __FUNCTION__, port->number); | 1465 | dbg("%s - port %d", __FUNCTION__, port->number); |
1377 | /* set flag, data received will be put into a queue | 1466 | /* set flag, data received will be put into a queue |
1378 | for later processing */ | 1467 | for later processing */ |
1468 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1379 | garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED; | 1469 | garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED; |
1470 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1380 | } | 1471 | } |
1381 | 1472 | ||
1382 | 1473 | ||
1383 | static void garmin_unthrottle (struct usb_serial_port *port) | 1474 | static void garmin_unthrottle (struct usb_serial_port *port) |
1384 | { | 1475 | { |
1476 | unsigned long flags; | ||
1385 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1477 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1478 | int status; | ||
1386 | 1479 | ||
1387 | dbg("%s - port %d", __FUNCTION__, port->number); | 1480 | dbg("%s - port %d", __FUNCTION__, port->number); |
1481 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1388 | garmin_data_p->flags &= ~FLAGS_THROTTLED; | 1482 | garmin_data_p->flags &= ~FLAGS_THROTTLED; |
1483 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1389 | 1484 | ||
1390 | /* in native mode send queued data to tty, in | 1485 | /* in native mode send queued data to tty, in |
1391 | serial mode nothing needs to be done here */ | 1486 | serial mode nothing needs to be done here */ |
1392 | if (garmin_data_p->mode == MODE_NATIVE) | 1487 | if (garmin_data_p->mode == MODE_NATIVE) |
1393 | garmin_flush_queue(garmin_data_p); | 1488 | garmin_flush_queue(garmin_data_p); |
1489 | |||
1490 | if (0 != (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) { | ||
1491 | status = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
1492 | if (status) | ||
1493 | dev_err(&port->dev, | ||
1494 | "%s - failed resubmitting read urb, error %d\n", | ||
1495 | __FUNCTION__, status); | ||
1496 | } | ||
1394 | } | 1497 | } |
1395 | 1498 | ||
1396 | 1499 | ||
@@ -1420,11 +1523,12 @@ static int garmin_attach (struct usb_serial *serial) | |||
1420 | 1523 | ||
1421 | dbg("%s", __FUNCTION__); | 1524 | dbg("%s", __FUNCTION__); |
1422 | 1525 | ||
1423 | garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL); | 1526 | garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL); |
1424 | if (garmin_data_p == NULL) { | 1527 | if (garmin_data_p == NULL) { |
1425 | dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__); | 1528 | dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__); |
1426 | return -ENOMEM; | 1529 | return -ENOMEM; |
1427 | } | 1530 | } |
1531 | memset (garmin_data_p, 0, sizeof(struct garmin_data)); | ||
1428 | init_timer(&garmin_data_p->timer); | 1532 | init_timer(&garmin_data_p->timer); |
1429 | spin_lock_init(&garmin_data_p->lock); | 1533 | spin_lock_init(&garmin_data_p->lock); |
1430 | INIT_LIST_HEAD(&garmin_data_p->pktlist); | 1534 | INIT_LIST_HEAD(&garmin_data_p->pktlist); |
@@ -1459,10 +1563,10 @@ static void garmin_shutdown (struct usb_serial *serial) | |||
1459 | /* All of the device info needed */ | 1563 | /* All of the device info needed */ |
1460 | static struct usb_serial_driver garmin_device = { | 1564 | static struct usb_serial_driver garmin_device = { |
1461 | .driver = { | 1565 | .driver = { |
1462 | .owner = THIS_MODULE, | 1566 | .owner = THIS_MODULE, |
1463 | .name = "garmin_gps", | 1567 | .name = "garmin_gps", |
1464 | }, | 1568 | }, |
1465 | .description = "Garmin GPS usb/tty", | 1569 | .description = "Garmin GPS usb/tty", |
1466 | .id_table = id_table, | 1570 | .id_table = id_table, |
1467 | .num_interrupt_in = 1, | 1571 | .num_interrupt_in = 1, |
1468 | .num_bulk_in = 1, | 1572 | .num_bulk_in = 1, |
@@ -1483,6 +1587,7 @@ static struct usb_serial_driver garmin_device = { | |||
1483 | }; | 1587 | }; |
1484 | 1588 | ||
1485 | 1589 | ||
1590 | |||
1486 | static int __init garmin_init (void) | 1591 | static int __init garmin_init (void) |
1487 | { | 1592 | { |
1488 | int retval; | 1593 | int retval; |