linux/drivers/usb/serial/garmin_gps.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * Garmin GPS driver
 *
 * Copyright (C) 2006-2011 Hermann Kneissel [email protected]
 *
 * 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 =;

#define GARMIN_VENDOR_ID

/*
 * Version Information
 */

#define VERSION_MAJOR
#define VERSION_MINOR

#define _STR(s)
#define _DRIVER_VERSION(a, b)
#define DRIVER_VERSION
#define DRIVER_AUTHOR
#define DRIVER_DESC

/* error codes returned by the driver */
#define EINVPKT


/* size of the header of a packet using the usb protocol */
#define GARMIN_PKTHDR_LENGTH

/* max. possible size of a packet using the serial protocol */
#define MAX_SERIAL_PKT_SIZ

/*  max. possible size of a packet with worst case stuffing */
#define MAX_SERIAL_PKT_SIZ_STUFFED

/* 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

/* size of a buffer able to hold a complete (incl. stuffing) packet */
#define GPS_OUT_BUFSIZ

/* 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

/* max. size of incoming private packets (header+1 param) */
#define PRIVPKTSIZ

#define GARMIN_LAYERID_TRANSPORT
#define GARMIN_LAYERID_APPL
/* our own layer-id to use for some control mechanisms */
#define GARMIN_LAYERID_PRIVATE

#define GARMIN_PKTID_PVT_DATA
#define GARMIN_PKTID_L001_COMMAND_DATA

#define CMND_ABORT_TRANSFER

/* packet ids used in private layer */
#define PRIV_PKTID_SET_DEBUG
#define PRIV_PKTID_SET_MODE
#define PRIV_PKTID_INFO_REQ
#define PRIV_PKTID_INFO_RESP
#define PRIV_PKTID_RESET_REQ
#define PRIV_PKTID_SET_DEF_MODE


#define ETX
#define DLE
#define ACK
#define NAK

/* structure used to queue incoming packets */
struct garmin_packet {};

/* structure used to keep the current state of the driver */
struct garmin_data {};


#define STATE_NEW
#define STATE_INITIAL_DELAY
#define STATE_TIMEOUT
#define STATE_SESSION_REQ1
#define STATE_SESSION_REQ2
#define STATE_ACTIVE

#define STATE_RESET
#define STATE_DISCONNECTED
#define STATE_WAIT_TTY_ACK
#define STATE_GSP_WAIT_DATA

#define MODE_NATIVE
#define MODE_GARMIN_SERIAL

/* Flags used in garmin_data.flags: */
#define FLAGS_SESSION_REPLY_MASK
#define FLAGS_SESSION_REPLY1_SEEN
#define FLAGS_SESSION_REPLY2_SEEN
#define FLAGS_BULK_IN_ACTIVE
#define FLAGS_BULK_IN_RESTART
#define FLAGS_THROTTLED
#define APP_REQ_SEEN
#define APP_RESP_SEEN
#define CLEAR_HALT_REQUIRED

#define FLAGS_QUEUING
#define FLAGS_DROP_DATA

#define FLAGS_GSP_SKIP
#define FLAGS_GSP_DLESEEN






/* function prototypes */
static int gsp_next_packet(struct garmin_data *garmin_data_p);
static int garmin_write_bulk(struct usb_serial_port *port,
			     const unsigned char *buf, int count,
			     int dismiss_ack);

/* some special packets to be send or received */
static unsigned char const GARMIN_START_SESSION_REQ[]
	=;
static unsigned char const GARMIN_START_SESSION_REPLY[]
	=;
static unsigned char const GARMIN_BULK_IN_AVAIL_REPLY[]
	=;
static unsigned char const GARMIN_STOP_TRANSFER_REQ[]
	=;
static unsigned char const GARMIN_STOP_TRANSFER_REQ_V2[]
	=;

/* packets currently unused, left as documentation */
#if 0
static unsigned char const GARMIN_APP_LAYER_REPLY[]
	= { 0x14, 0, 0, 0 };
static unsigned char const GARMIN_START_PVT_REQ[]
	= { 20, 0, 0, 0,  10, 0, 0, 0, 2, 0, 0, 0, 49, 0 };
static unsigned char const GARMIN_STOP_PVT_REQ[]
	= { 20, 0, 0, 0,  10, 0, 0, 0, 2, 0, 0, 0, 50, 0 };
static unsigned char const PRIVATE_REQ[]
	=    { 0x4B, 0x6E, 0x10, 0x01,  0xFF, 0, 0, 0, 0xFF, 0, 0, 0 };
#endif


static const struct usb_device_id id_table[] =;
MODULE_DEVICE_TABLE(usb, id_table);


static inline int getLayerId(const __u8 *usbPacket)
{}

static inline int getPacketId(const __u8 *usbPacket)
{}

static inline int getDataLength(const __u8 *usbPacket)
{}


