// SPDX-License-Identifier: GPL-2.0+
/*
* Garmin GPS driver
*
* Copyright (C) 2006-2011 Hermann Kneissel herkne@gmx.de
*
* The latest version of the driver can be found at
* http://sourceforge.net/projects/garmin-gps/
*
* This driver has been derived from v2.1 of the visor driver.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
/* the mode to be set when the port ist opened */
static int initial_mode = 1;
#define GARMIN_VENDOR_ID 0x091E
/*
* Version Information
*/
#define VERSION_MAJOR 0
#define VERSION_MINOR 36
#define _STR(s) #s
#define _DRIVER_VERSION(a, b) "v" _STR(a) "." _STR(b)
#define DRIVER_VERSION _DRIVER_VERSION(VERSION_MAJOR, VERSION_MINOR)
#define DRIVER_AUTHOR "hermann kneissel"
#define DRIVER_DESC "garmin gps driver"
/* error codes returned by the driver */
#define EINVPKT 1000 /* invalid packet structure */
/* size of the header of a packet using the usb protocol */
#define GARMIN_PKTHDR_LENGTH 12
/* max. possible size of a packet using the serial protocol */
#define MAX_SERIAL_PKT_SIZ (3 + 255 + 3)
/* max. possible size of a packet with worst case stuffing */
#define MAX_SERIAL_PKT_SIZ_STUFFED (MAX_SERIAL_PKT_SIZ + 256)
/* size of a buffer able to hold a complete (no stuffing) packet
* (the document protocol does not contain packets with a larger
* size, but in theory a packet may be 64k+12 bytes - if in
* later protocol versions larger packet sizes occur, this value
* should be increased accordingly, so the input buffer is always
* large enough the store a complete packet inclusive header) */
#define GPS_IN_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ)
/* size of a buffer able to hold a complete (incl. stuffing) packet */
#define GPS_OUT_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ_STUFFED)
/* where to place the packet id of a serial packet, so we can
* prepend the usb-packet header without the need to move the
* packets data */
#define GSP_INITIAL_OFFSET (GARMIN_PKTHDR_LENGTH-2)
/* max. size of incoming private packets (header+1 param) */
#define PRIVPKTSIZ (GARMIN_PKTHDR_LENGTH+4)
#define GARMIN_LAYERID_TRANSPORT 0
#define GARMIN_LAYERID_APPL 20
/* our own layer-id to use for some control mechanisms */
#define GARMIN_LAYERID_PRIVATE 0x01106E4B
#define GARMIN_PKTID_PVT_DATA 51
#define GARMIN_PKTID_L001_COMMAND_DATA 10
#define CMND_ABORT_TRANSFER 0
/* packet ids used in private layer */
#define PRIV_PKTID_SET_DEBUG 1
#define PRIV_PKTID_SET_MODE 2
#define PRIV_PKTID_INFO_REQ 3
#define PRIV_PKTID_INFO_RESP 4
#define PRIV_PKTID_RESET_REQ 5
#define PRIV_PKTID_SET_DEF_MODE 6
#define ETX 0x03
#define DLE 0x10
#define ACK 0x06
#define NAK 0x15
/* structure used to queue incoming packets */
struct garmin_packet {
struct list_head list;
int seq;