linux/drivers/net/can/can327.c

// SPDX-License-Identifier: GPL-2.0
/* ELM327 based CAN interface driver (tty line discipline)
 *
 * This driver started as a derivative of linux/drivers/net/can/slcan.c
 * and my thanks go to the original authors for their inspiration.
 *
 * can327.c Author : Max Staudt <[email protected]>
 * slcan.c Author  : Oliver Hartkopp <[email protected]>
 * slip.c Authors  : Laurence Culhane <[email protected]>
 *                   Fred N. van Kempen <[email protected]>
 */

#define pr_fmt(fmt)

#include <linux/init.h>
#include <linux/module.h>

#include <linux/bitops.h>
#include <linux/ctype.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/lockdep.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/tty.h>
#include <linux/tty_ldisc.h>
#include <linux/workqueue.h>

#include <uapi/linux/tty.h>

#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include <linux/can/rx-offload.h>

#define CAN327_NAPI_WEIGHT

#define CAN327_SIZE_TXBUF
#define CAN327_SIZE_RXBUF

#define CAN327_CAN_CONFIG_SEND_SFF
#define CAN327_CAN_CONFIG_VARIABLE_DLC
#define CAN327_CAN_CONFIG_RECV_BOTH_SFF_EFF
#define CAN327_CAN_CONFIG_BAUDRATE_MULT_8_7

#define CAN327_DUMMY_CHAR
#define CAN327_DUMMY_STRING
#define CAN327_READY_CHAR

/* Bits in elm->cmds_todo */
enum can327_tx_do {};

struct can327 {};

static inline void can327_uart_side_failure(struct can327 *elm);

static void can327_send(struct can327 *elm, const void *buf, size_t len)
{}

/* Take the ELM327 out of almost any state and back into command mode.
 * We send CAN327_DUMMY_CHAR which will either abort any running
 * operation, or be echoed back to us in case we're already in command
 * mode.
 */
static void can327_kick_into_cmd_mode(struct can327 *elm)
{}

/* Schedule a CAN frame and necessary config changes to be sent to the TTY. */
static void can327_send_frame(struct can327 *elm, struct can_frame *frame)
{}

/* ELM327 initialisation sequence.
 * The line length is limited by the buffer in can327_handle_prompt().
 */
static char *can327_init_script[] =;

static void can327_init_device(struct can327 *elm)
{}

static void can327_feed_frame_to_netdev(struct can327 *elm, struct sk_buff *skb)
{}

/* Called when we're out of ideas and just want it all to end. */
static inline void can327_uart_side_failure(struct can327 *elm)
{}

/* Compares a byte buffer (non-NUL terminated) to the payload part of
 * a string, and returns true iff the buffer (content *and* length) is
 * exactly that string, without the terminating NUL byte.
 *
 * Example: If reference is "BUS ERROR", then this returns true iff nbytes == 9
 *          and !memcmp(buf, "BUS ERROR", 9).
 *
 * The reason to use strings is so we can easily include them in the C
 * code, and to avoid hardcoding lengths.
 */
static inline bool can327_rxbuf_cmp(const u8 *buf, size_t nbytes,
				    const char *reference)
{}

static void can327_parse_error(struct can327 *elm, size_t len)
{}

/* Parse CAN frames coming as ASCII from ELM327.
 * They can be of various formats:
 *
 * 29-bit ID (EFF):  12 34 56 78 D PL PL PL PL PL PL PL PL
 * 11-bit ID (!EFF): 123 D PL PL PL PL PL PL PL PL
 *
 * where D = DLC, PL = payload byte
 *
 * Instead of a payload, RTR indicates a remote request.
 *
 * We will use the spaces and line length to guess the format.
 */
static int can327_parse_frame(struct can327 *elm, size_t len)
{}

static void can327_parse_line(struct can327 *elm, size_t len)
{}

static void can327_handle_prompt(struct can327 *elm)
{}

static bool can327_is_ready_char(char c)
{}

static void can327_drop_bytes(struct can327 *elm, size_t i)
{}

static void can327_parse_rxbuf(struct can327 *elm, size_t first_new_char_idx)
{}

static int can327_netdev_open(struct net_device *dev)
{}

static int can327_netdev_close(struct net_device *dev)
{}

/* Send a can_frame to a TTY. */
static netdev_tx_t can327_netdev_start_xmit(struct sk_buff *skb,
					    struct net_device *dev)
{}

static const struct net_device_ops can327_netdev_ops =;

static const struct ethtool_ops can327_ethtool_ops =;

static bool can327_is_valid_rx_char(u8 c)
{}

/* Handle incoming ELM327 ASCII data.
 * This will not be re-entered while running, but other ldisc
 * functions may be called in parallel.
 */
static void can327_ldisc_rx(struct tty_struct *tty, const u8 *cp,
			    const u8 *fp, size_t count)
{}

/* Write out remaining transmit buffer.
 * Scheduled when TTY is writable.
 */
static void can327_ldisc_tx_worker(struct work_struct *work)
{}

/* Called by the driver when there's room for more data. */
static void can327_ldisc_tx_wakeup(struct tty_struct *tty)
{}

/* ELM327 can only handle bitrates that are integer divisors of 500 kHz,
 * or 7/8 of that. Divisors are 1 to 64.
 * Currently we don't implement support for 7/8 rates.
 */
static const u32 can327_bitrate_const[] =;

static int can327_ldisc_open(struct tty_struct *tty)
{}

/* Close down a can327 channel.
 * This means flushing out any pending queues, and then returning.
 * This call is serialized against other ldisc functions:
 * Once this is called, no other ldisc function of ours is entered.
 *
 * We also use this function for a hangup event.
 */
static void can327_ldisc_close(struct tty_struct *tty)
{}

static int can327_ldisc_ioctl(struct tty_struct *tty, unsigned int cmd,
			      unsigned long arg)
{}

static struct tty_ldisc_ops can327_ldisc =;

static int __init can327_init(void)
{}

static void __exit can327_exit(void)
{}

module_init();
module_exit(can327_exit);

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