/*
 * check if the usb-packet in buf contains an abort-transfer command.
 * (if yes, all queued data will be dropped)
 */
static inline int isAbortTrfCmnd(const unsigned char *buf)
{}



static void send_to_tty(struct usb_serial_port *port,
			char *data, unsigned int actual_length)
{}


/******************************************************************************
 * packet queue handling
 ******************************************************************************/

/*
 * 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)
{}


/* get the next pending packet */
static struct garmin_packet *pkt_pop(struct garmin_data *garmin_data_p)
{}


/* free up all queued data */
static void pkt_clear(struct garmin_data *garmin_data_p)
{}


/******************************************************************************
 * garmin serial protocol handling handling
 ******************************************************************************/

/* send an ack packet back to the tty */
static int gsp_send_ack(struct garmin_data *garmin_data_p, __u8 pkt_id)
{}



/*
 * called for a complete packet received from tty layer
 *
 * the complete packet (pktid ... cksum) is in garmin_data_p->inbuf starting
 * at GSP_INITIAL_OFFSET.
 *
 * count - number of bytes in the input buffer including space reserved for
 *         the usb header: GSP_INITIAL_OFFSET + number of bytes in packet
 *         (including pkt-id, data-length a. cksum)
 */
static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count)
{}



/*
 * Called for data received from tty
 *
 * buf contains the data read, it may span more than one packet or even
 * incomplete packets
 *
 * input record should be a serial-record, but it may not be complete.
 * Copy it into our local buffer, until an etx is seen (or an error
 * occurs).
 * Once the record is complete, convert into a usb packet and send it
 * to the bulk pipe, send an ack back to the tty.
 *
 * If the input is an ack, just send the last queued packet to the
 * tty layer.
 *
 * if the input is an abort command, drop all queued data.
 */

static int gsp_receive(struct garmin_data *garmin_data_p,
		       const unsigned char *buf, int count)
{}



/*
 * Sends a usb packet to the tty
 *
 * Assumes, that all packages and at an usb-packet boundary.
 *
 * return <0 on error, 0 if packet is incomplete or > 0 if packet was sent
 */
static int gsp_send(struct garmin_data *garmin_data_p,
		    const unsigned char *buf, int count)
{}


/*
 * Process the next pending data packet - if there is one
 */
static int gsp_next_packet(struct garmin_data *garmin_data_p)
{}



/******************************************************************************
 * garmin native mode
 ******************************************************************************/


/*
 * Called for data received from tty
 *
 * The input data is expected to be in garmin usb-packet format.
 *
 * buf contains the data read, it may span more than one packet
 * or even incomplete packets
 */
static int nat_receive(struct garmin_data *garmin_data_p,
		       const unsigned char *buf, int count)
{}


/******************************************************************************
 * private packets
 ******************************************************************************/

static void priv_status_resp(struct usb_serial_port *port)
{}


/******************************************************************************
 * Garmin specific driver functions
 ******************************************************************************/

static int process_resetdev_request(struct usb_serial_port *port)
{}



/*
 * clear all cached data
 */
static int garmin_clear(struct garmin_data *garmin_data_p)
{}


static int garmin_init_session(struct usb_serial_port *port)
{}



static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port)
{}


static void garmin_close(struct usb_serial_port *port)
{}


static void garmin_write_bulk_callback(struct urb *urb)
{}


static int garmin_write_bulk(struct usb_serial_port *port,
			      const unsigned char *buf, int count,
			      int dismiss_ack)
{}

static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port,
					 const unsigned char *buf, int count)
{}


static unsigned int garmin_write_room(struct tty_struct *tty)
{}


static void garmin_read_process(struct garmin_data *garmin_data_p,
				 unsigned char *data, unsigned data_length,
				 int bulk_data)
{}


static void garmin_read_bulk_callback(struct urb *urb)
{}


static void garmin_read_int_callback(struct urb *urb)
{}


/*
 * Sends the next queued packt to the tty port (garmin native mode only)
 * and then sets a timer to call itself again until all queued data
 * is sent.
 */
static int garmin_flush_queue(struct garmin_data *garmin_data_p)
{}


static void garmin_throttle(struct tty_struct *tty)
{}


static void garmin_unthrottle(struct tty_struct *tty)
{}

/*
 * The timer is currently only used to send queued packets to
 * the tty in cases where the protocol provides no own handshaking
 * to initiate the transfer.
 */
static void timeout_handler(struct timer_list *t)
{}



static int garmin_port_probe(struct usb_serial_port *port)
{}


static void garmin_port_remove(struct usb_serial_port *port)
{}


/* All of the device info needed */
static struct usb_serial_driver garmin_device =;

static struct usb_serial_driver * const serial_drivers[] =;

module_usb_serial_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

module_param(initial_mode, int, 0444);
MODULE_PARM_DESC();