mirror of https://gitee.com/openkylin/linux.git
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
|
||||
*
|
||||
* 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
|
||||
* http://sourceforge.net/projects/garmin-gps/
|
||||
|
@ -37,6 +37,8 @@
|
|||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
/* the mode to be set when the port ist opened */
|
||||
static int initial_mode = 1;
|
||||
|
||||
|
@ -50,7 +52,7 @@ static int debug = 0;
|
|||
*/
|
||||
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 23
|
||||
#define VERSION_MINOR 28
|
||||
|
||||
#define _STR(s) #s
|
||||
#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_REPLY2_SEEN 0x0040
|
||||
#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 FLAGS_QUEUING 0x0100
|
||||
|
@ -224,7 +227,7 @@ static struct usb_driver garmin_driver = {
|
|||
.probe = usb_serial_probe,
|
||||
.disconnect = usb_serial_disconnect,
|
||||
.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,
|
||||
char *data, unsigned int actual_length)
|
||||
char *data, unsigned int actual_length)
|
||||
{
|
||||
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
|
||||
*/
|
||||
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;
|
||||
unsigned long flags;
|
||||
struct garmin_packet *pkt;
|
||||
|
||||
/* process only packets containg data ... */
|
||||
if (data_length) {
|
||||
garmin_data_p->flags |= FLAGS_QUEUING;
|
||||
pkt = kmalloc(sizeof(struct garmin_packet)+data_length,
|
||||
GFP_ATOMIC);
|
||||
if (pkt == NULL) {
|
||||
|
@ -313,14 +316,16 @@ static int pkt_add(struct garmin_data * garmin_data_p,
|
|||
memcpy(pkt->data, data, data_length);
|
||||
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
garmin_data_p->flags |= FLAGS_QUEUING;
|
||||
result = list_empty(&garmin_data_p->pktlist);
|
||||
pkt->seq = garmin_data_p->seq_counter++;
|
||||
list_add_tail(&pkt->list, &garmin_data_p->pktlist);
|
||||
state = garmin_data_p->state;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
|
||||
/* in serial mode, if someone is waiting for data from
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
__u8 pkt[10];
|
||||
__u8 cksum = 0;
|
||||
__u8 *ptr = pkt;
|
||||
unsigned l = 0;
|
||||
__u8 cksum = 0;
|
||||
__u8 *ptr = pkt;
|
||||
unsigned l = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
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 n = 0;
|
||||
|
@ -447,11 +452,11 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
|
|||
n++;
|
||||
}
|
||||
|
||||
if ((0xff & (cksum + *recpkt)) != 0) {
|
||||
dbg("%s - invalid checksum, expected %02x, got %02x",
|
||||
__FUNCTION__, 0xff & -cksum, 0xff & *recpkt);
|
||||
return -EINVPKT;
|
||||
}
|
||||
if ((0xff & (cksum + *recpkt)) != 0) {
|
||||
dbg("%s - invalid checksum, expected %02x, got %02x",
|
||||
__FUNCTION__, 0xff & -cksum, 0xff & *recpkt);
|
||||
return -EINVPKT;
|
||||
}
|
||||
|
||||
usbdata[0] = __cpu_to_le32(GARMIN_LAYERID_APPL);
|
||||
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,
|
||||
const unsigned char *buf, int count)
|
||||
const unsigned char *buf, int count)
|
||||
{
|
||||
unsigned long flags;
|
||||
int offs = 0;
|
||||
int ack_or_nak_seen = 0;
|
||||
int i = 0;
|
||||
__u8 *dest = garmin_data_p->inbuffer;
|
||||
int size = garmin_data_p->insize;
|
||||
__u8 *dest;
|
||||
int size;
|
||||
// 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
|
||||
// new packet
|
||||
int skip = garmin_data_p->flags & FLAGS_GSP_SKIP;
|
||||
int skip;
|
||||
__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",
|
||||
__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;
|
||||
|
||||
// copy flags back to structure
|
||||
|
@ -587,6 +602,11 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
|
|||
|
||||
if (ack_or_nak_seen) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -676,7 +696,7 @@ static int gsp_send(struct garmin_data * garmin_data_p,
|
|||
src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH;
|
||||
if (k > (GARMIN_PKTHDR_LENGTH-2)) {
|
||||
/* can't add stuffing DLEs in place, move data to end
|
||||
of buffer ... */
|
||||
of buffer ... */
|
||||
dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen;
|
||||
memcpy(dst, src, datalen);
|
||||
src = dst;
|
||||
|
@ -755,8 +775,9 @@ static void gsp_next_packet(struct garmin_data * garmin_data_p)
|
|||
* or even incomplete packets
|
||||
*/
|
||||
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;
|
||||
int offs = 0;
|
||||
int result = count;
|
||||
|
@ -803,7 +824,9 @@ static int nat_receive(struct garmin_data * garmin_data_p,
|
|||
/* if this was an abort-transfer command,
|
||||
flush all queued data. */
|
||||
if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
garmin_data_p->flags |= FLAGS_DROP_DATA;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
pkt_clear(garmin_data_p);
|
||||
}
|
||||
}
|
||||
|
@ -839,12 +862,15 @@ static void priv_status_resp(struct usb_serial_port *port)
|
|||
|
||||
static int process_resetdev_request(struct usb_serial_port *port)
|
||||
{
|
||||
unsigned long flags;
|
||||
int status;
|
||||
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->state = STATE_RESET;
|
||||
garmin_data_p->serial_num = 0;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
|
||||
usb_kill_urb (port->interrupt_in_urb);
|
||||
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)
|
||||
{
|
||||
unsigned long flags;
|
||||
int status = 0;
|
||||
|
||||
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 */
|
||||
pkt_clear(garmin_data_p);
|
||||
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
garmin_data_p->insize = 0;
|
||||
garmin_data_p->outsize = 0;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct usb_serial *serial = port->serial;
|
||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||
int status = 0;
|
||||
|
@ -913,7 +943,9 @@ static int garmin_init_session(struct usb_serial_port *port)
|
|||
|
||||
if (status >= 0) {
|
||||
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
garmin_data_p->ignorePkts++;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
|
||||
/* not needed, but the win32 driver does it too ... */
|
||||
status = garmin_write_bulk(port,
|
||||
|
@ -921,7 +953,9 @@ static int garmin_init_session(struct usb_serial_port *port)
|
|||
sizeof(GARMIN_START_SESSION_REQ2));
|
||||
if (status >= 0) {
|
||||
status = 0;
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
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)
|
||||
{
|
||||
unsigned long flags;
|
||||
int status = 0;
|
||||
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)
|
||||
port->tty->low_latency = 1;
|
||||
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
garmin_data_p->mode = initial_mode;
|
||||
garmin_data_p->count = 0;
|
||||
garmin_data_p->flags = 0;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
|
||||
/* shutdown any bulk reads that might be going on */
|
||||
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)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
|
||||
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) {
|
||||
dbg("%s - nonzero write bulk status received: %d",
|
||||
__FUNCTION__, urb->status);
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
}
|
||||
|
||||
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,
|
||||
const unsigned char *buf, int count)
|
||||
const unsigned char *buf, int count)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct usb_serial *serial = port->serial;
|
||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||
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,
|
||||
garmin_data_p->state);
|
||||
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
garmin_data_p->flags &= ~FLAGS_DROP_DATA;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
|
||||
buffer = kmalloc (count, GFP_ATOMIC);
|
||||
if (!buffer) {
|
||||
|
@ -1053,7 +1096,9 @@ static int garmin_write_bulk (struct usb_serial_port *port,
|
|||
urb->transfer_flags |= URB_ZERO_PACKET;
|
||||
|
||||
if (GARMIN_LAYERID_APPL == getLayerId(buffer)) {
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
|
||||
pkt_clear(garmin_data_p);
|
||||
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,
|
||||
const unsigned char *buf, int count)
|
||||
const unsigned char *buf, int count)
|
||||
{
|
||||
unsigned long flags;
|
||||
int pktid, pktsiz, len;
|
||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||
__le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
|
||||
|
@ -1139,7 +1185,9 @@ static int garmin_write (struct usb_serial_port *port,
|
|||
break;
|
||||
|
||||
case PRIV_PKTID_RESET_REQ:
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
break;
|
||||
|
||||
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) {
|
||||
return gsp_receive(garmin_data_p, buf, count);
|
||||
} 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.
|
||||
* Will this lock up the driver - the buffer contains an incomplete
|
||||
* package which will not be written to the device until it
|
||||
* has been completed ?
|
||||
*/
|
||||
* Will this lock up the driver - the buffer contains an incomplete
|
||||
* package which will not be written to the device until it
|
||||
* has been completed ?
|
||||
*/
|
||||
//struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||
//return garmin_data_p->insize;
|
||||
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,
|
||||
unsigned char *data, unsigned data_length)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (garmin_data_p->flags & FLAGS_DROP_DATA) {
|
||||
/* abort-transfer cmd is actice */
|
||||
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
|
||||
the device */
|
||||
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;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
if (garmin_data_p->flags & FLAGS_QUEUING) {
|
||||
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)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
|
||||
struct usb_serial *serial = port->serial;
|
||||
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);
|
||||
|
||||
/* Continue trying to read until nothing more is received */
|
||||
if (urb->actual_length > 0) {
|
||||
usb_fill_bulk_urb (port->read_urb, serial->dev,
|
||||
usb_rcvbulkpipe (serial->dev,
|
||||
port->bulk_in_endpointAddress),
|
||||
port->read_urb->transfer_buffer,
|
||||
port->read_urb->transfer_buffer_length,
|
||||
garmin_read_bulk_callback, port);
|
||||
if (urb->actual_length == 0 &&
|
||||
0 != (garmin_data_p->flags & FLAGS_BULK_IN_RESTART)) {
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
garmin_data_p->flags &= ~FLAGS_BULK_IN_RESTART;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
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 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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
unsigned long flags;
|
||||
int status;
|
||||
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
|
||||
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__);
|
||||
|
||||
/* bulk data available */
|
||||
usb_fill_bulk_urb (port->read_urb, serial->dev,
|
||||
usb_rcvbulkpipe (serial->dev,
|
||||
port->bulk_in_endpointAddress),
|
||||
port->read_urb->transfer_buffer,
|
||||
port->read_urb->transfer_buffer_length,
|
||||
garmin_read_bulk_callback, port);
|
||||
status = usb_submit_urb(port->read_urb, GFP_KERNEL);
|
||||
if (status) {
|
||||
dev_err(&port->dev,
|
||||
"%s - failed submitting read urb, error %d\n",
|
||||
__FUNCTION__, status);
|
||||
if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
|
||||
|
||||
/* bulk data available */
|
||||
usb_fill_bulk_urb (port->read_urb, serial->dev,
|
||||
usb_rcvbulkpipe (serial->dev,
|
||||
port->bulk_in_endpointAddress),
|
||||
port->read_urb->transfer_buffer,
|
||||
port->read_urb->transfer_buffer_length,
|
||||
garmin_read_bulk_callback, port);
|
||||
status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
|
||||
if (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))
|
||||
&& 0 == memcmp(data, 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;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
|
||||
/* save the serial number */
|
||||
garmin_data_p->serial_num
|
||||
|
@ -1330,7 +1414,9 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
|
|||
ignore it. */
|
||||
dbg("%s - pkt ignored (%d)",
|
||||
__FUNCTION__, garmin_data_p->ignorePkts);
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
garmin_data_p->ignorePkts--;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
} else {
|
||||
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)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct garmin_packet *pkt;
|
||||
|
||||
if ((garmin_data_p->flags & FLAGS_THROTTLED) == 0) {
|
||||
pkt = pkt_pop(garmin_data_p);
|
||||
if (pkt != NULL) {
|
||||
|
||||
send_to_tty(garmin_data_p->port, pkt->data, pkt->size);
|
||||
kfree(pkt);
|
||||
mod_timer(&garmin_data_p->timer, (1)+jiffies);
|
||||
|
||||
} else {
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
garmin_data_p->flags &= ~FLAGS_QUEUING;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||
|
||||
dbg("%s - port %d", __FUNCTION__, port->number);
|
||||
/* set flag, data received will be put into a queue
|
||||
for later processing */
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
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)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||
int status;
|
||||
|
||||
dbg("%s - port %d", __FUNCTION__, port->number);
|
||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||
garmin_data_p->flags &= ~FLAGS_THROTTLED;
|
||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||
|
||||
/* in native mode send queued data to tty, in
|
||||
serial mode nothing needs to be done here */
|
||||
if (garmin_data_p->mode == MODE_NATIVE)
|
||||
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__);
|
||||
|
||||
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) {
|
||||
dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (garmin_data_p, 0, sizeof(struct garmin_data));
|
||||
init_timer(&garmin_data_p->timer);
|
||||
spin_lock_init(&garmin_data_p->lock);
|
||||
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 */
|
||||
static struct usb_serial_driver garmin_device = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "garmin_gps",
|
||||
.owner = THIS_MODULE,
|
||||
.name = "garmin_gps",
|
||||
},
|
||||
.description = "Garmin GPS usb/tty",
|
||||
.description = "Garmin GPS usb/tty",
|
||||
.id_table = id_table,
|
||||
.num_interrupt_in = 1,
|
||||
.num_bulk_in = 1,
|
||||
|
@ -1483,6 +1587,7 @@ static struct usb_serial_driver garmin_device = {
|
|||
};
|
||||
|
||||
|
||||
|
||||
static int __init garmin_init (void)
|
||||
{
|
||||
int retval;
|
||||
|
|
Loading…
Reference in New Issue