USB: garmin_gps support for new generation of gps receivers
The attached patch adds support for the new generation of gps receivers (eg. GPSmap 60Cx) to garmin_gps.c. Signed-off-by: Hermann Kneissel <herkne@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
3bea733ab2
commit
eb6d8c2d14
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Garmin GPS driver
|
* Garmin GPS driver
|
||||||
*
|
*
|
||||||
* Copyright (C) 2004 Hermann Kneissel herkne@users.sourceforge.net
|
* Copyright (C) 2006 Hermann Kneissel herkne@users.sourceforge.net
|
||||||
*
|
*
|
||||||
* The latest version of the driver can be found at
|
* The latest version of the driver can be found at
|
||||||
* http://sourceforge.net/projects/garmin-gps/
|
* http://sourceforge.net/projects/garmin-gps/
|
||||||
@ -37,6 +37,8 @@
|
|||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
#include <linux/usb/serial.h>
|
#include <linux/usb/serial.h>
|
||||||
|
|
||||||
|
#include <linux/version.h>
|
||||||
|
|
||||||
/* the mode to be set when the port ist opened */
|
/* the mode to be set when the port ist opened */
|
||||||
static int initial_mode = 1;
|
static int initial_mode = 1;
|
||||||
|
|
||||||
@ -50,7 +52,7 @@ static int debug = 0;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 23
|
#define VERSION_MINOR 28
|
||||||
|
|
||||||
#define _STR(s) #s
|
#define _STR(s) #s
|
||||||
#define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b)
|
#define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b)
|
||||||
@ -164,7 +166,8 @@ struct garmin_data {
|
|||||||
#define FLAGS_SESSION_REPLY1_SEEN 0x0080
|
#define FLAGS_SESSION_REPLY1_SEEN 0x0080
|
||||||
#define FLAGS_SESSION_REPLY2_SEEN 0x0040
|
#define FLAGS_SESSION_REPLY2_SEEN 0x0040
|
||||||
#define FLAGS_BULK_IN_ACTIVE 0x0020
|
#define FLAGS_BULK_IN_ACTIVE 0x0020
|
||||||
#define FLAGS_THROTTLED 0x0010
|
#define FLAGS_BULK_IN_RESTART 0x0010
|
||||||
|
#define FLAGS_THROTTLED 0x0008
|
||||||
#define CLEAR_HALT_REQUIRED 0x0001
|
#define CLEAR_HALT_REQUIRED 0x0001
|
||||||
|
|
||||||
#define FLAGS_QUEUING 0x0100
|
#define FLAGS_QUEUING 0x0100
|
||||||
@ -224,7 +227,7 @@ static struct usb_driver garmin_driver = {
|
|||||||
.probe = usb_serial_probe,
|
.probe = usb_serial_probe,
|
||||||
.disconnect = usb_serial_disconnect,
|
.disconnect = usb_serial_disconnect,
|
||||||
.id_table = id_table,
|
.id_table = id_table,
|
||||||
.no_dynamic_id = 1,
|
.no_dynamic_id = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -270,7 +273,7 @@ static inline int isAbortTrfCmnd(const unsigned char *buf)
|
|||||||
|
|
||||||
|
|
||||||
static void send_to_tty(struct usb_serial_port *port,
|
static void send_to_tty(struct usb_serial_port *port,
|
||||||
char *data, unsigned int actual_length)
|
char *data, unsigned int actual_length)
|
||||||
{
|
{
|
||||||
struct tty_struct *tty = port->tty;
|
struct tty_struct *tty = port->tty;
|
||||||
|
|
||||||
@ -294,15 +297,15 @@ static void send_to_tty(struct usb_serial_port *port,
|
|||||||
* queue a received (usb-)packet for later processing
|
* queue a received (usb-)packet for later processing
|
||||||
*/
|
*/
|
||||||
static int pkt_add(struct garmin_data * garmin_data_p,
|
static int pkt_add(struct garmin_data * garmin_data_p,
|
||||||
unsigned char *data, unsigned int data_length)
|
unsigned char *data, unsigned int data_length)
|
||||||
{
|
{
|
||||||
|
int state = 0;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct garmin_packet *pkt;
|
struct garmin_packet *pkt;
|
||||||
|
|
||||||
/* process only packets containg data ... */
|
/* process only packets containg data ... */
|
||||||
if (data_length) {
|
if (data_length) {
|
||||||
garmin_data_p->flags |= FLAGS_QUEUING;
|
|
||||||
pkt = kmalloc(sizeof(struct garmin_packet)+data_length,
|
pkt = kmalloc(sizeof(struct garmin_packet)+data_length,
|
||||||
GFP_ATOMIC);
|
GFP_ATOMIC);
|
||||||
if (pkt == NULL) {
|
if (pkt == NULL) {
|
||||||
@ -313,14 +316,16 @@ static int pkt_add(struct garmin_data * garmin_data_p,
|
|||||||
memcpy(pkt->data, data, data_length);
|
memcpy(pkt->data, data, data_length);
|
||||||
|
|
||||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
|
garmin_data_p->flags |= FLAGS_QUEUING;
|
||||||
result = list_empty(&garmin_data_p->pktlist);
|
result = list_empty(&garmin_data_p->pktlist);
|
||||||
pkt->seq = garmin_data_p->seq_counter++;
|
pkt->seq = garmin_data_p->seq_counter++;
|
||||||
list_add_tail(&pkt->list, &garmin_data_p->pktlist);
|
list_add_tail(&pkt->list, &garmin_data_p->pktlist);
|
||||||
|
state = garmin_data_p->state;
|
||||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
|
|
||||||
/* in serial mode, if someone is waiting for data from
|
/* in serial mode, if someone is waiting for data from
|
||||||
the device, iconvert and send the next packet to tty. */
|
the device, iconvert and send the next packet to tty. */
|
||||||
if (result && (garmin_data_p->state == STATE_GSP_WAIT_DATA)) {
|
if (result && (state == STATE_GSP_WAIT_DATA)) {
|
||||||
gsp_next_packet(garmin_data_p);
|
gsp_next_packet(garmin_data_p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -370,9 +375,9 @@ static void pkt_clear(struct garmin_data * garmin_data_p)
|
|||||||
static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
|
static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
|
||||||
{
|
{
|
||||||
__u8 pkt[10];
|
__u8 pkt[10];
|
||||||
__u8 cksum = 0;
|
__u8 cksum = 0;
|
||||||
__u8 *ptr = pkt;
|
__u8 *ptr = pkt;
|
||||||
unsigned l = 0;
|
unsigned l = 0;
|
||||||
|
|
||||||
dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id);
|
dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id);
|
||||||
|
|
||||||
@ -416,7 +421,7 @@ static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
|
|||||||
static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
|
static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
|
||||||
{
|
{
|
||||||
const __u8* recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
|
const __u8* recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
|
||||||
__le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
|
__le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
|
||||||
|
|
||||||
int cksum = 0;
|
int cksum = 0;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
@ -447,11 +452,11 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
|
|||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((0xff & (cksum + *recpkt)) != 0) {
|
if ((0xff & (cksum + *recpkt)) != 0) {
|
||||||
dbg("%s - invalid checksum, expected %02x, got %02x",
|
dbg("%s - invalid checksum, expected %02x, got %02x",
|
||||||
__FUNCTION__, 0xff & -cksum, 0xff & *recpkt);
|
__FUNCTION__, 0xff & -cksum, 0xff & *recpkt);
|
||||||
return -EINVPKT;
|
return -EINVPKT;
|
||||||
}
|
}
|
||||||
|
|
||||||
usbdata[0] = __cpu_to_le32(GARMIN_LAYERID_APPL);
|
usbdata[0] = __cpu_to_le32(GARMIN_LAYERID_APPL);
|
||||||
usbdata[1] = __cpu_to_le32(pktid);
|
usbdata[1] = __cpu_to_le32(pktid);
|
||||||
@ -491,20 +496,28 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int gsp_receive(struct garmin_data * garmin_data_p,
|
static int gsp_receive(struct garmin_data * garmin_data_p,
|
||||||
const unsigned char *buf, int count)
|
const unsigned char *buf, int count)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int offs = 0;
|
int offs = 0;
|
||||||
int ack_or_nak_seen = 0;
|
int ack_or_nak_seen = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
__u8 *dest = garmin_data_p->inbuffer;
|
__u8 *dest;
|
||||||
int size = garmin_data_p->insize;
|
int size;
|
||||||
// dleSeen: set if last byte read was a DLE
|
// dleSeen: set if last byte read was a DLE
|
||||||
int dleSeen = garmin_data_p->flags & FLAGS_GSP_DLESEEN;
|
int dleSeen;
|
||||||
// skip: if set, skip incoming data until possible start of
|
// skip: if set, skip incoming data until possible start of
|
||||||
// new packet
|
// new packet
|
||||||
int skip = garmin_data_p->flags & FLAGS_GSP_SKIP;
|
int skip;
|
||||||
__u8 data;
|
__u8 data;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
|
dest = garmin_data_p->inbuffer;
|
||||||
|
size = garmin_data_p->insize;
|
||||||
|
dleSeen = garmin_data_p->flags & FLAGS_GSP_DLESEEN;
|
||||||
|
skip = garmin_data_p->flags & FLAGS_GSP_SKIP;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
|
|
||||||
dbg("%s - dle=%d skip=%d size=%d count=%d",
|
dbg("%s - dle=%d skip=%d size=%d count=%d",
|
||||||
__FUNCTION__, dleSeen, skip, size, count);
|
__FUNCTION__, dleSeen, skip, size, count);
|
||||||
|
|
||||||
@ -572,6 +585,8 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
|
|
||||||
garmin_data_p->insize = size;
|
garmin_data_p->insize = size;
|
||||||
|
|
||||||
// copy flags back to structure
|
// copy flags back to structure
|
||||||
@ -587,6 +602,11 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
|
|||||||
|
|
||||||
if (ack_or_nak_seen) {
|
if (ack_or_nak_seen) {
|
||||||
garmin_data_p->state = STATE_GSP_WAIT_DATA;
|
garmin_data_p->state = STATE_GSP_WAIT_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
|
|
||||||
|
if (ack_or_nak_seen) {
|
||||||
gsp_next_packet(garmin_data_p);
|
gsp_next_packet(garmin_data_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -676,7 +696,7 @@ static int gsp_send(struct garmin_data * garmin_data_p,
|
|||||||
src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH;
|
src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH;
|
||||||
if (k > (GARMIN_PKTHDR_LENGTH-2)) {
|
if (k > (GARMIN_PKTHDR_LENGTH-2)) {
|
||||||
/* can't add stuffing DLEs in place, move data to end
|
/* can't add stuffing DLEs in place, move data to end
|
||||||
of buffer ... */
|
of buffer ... */
|
||||||
dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen;
|
dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen;
|
||||||
memcpy(dst, src, datalen);
|
memcpy(dst, src, datalen);
|
||||||
src = dst;
|
src = dst;
|
||||||
@ -755,8 +775,9 @@ static void gsp_next_packet(struct garmin_data * garmin_data_p)
|
|||||||
* or even incomplete packets
|
* or even incomplete packets
|
||||||
*/
|
*/
|
||||||
static int nat_receive(struct garmin_data * garmin_data_p,
|
static int nat_receive(struct garmin_data * garmin_data_p,
|
||||||
const unsigned char *buf, int count)
|
const unsigned char *buf, int count)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
__u8 * dest;
|
__u8 * dest;
|
||||||
int offs = 0;
|
int offs = 0;
|
||||||
int result = count;
|
int result = count;
|
||||||
@ -803,7 +824,9 @@ static int nat_receive(struct garmin_data * garmin_data_p,
|
|||||||
/* if this was an abort-transfer command,
|
/* if this was an abort-transfer command,
|
||||||
flush all queued data. */
|
flush all queued data. */
|
||||||
if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
|
if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->flags |= FLAGS_DROP_DATA;
|
garmin_data_p->flags |= FLAGS_DROP_DATA;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
pkt_clear(garmin_data_p);
|
pkt_clear(garmin_data_p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -839,12 +862,15 @@ static void priv_status_resp(struct usb_serial_port *port)
|
|||||||
|
|
||||||
static int process_resetdev_request(struct usb_serial_port *port)
|
static int process_resetdev_request(struct usb_serial_port *port)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int status;
|
int status;
|
||||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->flags &= ~(CLEAR_HALT_REQUIRED);
|
garmin_data_p->flags &= ~(CLEAR_HALT_REQUIRED);
|
||||||
garmin_data_p->state = STATE_RESET;
|
garmin_data_p->state = STATE_RESET;
|
||||||
garmin_data_p->serial_num = 0;
|
garmin_data_p->serial_num = 0;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
|
|
||||||
usb_kill_urb (port->interrupt_in_urb);
|
usb_kill_urb (port->interrupt_in_urb);
|
||||||
dbg("%s - usb_reset_device", __FUNCTION__ );
|
dbg("%s - usb_reset_device", __FUNCTION__ );
|
||||||
@ -862,6 +888,7 @@ static int process_resetdev_request(struct usb_serial_port *port)
|
|||||||
*/
|
*/
|
||||||
static int garmin_clear(struct garmin_data * garmin_data_p)
|
static int garmin_clear(struct garmin_data * garmin_data_p)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
struct usb_serial_port *port = garmin_data_p->port;
|
struct usb_serial_port *port = garmin_data_p->port;
|
||||||
@ -875,8 +902,10 @@ static int garmin_clear(struct garmin_data * garmin_data_p)
|
|||||||
/* flush all queued data */
|
/* flush all queued data */
|
||||||
pkt_clear(garmin_data_p);
|
pkt_clear(garmin_data_p);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->insize = 0;
|
garmin_data_p->insize = 0;
|
||||||
garmin_data_p->outsize = 0;
|
garmin_data_p->outsize = 0;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -888,6 +917,7 @@ static int garmin_clear(struct garmin_data * garmin_data_p)
|
|||||||
|
|
||||||
static int garmin_init_session(struct usb_serial_port *port)
|
static int garmin_init_session(struct usb_serial_port *port)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
struct usb_serial *serial = port->serial;
|
struct usb_serial *serial = port->serial;
|
||||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||||
int status = 0;
|
int status = 0;
|
||||||
@ -913,7 +943,9 @@ static int garmin_init_session(struct usb_serial_port *port)
|
|||||||
|
|
||||||
if (status >= 0) {
|
if (status >= 0) {
|
||||||
|
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->ignorePkts++;
|
garmin_data_p->ignorePkts++;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
|
|
||||||
/* not needed, but the win32 driver does it too ... */
|
/* not needed, but the win32 driver does it too ... */
|
||||||
status = garmin_write_bulk(port,
|
status = garmin_write_bulk(port,
|
||||||
@ -921,7 +953,9 @@ static int garmin_init_session(struct usb_serial_port *port)
|
|||||||
sizeof(GARMIN_START_SESSION_REQ2));
|
sizeof(GARMIN_START_SESSION_REQ2));
|
||||||
if (status >= 0) {
|
if (status >= 0) {
|
||||||
status = 0;
|
status = 0;
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->ignorePkts++;
|
garmin_data_p->ignorePkts++;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -935,6 +969,7 @@ static int garmin_init_session(struct usb_serial_port *port)
|
|||||||
|
|
||||||
static int garmin_open (struct usb_serial_port *port, struct file *filp)
|
static int garmin_open (struct usb_serial_port *port, struct file *filp)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
@ -948,9 +983,11 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp)
|
|||||||
if (port->tty)
|
if (port->tty)
|
||||||
port->tty->low_latency = 1;
|
port->tty->low_latency = 1;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->mode = initial_mode;
|
garmin_data_p->mode = initial_mode;
|
||||||
garmin_data_p->count = 0;
|
garmin_data_p->count = 0;
|
||||||
garmin_data_p->flags = 0;
|
garmin_data_p->flags = 0;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
|
|
||||||
/* shutdown any bulk reads that might be going on */
|
/* shutdown any bulk reads that might be going on */
|
||||||
usb_kill_urb (port->write_urb);
|
usb_kill_urb (port->write_urb);
|
||||||
@ -996,6 +1033,7 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp)
|
|||||||
|
|
||||||
static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
|
static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
|
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
|
||||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
@ -1007,7 +1045,9 @@ static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
|
|||||||
if (urb->status) {
|
if (urb->status) {
|
||||||
dbg("%s - nonzero write bulk status received: %d",
|
dbg("%s - nonzero write bulk status received: %d",
|
||||||
__FUNCTION__, urb->status);
|
__FUNCTION__, urb->status);
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
|
garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_serial_port_softint(port);
|
usb_serial_port_softint(port);
|
||||||
@ -1015,8 +1055,9 @@ static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
|
|||||||
|
|
||||||
|
|
||||||
static int garmin_write_bulk (struct usb_serial_port *port,
|
static int garmin_write_bulk (struct usb_serial_port *port,
|
||||||
const unsigned char *buf, int count)
|
const unsigned char *buf, int count)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
struct usb_serial *serial = port->serial;
|
struct usb_serial *serial = port->serial;
|
||||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
@ -1026,7 +1067,9 @@ static int garmin_write_bulk (struct usb_serial_port *port,
|
|||||||
dbg("%s - port %d, state %d", __FUNCTION__, port->number,
|
dbg("%s - port %d, state %d", __FUNCTION__, port->number,
|
||||||
garmin_data_p->state);
|
garmin_data_p->state);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->flags &= ~FLAGS_DROP_DATA;
|
garmin_data_p->flags &= ~FLAGS_DROP_DATA;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
|
|
||||||
buffer = kmalloc (count, GFP_ATOMIC);
|
buffer = kmalloc (count, GFP_ATOMIC);
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
@ -1053,7 +1096,9 @@ static int garmin_write_bulk (struct usb_serial_port *port,
|
|||||||
urb->transfer_flags |= URB_ZERO_PACKET;
|
urb->transfer_flags |= URB_ZERO_PACKET;
|
||||||
|
|
||||||
if (GARMIN_LAYERID_APPL == getLayerId(buffer)) {
|
if (GARMIN_LAYERID_APPL == getLayerId(buffer)) {
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
|
garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
|
if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
|
||||||
pkt_clear(garmin_data_p);
|
pkt_clear(garmin_data_p);
|
||||||
garmin_data_p->state = STATE_GSP_WAIT_DATA;
|
garmin_data_p->state = STATE_GSP_WAIT_DATA;
|
||||||
@ -1087,8 +1132,9 @@ static int garmin_write_bulk (struct usb_serial_port *port,
|
|||||||
|
|
||||||
|
|
||||||
static int garmin_write (struct usb_serial_port *port,
|
static int garmin_write (struct usb_serial_port *port,
|
||||||
const unsigned char *buf, int count)
|
const unsigned char *buf, int count)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int pktid, pktsiz, len;
|
int pktid, pktsiz, len;
|
||||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||||
__le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
|
__le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
|
||||||
@ -1139,7 +1185,9 @@ static int garmin_write (struct usb_serial_port *port,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PRIV_PKTID_RESET_REQ:
|
case PRIV_PKTID_RESET_REQ:
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
|
garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRIV_PKTID_SET_DEF_MODE:
|
case PRIV_PKTID_SET_DEF_MODE:
|
||||||
@ -1155,6 +1203,8 @@ static int garmin_write (struct usb_serial_port *port,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
garmin_data_p->ignorePkts = 0;
|
||||||
|
|
||||||
if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
|
if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
|
||||||
return gsp_receive(garmin_data_p, buf, count);
|
return gsp_receive(garmin_data_p, buf, count);
|
||||||
} else { /* MODE_NATIVE */
|
} else { /* MODE_NATIVE */
|
||||||
@ -1177,10 +1227,10 @@ static int garmin_chars_in_buffer (struct usb_serial_port *port)
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Report back the number of bytes currently in our input buffer.
|
* Report back the number of bytes currently in our input buffer.
|
||||||
* Will this lock up the driver - the buffer contains an incomplete
|
* Will this lock up the driver - the buffer contains an incomplete
|
||||||
* package which will not be written to the device until it
|
* package which will not be written to the device until it
|
||||||
* has been completed ?
|
* has been completed ?
|
||||||
*/
|
*/
|
||||||
//struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
//struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||||
//return garmin_data_p->insize;
|
//return garmin_data_p->insize;
|
||||||
return 0;
|
return 0;
|
||||||
@ -1190,6 +1240,8 @@ static int garmin_chars_in_buffer (struct usb_serial_port *port)
|
|||||||
static void garmin_read_process(struct garmin_data * garmin_data_p,
|
static void garmin_read_process(struct garmin_data * garmin_data_p,
|
||||||
unsigned char *data, unsigned data_length)
|
unsigned char *data, unsigned data_length)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
if (garmin_data_p->flags & FLAGS_DROP_DATA) {
|
if (garmin_data_p->flags & FLAGS_DROP_DATA) {
|
||||||
/* abort-transfer cmd is actice */
|
/* abort-transfer cmd is actice */
|
||||||
dbg("%s - pkt dropped", __FUNCTION__);
|
dbg("%s - pkt dropped", __FUNCTION__);
|
||||||
@ -1200,11 +1252,14 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
|
|||||||
if a reset is required or not when closing
|
if a reset is required or not when closing
|
||||||
the device */
|
the device */
|
||||||
if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY,
|
if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY,
|
||||||
sizeof(GARMIN_APP_LAYER_REPLY)))
|
sizeof(GARMIN_APP_LAYER_REPLY))) {
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->flags |= FLAGS_APP_RESP_SEEN;
|
garmin_data_p->flags |= FLAGS_APP_RESP_SEEN;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
/* if throttling is active or postprecessing is required
|
/* if throttling is active or postprecessing is required
|
||||||
put the received data in th input queue, otherwise
|
put the received data in the input queue, otherwise
|
||||||
send it directly to the tty port */
|
send it directly to the tty port */
|
||||||
if (garmin_data_p->flags & FLAGS_QUEUING) {
|
if (garmin_data_p->flags & FLAGS_QUEUING) {
|
||||||
pkt_add(garmin_data_p, data, data_length);
|
pkt_add(garmin_data_p, data, data_length);
|
||||||
@ -1221,6 +1276,7 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
|
|||||||
|
|
||||||
static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
|
static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
|
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
|
||||||
struct usb_serial *serial = port->serial;
|
struct usb_serial *serial = port->serial;
|
||||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
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)
|
|||||||
|
|
||||||
garmin_read_process(garmin_data_p, data, urb->actual_length);
|
garmin_read_process(garmin_data_p, data, urb->actual_length);
|
||||||
|
|
||||||
/* Continue trying to read until nothing more is received */
|
if (urb->actual_length == 0 &&
|
||||||
if (urb->actual_length > 0) {
|
0 != (garmin_data_p->flags & FLAGS_BULK_IN_RESTART)) {
|
||||||
usb_fill_bulk_urb (port->read_urb, serial->dev,
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
usb_rcvbulkpipe (serial->dev,
|
garmin_data_p->flags &= ~FLAGS_BULK_IN_RESTART;
|
||||||
port->bulk_in_endpointAddress),
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
port->read_urb->transfer_buffer,
|
|
||||||
port->read_urb->transfer_buffer_length,
|
|
||||||
garmin_read_bulk_callback, port);
|
|
||||||
status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
|
status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
|
||||||
if (status)
|
if (status)
|
||||||
dev_err(&port->dev,
|
dev_err(&port->dev,
|
||||||
"%s - failed resubmitting read urb, error %d\n",
|
"%s - failed resubmitting read urb, error %d\n",
|
||||||
__FUNCTION__, status);
|
__FUNCTION__, status);
|
||||||
|
} else if (urb->actual_length > 0) {
|
||||||
|
/* Continue trying to read until nothing more is received */
|
||||||
|
if (0 == (garmin_data_p->flags & FLAGS_THROTTLED)) {
|
||||||
|
status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
|
||||||
|
if (status)
|
||||||
|
dev_err(&port->dev,
|
||||||
|
"%s - failed resubmitting read urb, error %d\n",
|
||||||
|
__FUNCTION__, status);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dbg("%s - end of bulk data", __FUNCTION__);
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
|
garmin_data_p->flags &= ~FLAGS_BULK_IN_ACTIVE;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1265,6 +1332,7 @@ 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)
|
static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int status;
|
int status;
|
||||||
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
|
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
|
||||||
struct usb_serial *serial = port->serial;
|
struct usb_serial *serial = port->serial;
|
||||||
@ -1297,25 +1365,41 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
|
|||||||
|
|
||||||
dbg("%s - bulk data available.", __FUNCTION__);
|
dbg("%s - bulk data available.", __FUNCTION__);
|
||||||
|
|
||||||
/* bulk data available */
|
if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
|
||||||
usb_fill_bulk_urb (port->read_urb, serial->dev,
|
|
||||||
usb_rcvbulkpipe (serial->dev,
|
/* bulk data available */
|
||||||
port->bulk_in_endpointAddress),
|
usb_fill_bulk_urb (port->read_urb, serial->dev,
|
||||||
port->read_urb->transfer_buffer,
|
usb_rcvbulkpipe (serial->dev,
|
||||||
port->read_urb->transfer_buffer_length,
|
port->bulk_in_endpointAddress),
|
||||||
garmin_read_bulk_callback, port);
|
port->read_urb->transfer_buffer,
|
||||||
status = usb_submit_urb(port->read_urb, GFP_KERNEL);
|
port->read_urb->transfer_buffer_length,
|
||||||
if (status) {
|
garmin_read_bulk_callback, port);
|
||||||
dev_err(&port->dev,
|
status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
|
||||||
"%s - failed submitting read urb, error %d\n",
|
if (status) {
|
||||||
__FUNCTION__, status);
|
dev_err(&port->dev,
|
||||||
|
"%s - failed submitting read urb, error %d\n",
|
||||||
|
__FUNCTION__, status);
|
||||||
|
} else {
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
|
garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE;
|
||||||
|
/* do not send this packet to the user */
|
||||||
|
garmin_data_p->ignorePkts = 1;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* bulk-in transfer still active */
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
|
garmin_data_p->flags |= FLAGS_BULK_IN_RESTART;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY))
|
} else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY))
|
||||||
&& 0 == memcmp(data, GARMIN_START_SESSION_REPLY,
|
&& 0 == memcmp(data, GARMIN_START_SESSION_REPLY,
|
||||||
sizeof(GARMIN_START_SESSION_REPLY))) {
|
sizeof(GARMIN_START_SESSION_REPLY))) {
|
||||||
|
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->flags |= FLAGS_SESSION_REPLY1_SEEN;
|
garmin_data_p->flags |= FLAGS_SESSION_REPLY1_SEEN;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
|
|
||||||
/* save the serial number */
|
/* save the serial number */
|
||||||
garmin_data_p->serial_num
|
garmin_data_p->serial_num
|
||||||
@ -1330,7 +1414,9 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
|
|||||||
ignore it. */
|
ignore it. */
|
||||||
dbg("%s - pkt ignored (%d)",
|
dbg("%s - pkt ignored (%d)",
|
||||||
__FUNCTION__, garmin_data_p->ignorePkts);
|
__FUNCTION__, garmin_data_p->ignorePkts);
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->ignorePkts--;
|
garmin_data_p->ignorePkts--;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
} else {
|
} else {
|
||||||
garmin_read_process(garmin_data_p, data, urb->actual_length);
|
garmin_read_process(garmin_data_p, data, urb->actual_length);
|
||||||
}
|
}
|
||||||
@ -1351,18 +1437,20 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
|
|||||||
*/
|
*/
|
||||||
static int garmin_flush_queue(struct garmin_data * garmin_data_p)
|
static int garmin_flush_queue(struct garmin_data * garmin_data_p)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
struct garmin_packet *pkt;
|
struct garmin_packet *pkt;
|
||||||
|
|
||||||
if ((garmin_data_p->flags & FLAGS_THROTTLED) == 0) {
|
if ((garmin_data_p->flags & FLAGS_THROTTLED) == 0) {
|
||||||
pkt = pkt_pop(garmin_data_p);
|
pkt = pkt_pop(garmin_data_p);
|
||||||
if (pkt != NULL) {
|
if (pkt != NULL) {
|
||||||
|
|
||||||
send_to_tty(garmin_data_p->port, pkt->data, pkt->size);
|
send_to_tty(garmin_data_p->port, pkt->data, pkt->size);
|
||||||
kfree(pkt);
|
kfree(pkt);
|
||||||
mod_timer(&garmin_data_p->timer, (1)+jiffies);
|
mod_timer(&garmin_data_p->timer, (1)+jiffies);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->flags &= ~FLAGS_QUEUING;
|
garmin_data_p->flags &= ~FLAGS_QUEUING;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1371,26 +1459,41 @@ static int garmin_flush_queue(struct garmin_data * garmin_data_p)
|
|||||||
|
|
||||||
static void garmin_throttle (struct usb_serial_port *port)
|
static void garmin_throttle (struct usb_serial_port *port)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
dbg("%s - port %d", __FUNCTION__, port->number);
|
dbg("%s - port %d", __FUNCTION__, port->number);
|
||||||
/* set flag, data received will be put into a queue
|
/* set flag, data received will be put into a queue
|
||||||
for later processing */
|
for later processing */
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED;
|
garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void garmin_unthrottle (struct usb_serial_port *port)
|
static void garmin_unthrottle (struct usb_serial_port *port)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||||
|
int status;
|
||||||
|
|
||||||
dbg("%s - port %d", __FUNCTION__, port->number);
|
dbg("%s - port %d", __FUNCTION__, port->number);
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
garmin_data_p->flags &= ~FLAGS_THROTTLED;
|
garmin_data_p->flags &= ~FLAGS_THROTTLED;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
|
|
||||||
/* in native mode send queued data to tty, in
|
/* in native mode send queued data to tty, in
|
||||||
serial mode nothing needs to be done here */
|
serial mode nothing needs to be done here */
|
||||||
if (garmin_data_p->mode == MODE_NATIVE)
|
if (garmin_data_p->mode == MODE_NATIVE)
|
||||||
garmin_flush_queue(garmin_data_p);
|
garmin_flush_queue(garmin_data_p);
|
||||||
|
|
||||||
|
if (0 != (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
|
||||||
|
status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
|
||||||
|
if (status)
|
||||||
|
dev_err(&port->dev,
|
||||||
|
"%s - failed resubmitting read urb, error %d\n",
|
||||||
|
__FUNCTION__, status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1420,11 +1523,12 @@ static int garmin_attach (struct usb_serial *serial)
|
|||||||
|
|
||||||
dbg("%s", __FUNCTION__);
|
dbg("%s", __FUNCTION__);
|
||||||
|
|
||||||
garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
|
garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL);
|
||||||
if (garmin_data_p == NULL) {
|
if (garmin_data_p == NULL) {
|
||||||
dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
|
dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
memset (garmin_data_p, 0, sizeof(struct garmin_data));
|
||||||
init_timer(&garmin_data_p->timer);
|
init_timer(&garmin_data_p->timer);
|
||||||
spin_lock_init(&garmin_data_p->lock);
|
spin_lock_init(&garmin_data_p->lock);
|
||||||
INIT_LIST_HEAD(&garmin_data_p->pktlist);
|
INIT_LIST_HEAD(&garmin_data_p->pktlist);
|
||||||
@ -1459,10 +1563,10 @@ static void garmin_shutdown (struct usb_serial *serial)
|
|||||||
/* All of the device info needed */
|
/* All of the device info needed */
|
||||||
static struct usb_serial_driver garmin_device = {
|
static struct usb_serial_driver garmin_device = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = "garmin_gps",
|
.name = "garmin_gps",
|
||||||
},
|
},
|
||||||
.description = "Garmin GPS usb/tty",
|
.description = "Garmin GPS usb/tty",
|
||||||
.id_table = id_table,
|
.id_table = id_table,
|
||||||
.num_interrupt_in = 1,
|
.num_interrupt_in = 1,
|
||||||
.num_bulk_in = 1,
|
.num_bulk_in = 1,
|
||||||
@ -1483,6 +1587,7 @@ static struct usb_serial_driver garmin_device = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int __init garmin_init (void)
|
static int __init garmin_init (void)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
Loading…
Reference in New Issue
Block a user