// 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 <max-linux@enpas.org>
* slcan.c Author : Oliver Hartkopp <socketcan@hartkopp.net>
* slip.c Authors : Laurence Culhane <loz@holmes.demon.co.uk>
* Fred N. van Kempen <waltje@uwalt.nl.mugnet.org>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " 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 4
#define CAN327_SIZE_TXBUF 32
#define CAN327_SIZE_RXBUF 1024
#define CAN327_CAN_CONFIG_SEND_SFF 0x8000
#define CAN327_CAN_CONFIG_VARIABLE_DLC 0x4000
#define CAN327_CAN_CONFIG_RECV_BOTH_SFF_EFF 0x2000
#define CAN327_CAN_CONFIG_BAUDRATE_MULT_8_7 0x1000
#define CAN327_DUMMY_CHAR 'y'
#define CAN327_DUMMY_STRING "y"
#define CAN327_READY_CHAR '>'
/* Bits in elm->cmds_todo */
enum can327_tx_do {
CAN327_TX_DO_CAN_DATA = 0,
CAN327_TX_DO_CANID_11BIT,
CAN327_TX_DO_CANID_29BIT_LOW,
CAN327_TX_DO_CANID_29BIT_HIGH,
CAN327_TX_DO_CAN_CONFIG_PART2,
CAN327_TX_DO_CAN_CONFIG,
CAN327_TX_DO_RESPONSES,
CAN327_TX_DO_SILENT_MONITOR,
CAN327_TX_DO_INIT,
};
struct can327 {
/* This must be the first member when using alloc_candev() */
struct can_priv can;
struct can_rx_offload offload;
/* TTY buffers */
u8 txbuf[CAN327_SIZE_TXBUF];
u8 rxbuf[CAN327_SIZE_RXBUF];
/* Per-channel lock */
spinlock_t lock;
/* TTY and netdev devices that we're bridging */
struct tty_struct *tty;
struct net_device *dev;
/* TTY buffer accounting */
struct work_struct tx_work; /* Flushes TTY TX buffer */
u8 *txhead; /* Next TX byte */
size_t txleft; /* Bytes left to TX */
int rxfill; /* Bytes already RX'd in buffer */
/* State machine */
enum {
CAN327_STATE_NOTINIT = 0,
CAN327_STATE_GETDUMMYCHAR,
CAN327_STATE_GETPROMPT,
CAN327_STATE_RECEIVING,
} state;
/* Things we have yet to send */
char **next_init_cmd;
unsigned long cmds_todo;
/* The CAN frame and config the ELM327 is sending/using,
* or will send/use after finishing all cmds_todo
*/
struct can_frame can_frame_to_send;
u16 can_config;
u8 can_bitrate_divisor;
/* Parser state */
bool drop_next_line;
/* Stop the channel on UART side hardware failure, e.g. stray
* characters or neverending lines. This may be caused by bad
* UART wiring, a bad ELM327, a bad UART bridge...
* Once this is true, nothing will be sent to the TTY.
*/
bool uart_side_failure;
};
static inline void can327_uart_side_failure(struct can327 *elm);
static void can327_send(struct can327 *elm, const void *buf, size_t len)
{
int written;
lockdep_assert_held(&elm->lock);
if (elm->uart_side_failure)
return;
memcpy(elm->txbuf, buf, len);
/* Order of next two lines is *very* important.
* When we are sending a little amount of data,
* the transfer may be completed inside the ops->write()
* routine, because it's running with interrupts enabled.
* In this case we *never* got WRITE_WAKEUP event,
* if we did not request it before write operation.
* 14 Oct 1994 Dmitry Gorodchanin.
*/
set_bit(TTY_DO_WRITE_WAKEUP, &elm->tty->flags);
written = elm->tty->ops->write(elm->tty, elm->txbuf, len);
if (written < 0) {
netdev_err(elm->dev, "Failed to write to tty %s.\n",
elm->tty->name);
can327_uart_side_failure(elm);
return;
}
elm->txleft = len - written;
elm->txhead = elm->txbuf + written;
}
/* 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)
{
lockdep_assert_held(&elm->lock);
if (elm->state != CAN327_STATE_GETDUMMYCHAR &&
elm->state != CAN327_STATE_GETPROMPT) {
can327_send(elm, CAN327_DUMMY_STRING, 1);
elm->state = CAN327_STATE_GETDUMMYCHAR;
}
}
/* 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)
{
lockdep_assert_held(&elm->lock);
/* Schedule any necessary changes in ELM327's CAN configuration */
if (elm->can_frame_to_send.can_id != frame->can_id) {
/* Set the new CAN ID for transmission. */
if ((frame->can_id ^ elm->can_frame_to_send.can_id)
& CAN_EFF_FLAG) {
elm->can_config =
(frame->can_id & CAN_EFF_FLAG ? 0 : CAN327_CAN_CONFIG_SEND_SFF) |
CAN327_CAN_CONFIG_VARIABLE_DLC |
CAN327_CAN_CONFIG_RECV_BOTH_SFF_EFF |
elm->can_bitrate_divisor;
set_bit(CAN