162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* ELM327 based CAN interface driver (tty line discipline) 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * This driver started as a derivative of linux/drivers/net/can/slcan.c 562306a36Sopenharmony_ci * and my thanks go to the original authors for their inspiration. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * can327.c Author : Max Staudt <max-linux@enpas.org> 862306a36Sopenharmony_ci * slcan.c Author : Oliver Hartkopp <socketcan@hartkopp.net> 962306a36Sopenharmony_ci * slip.c Authors : Laurence Culhane <loz@holmes.demon.co.uk> 1062306a36Sopenharmony_ci * Fred N. van Kempen <waltje@uwalt.nl.mugnet.org> 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/init.h> 1662306a36Sopenharmony_ci#include <linux/module.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <linux/bitops.h> 1962306a36Sopenharmony_ci#include <linux/ctype.h> 2062306a36Sopenharmony_ci#include <linux/errno.h> 2162306a36Sopenharmony_ci#include <linux/kernel.h> 2262306a36Sopenharmony_ci#include <linux/list.h> 2362306a36Sopenharmony_ci#include <linux/lockdep.h> 2462306a36Sopenharmony_ci#include <linux/netdevice.h> 2562306a36Sopenharmony_ci#include <linux/skbuff.h> 2662306a36Sopenharmony_ci#include <linux/spinlock.h> 2762306a36Sopenharmony_ci#include <linux/string.h> 2862306a36Sopenharmony_ci#include <linux/tty.h> 2962306a36Sopenharmony_ci#include <linux/tty_ldisc.h> 3062306a36Sopenharmony_ci#include <linux/workqueue.h> 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#include <uapi/linux/tty.h> 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#include <linux/can.h> 3562306a36Sopenharmony_ci#include <linux/can/dev.h> 3662306a36Sopenharmony_ci#include <linux/can/error.h> 3762306a36Sopenharmony_ci#include <linux/can/rx-offload.h> 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define CAN327_NAPI_WEIGHT 4 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#define CAN327_SIZE_TXBUF 32 4262306a36Sopenharmony_ci#define CAN327_SIZE_RXBUF 1024 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define CAN327_CAN_CONFIG_SEND_SFF 0x8000 4562306a36Sopenharmony_ci#define CAN327_CAN_CONFIG_VARIABLE_DLC 0x4000 4662306a36Sopenharmony_ci#define CAN327_CAN_CONFIG_RECV_BOTH_SFF_EFF 0x2000 4762306a36Sopenharmony_ci#define CAN327_CAN_CONFIG_BAUDRATE_MULT_8_7 0x1000 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define CAN327_DUMMY_CHAR 'y' 5062306a36Sopenharmony_ci#define CAN327_DUMMY_STRING "y" 5162306a36Sopenharmony_ci#define CAN327_READY_CHAR '>' 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* Bits in elm->cmds_todo */ 5462306a36Sopenharmony_cienum can327_tx_do { 5562306a36Sopenharmony_ci CAN327_TX_DO_CAN_DATA = 0, 5662306a36Sopenharmony_ci CAN327_TX_DO_CANID_11BIT, 5762306a36Sopenharmony_ci CAN327_TX_DO_CANID_29BIT_LOW, 5862306a36Sopenharmony_ci CAN327_TX_DO_CANID_29BIT_HIGH, 5962306a36Sopenharmony_ci CAN327_TX_DO_CAN_CONFIG_PART2, 6062306a36Sopenharmony_ci CAN327_TX_DO_CAN_CONFIG, 6162306a36Sopenharmony_ci CAN327_TX_DO_RESPONSES, 6262306a36Sopenharmony_ci CAN327_TX_DO_SILENT_MONITOR, 6362306a36Sopenharmony_ci CAN327_TX_DO_INIT, 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistruct can327 { 6762306a36Sopenharmony_ci /* This must be the first member when using alloc_candev() */ 6862306a36Sopenharmony_ci struct can_priv can; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci struct can_rx_offload offload; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci /* TTY buffers */ 7362306a36Sopenharmony_ci u8 txbuf[CAN327_SIZE_TXBUF]; 7462306a36Sopenharmony_ci u8 rxbuf[CAN327_SIZE_RXBUF]; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci /* Per-channel lock */ 7762306a36Sopenharmony_ci spinlock_t lock; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci /* TTY and netdev devices that we're bridging */ 8062306a36Sopenharmony_ci struct tty_struct *tty; 8162306a36Sopenharmony_ci struct net_device *dev; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* TTY buffer accounting */ 8462306a36Sopenharmony_ci struct work_struct tx_work; /* Flushes TTY TX buffer */ 8562306a36Sopenharmony_ci u8 *txhead; /* Next TX byte */ 8662306a36Sopenharmony_ci size_t txleft; /* Bytes left to TX */ 8762306a36Sopenharmony_ci int rxfill; /* Bytes already RX'd in buffer */ 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci /* State machine */ 9062306a36Sopenharmony_ci enum { 9162306a36Sopenharmony_ci CAN327_STATE_NOTINIT = 0, 9262306a36Sopenharmony_ci CAN327_STATE_GETDUMMYCHAR, 9362306a36Sopenharmony_ci CAN327_STATE_GETPROMPT, 9462306a36Sopenharmony_ci CAN327_STATE_RECEIVING, 9562306a36Sopenharmony_ci } state; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* Things we have yet to send */ 9862306a36Sopenharmony_ci char **next_init_cmd; 9962306a36Sopenharmony_ci unsigned long cmds_todo; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* The CAN frame and config the ELM327 is sending/using, 10262306a36Sopenharmony_ci * or will send/use after finishing all cmds_todo 10362306a36Sopenharmony_ci */ 10462306a36Sopenharmony_ci struct can_frame can_frame_to_send; 10562306a36Sopenharmony_ci u16 can_config; 10662306a36Sopenharmony_ci u8 can_bitrate_divisor; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci /* Parser state */ 10962306a36Sopenharmony_ci bool drop_next_line; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci /* Stop the channel on UART side hardware failure, e.g. stray 11262306a36Sopenharmony_ci * characters or neverending lines. This may be caused by bad 11362306a36Sopenharmony_ci * UART wiring, a bad ELM327, a bad UART bridge... 11462306a36Sopenharmony_ci * Once this is true, nothing will be sent to the TTY. 11562306a36Sopenharmony_ci */ 11662306a36Sopenharmony_ci bool uart_side_failure; 11762306a36Sopenharmony_ci}; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic inline void can327_uart_side_failure(struct can327 *elm); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistatic void can327_send(struct can327 *elm, const void *buf, size_t len) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci int written; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci lockdep_assert_held(&elm->lock); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (elm->uart_side_failure) 12862306a36Sopenharmony_ci return; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci memcpy(elm->txbuf, buf, len); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci /* Order of next two lines is *very* important. 13362306a36Sopenharmony_ci * When we are sending a little amount of data, 13462306a36Sopenharmony_ci * the transfer may be completed inside the ops->write() 13562306a36Sopenharmony_ci * routine, because it's running with interrupts enabled. 13662306a36Sopenharmony_ci * In this case we *never* got WRITE_WAKEUP event, 13762306a36Sopenharmony_ci * if we did not request it before write operation. 13862306a36Sopenharmony_ci * 14 Oct 1994 Dmitry Gorodchanin. 13962306a36Sopenharmony_ci */ 14062306a36Sopenharmony_ci set_bit(TTY_DO_WRITE_WAKEUP, &elm->tty->flags); 14162306a36Sopenharmony_ci written = elm->tty->ops->write(elm->tty, elm->txbuf, len); 14262306a36Sopenharmony_ci if (written < 0) { 14362306a36Sopenharmony_ci netdev_err(elm->dev, "Failed to write to tty %s.\n", 14462306a36Sopenharmony_ci elm->tty->name); 14562306a36Sopenharmony_ci can327_uart_side_failure(elm); 14662306a36Sopenharmony_ci return; 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci elm->txleft = len - written; 15062306a36Sopenharmony_ci elm->txhead = elm->txbuf + written; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/* Take the ELM327 out of almost any state and back into command mode. 15462306a36Sopenharmony_ci * We send CAN327_DUMMY_CHAR which will either abort any running 15562306a36Sopenharmony_ci * operation, or be echoed back to us in case we're already in command 15662306a36Sopenharmony_ci * mode. 15762306a36Sopenharmony_ci */ 15862306a36Sopenharmony_cistatic void can327_kick_into_cmd_mode(struct can327 *elm) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci lockdep_assert_held(&elm->lock); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci if (elm->state != CAN327_STATE_GETDUMMYCHAR && 16362306a36Sopenharmony_ci elm->state != CAN327_STATE_GETPROMPT) { 16462306a36Sopenharmony_ci can327_send(elm, CAN327_DUMMY_STRING, 1); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci elm->state = CAN327_STATE_GETDUMMYCHAR; 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci/* Schedule a CAN frame and necessary config changes to be sent to the TTY. */ 17162306a36Sopenharmony_cistatic void can327_send_frame(struct can327 *elm, struct can_frame *frame) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci lockdep_assert_held(&elm->lock); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci /* Schedule any necessary changes in ELM327's CAN configuration */ 17662306a36Sopenharmony_ci if (elm->can_frame_to_send.can_id != frame->can_id) { 17762306a36Sopenharmony_ci /* Set the new CAN ID for transmission. */ 17862306a36Sopenharmony_ci if ((frame->can_id ^ elm->can_frame_to_send.can_id) 17962306a36Sopenharmony_ci & CAN_EFF_FLAG) { 18062306a36Sopenharmony_ci elm->can_config = 18162306a36Sopenharmony_ci (frame->can_id & CAN_EFF_FLAG ? 0 : CAN327_CAN_CONFIG_SEND_SFF) | 18262306a36Sopenharmony_ci CAN327_CAN_CONFIG_VARIABLE_DLC | 18362306a36Sopenharmony_ci CAN327_CAN_CONFIG_RECV_BOTH_SFF_EFF | 18462306a36Sopenharmony_ci elm->can_bitrate_divisor; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci set_bit(CAN327_TX_DO_CAN_CONFIG, &elm->cmds_todo); 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci if (frame->can_id & CAN_EFF_FLAG) { 19062306a36Sopenharmony_ci clear_bit(CAN327_TX_DO_CANID_11BIT, &elm->cmds_todo); 19162306a36Sopenharmony_ci set_bit(CAN327_TX_DO_CANID_29BIT_LOW, &elm->cmds_todo); 19262306a36Sopenharmony_ci set_bit(CAN327_TX_DO_CANID_29BIT_HIGH, &elm->cmds_todo); 19362306a36Sopenharmony_ci } else { 19462306a36Sopenharmony_ci set_bit(CAN327_TX_DO_CANID_11BIT, &elm->cmds_todo); 19562306a36Sopenharmony_ci clear_bit(CAN327_TX_DO_CANID_29BIT_LOW, 19662306a36Sopenharmony_ci &elm->cmds_todo); 19762306a36Sopenharmony_ci clear_bit(CAN327_TX_DO_CANID_29BIT_HIGH, 19862306a36Sopenharmony_ci &elm->cmds_todo); 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci /* Schedule the CAN frame itself. */ 20362306a36Sopenharmony_ci elm->can_frame_to_send = *frame; 20462306a36Sopenharmony_ci set_bit(CAN327_TX_DO_CAN_DATA, &elm->cmds_todo); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci can327_kick_into_cmd_mode(elm); 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci/* ELM327 initialisation sequence. 21062306a36Sopenharmony_ci * The line length is limited by the buffer in can327_handle_prompt(). 21162306a36Sopenharmony_ci */ 21262306a36Sopenharmony_cistatic char *can327_init_script[] = { 21362306a36Sopenharmony_ci "AT WS\r", /* v1.0: Warm Start */ 21462306a36Sopenharmony_ci "AT PP FF OFF\r", /* v1.0: All Programmable Parameters Off */ 21562306a36Sopenharmony_ci "AT M0\r", /* v1.0: Memory Off */ 21662306a36Sopenharmony_ci "AT AL\r", /* v1.0: Allow Long messages */ 21762306a36Sopenharmony_ci "AT BI\r", /* v1.0: Bypass Initialisation */ 21862306a36Sopenharmony_ci "AT CAF0\r", /* v1.0: CAN Auto Formatting Off */ 21962306a36Sopenharmony_ci "AT CFC0\r", /* v1.0: CAN Flow Control Off */ 22062306a36Sopenharmony_ci "AT CF 000\r", /* v1.0: Reset CAN ID Filter */ 22162306a36Sopenharmony_ci "AT CM 000\r", /* v1.0: Reset CAN ID Mask */ 22262306a36Sopenharmony_ci "AT E1\r", /* v1.0: Echo On */ 22362306a36Sopenharmony_ci "AT H1\r", /* v1.0: Headers On */ 22462306a36Sopenharmony_ci "AT L0\r", /* v1.0: Linefeeds Off */ 22562306a36Sopenharmony_ci "AT SH 7DF\r", /* v1.0: Set CAN sending ID to 0x7df */ 22662306a36Sopenharmony_ci "AT ST FF\r", /* v1.0: Set maximum Timeout for response after TX */ 22762306a36Sopenharmony_ci "AT AT0\r", /* v1.2: Adaptive Timing Off */ 22862306a36Sopenharmony_ci "AT D1\r", /* v1.3: Print DLC On */ 22962306a36Sopenharmony_ci "AT S1\r", /* v1.3: Spaces On */ 23062306a36Sopenharmony_ci "AT TP B\r", /* v1.0: Try Protocol B */ 23162306a36Sopenharmony_ci NULL 23262306a36Sopenharmony_ci}; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic void can327_init_device(struct can327 *elm) 23562306a36Sopenharmony_ci{ 23662306a36Sopenharmony_ci lockdep_assert_held(&elm->lock); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci elm->state = CAN327_STATE_NOTINIT; 23962306a36Sopenharmony_ci elm->can_frame_to_send.can_id = 0x7df; /* ELM327 HW default */ 24062306a36Sopenharmony_ci elm->rxfill = 0; 24162306a36Sopenharmony_ci elm->drop_next_line = 0; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* We can only set the bitrate as a fraction of 500000. 24462306a36Sopenharmony_ci * The bitrates listed in can327_bitrate_const will 24562306a36Sopenharmony_ci * limit the user to the right values. 24662306a36Sopenharmony_ci */ 24762306a36Sopenharmony_ci elm->can_bitrate_divisor = 500000 / elm->can.bittiming.bitrate; 24862306a36Sopenharmony_ci elm->can_config = 24962306a36Sopenharmony_ci CAN327_CAN_CONFIG_SEND_SFF | CAN327_CAN_CONFIG_VARIABLE_DLC | 25062306a36Sopenharmony_ci CAN327_CAN_CONFIG_RECV_BOTH_SFF_EFF | elm->can_bitrate_divisor; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci /* Configure ELM327 and then start monitoring */ 25362306a36Sopenharmony_ci elm->next_init_cmd = &can327_init_script[0]; 25462306a36Sopenharmony_ci set_bit(CAN327_TX_DO_INIT, &elm->cmds_todo); 25562306a36Sopenharmony_ci set_bit(CAN327_TX_DO_SILENT_MONITOR, &elm->cmds_todo); 25662306a36Sopenharmony_ci set_bit(CAN327_TX_DO_RESPONSES, &elm->cmds_todo); 25762306a36Sopenharmony_ci set_bit(CAN327_TX_DO_CAN_CONFIG, &elm->cmds_todo); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci can327_kick_into_cmd_mode(elm); 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cistatic void can327_feed_frame_to_netdev(struct can327 *elm, struct sk_buff *skb) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci lockdep_assert_held(&elm->lock); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci if (!netif_running(elm->dev)) { 26762306a36Sopenharmony_ci kfree_skb(skb); 26862306a36Sopenharmony_ci return; 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* Queue for NAPI pickup. 27262306a36Sopenharmony_ci * rx-offload will update stats and LEDs for us. 27362306a36Sopenharmony_ci */ 27462306a36Sopenharmony_ci if (can_rx_offload_queue_tail(&elm->offload, skb)) 27562306a36Sopenharmony_ci elm->dev->stats.rx_fifo_errors++; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci /* Wake NAPI */ 27862306a36Sopenharmony_ci can_rx_offload_irq_finish(&elm->offload); 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci/* Called when we're out of ideas and just want it all to end. */ 28262306a36Sopenharmony_cistatic inline void can327_uart_side_failure(struct can327 *elm) 28362306a36Sopenharmony_ci{ 28462306a36Sopenharmony_ci struct can_frame *frame; 28562306a36Sopenharmony_ci struct sk_buff *skb; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci lockdep_assert_held(&elm->lock); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci elm->uart_side_failure = true; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci clear_bit(TTY_DO_WRITE_WAKEUP, &elm->tty->flags); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci elm->can.can_stats.bus_off++; 29462306a36Sopenharmony_ci netif_stop_queue(elm->dev); 29562306a36Sopenharmony_ci elm->can.state = CAN_STATE_BUS_OFF; 29662306a36Sopenharmony_ci can_bus_off(elm->dev); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci netdev_err(elm->dev, 29962306a36Sopenharmony_ci "ELM327 misbehaved. Blocking further communication.\n"); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci skb = alloc_can_err_skb(elm->dev, &frame); 30262306a36Sopenharmony_ci if (!skb) 30362306a36Sopenharmony_ci return; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci frame->can_id |= CAN_ERR_BUSOFF; 30662306a36Sopenharmony_ci can327_feed_frame_to_netdev(elm, skb); 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci/* Compares a byte buffer (non-NUL terminated) to the payload part of 31062306a36Sopenharmony_ci * a string, and returns true iff the buffer (content *and* length) is 31162306a36Sopenharmony_ci * exactly that string, without the terminating NUL byte. 31262306a36Sopenharmony_ci * 31362306a36Sopenharmony_ci * Example: If reference is "BUS ERROR", then this returns true iff nbytes == 9 31462306a36Sopenharmony_ci * and !memcmp(buf, "BUS ERROR", 9). 31562306a36Sopenharmony_ci * 31662306a36Sopenharmony_ci * The reason to use strings is so we can easily include them in the C 31762306a36Sopenharmony_ci * code, and to avoid hardcoding lengths. 31862306a36Sopenharmony_ci */ 31962306a36Sopenharmony_cistatic inline bool can327_rxbuf_cmp(const u8 *buf, size_t nbytes, 32062306a36Sopenharmony_ci const char *reference) 32162306a36Sopenharmony_ci{ 32262306a36Sopenharmony_ci size_t ref_len = strlen(reference); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci return (nbytes == ref_len) && !memcmp(buf, reference, ref_len); 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cistatic void can327_parse_error(struct can327 *elm, size_t len) 32862306a36Sopenharmony_ci{ 32962306a36Sopenharmony_ci struct can_frame *frame; 33062306a36Sopenharmony_ci struct sk_buff *skb; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci lockdep_assert_held(&elm->lock); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci skb = alloc_can_err_skb(elm->dev, &frame); 33562306a36Sopenharmony_ci if (!skb) 33662306a36Sopenharmony_ci /* It's okay to return here: 33762306a36Sopenharmony_ci * The outer parsing loop will drop this UART buffer. 33862306a36Sopenharmony_ci */ 33962306a36Sopenharmony_ci return; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci /* Filter possible error messages based on length of RX'd line */ 34262306a36Sopenharmony_ci if (can327_rxbuf_cmp(elm->rxbuf, len, "UNABLE TO CONNECT")) { 34362306a36Sopenharmony_ci netdev_err(elm->dev, 34462306a36Sopenharmony_ci "ELM327 reported UNABLE TO CONNECT. Please check your setup.\n"); 34562306a36Sopenharmony_ci } else if (can327_rxbuf_cmp(elm->rxbuf, len, "BUFFER FULL")) { 34662306a36Sopenharmony_ci /* This will only happen if the last data line was complete. 34762306a36Sopenharmony_ci * Otherwise, can327_parse_frame() will heuristically 34862306a36Sopenharmony_ci * emit this kind of error frame instead. 34962306a36Sopenharmony_ci */ 35062306a36Sopenharmony_ci frame->can_id |= CAN_ERR_CRTL; 35162306a36Sopenharmony_ci frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; 35262306a36Sopenharmony_ci } else if (can327_rxbuf_cmp(elm->rxbuf, len, "BUS ERROR")) { 35362306a36Sopenharmony_ci frame->can_id |= CAN_ERR_BUSERROR; 35462306a36Sopenharmony_ci } else if (can327_rxbuf_cmp(elm->rxbuf, len, "CAN ERROR")) { 35562306a36Sopenharmony_ci frame->can_id |= CAN_ERR_PROT; 35662306a36Sopenharmony_ci } else if (can327_rxbuf_cmp(elm->rxbuf, len, "<RX ERROR")) { 35762306a36Sopenharmony_ci frame->can_id |= CAN_ERR_PROT; 35862306a36Sopenharmony_ci } else if (can327_rxbuf_cmp(elm->rxbuf, len, "BUS BUSY")) { 35962306a36Sopenharmony_ci frame->can_id |= CAN_ERR_PROT; 36062306a36Sopenharmony_ci frame->data[2] = CAN_ERR_PROT_OVERLOAD; 36162306a36Sopenharmony_ci } else if (can327_rxbuf_cmp(elm->rxbuf, len, "FB ERROR")) { 36262306a36Sopenharmony_ci frame->can_id |= CAN_ERR_PROT; 36362306a36Sopenharmony_ci frame->data[2] = CAN_ERR_PROT_TX; 36462306a36Sopenharmony_ci } else if (len == 5 && !memcmp(elm->rxbuf, "ERR", 3)) { 36562306a36Sopenharmony_ci /* ERR is followed by two digits, hence line length 5 */ 36662306a36Sopenharmony_ci netdev_err(elm->dev, "ELM327 reported an ERR%c%c. Please power it off and on again.\n", 36762306a36Sopenharmony_ci elm->rxbuf[3], elm->rxbuf[4]); 36862306a36Sopenharmony_ci frame->can_id |= CAN_ERR_CRTL; 36962306a36Sopenharmony_ci } else { 37062306a36Sopenharmony_ci /* Something else has happened. 37162306a36Sopenharmony_ci * Maybe garbage on the UART line. 37262306a36Sopenharmony_ci * Emit a generic error frame. 37362306a36Sopenharmony_ci */ 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci can327_feed_frame_to_netdev(elm, skb); 37762306a36Sopenharmony_ci} 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci/* Parse CAN frames coming as ASCII from ELM327. 38062306a36Sopenharmony_ci * They can be of various formats: 38162306a36Sopenharmony_ci * 38262306a36Sopenharmony_ci * 29-bit ID (EFF): 12 34 56 78 D PL PL PL PL PL PL PL PL 38362306a36Sopenharmony_ci * 11-bit ID (!EFF): 123 D PL PL PL PL PL PL PL PL 38462306a36Sopenharmony_ci * 38562306a36Sopenharmony_ci * where D = DLC, PL = payload byte 38662306a36Sopenharmony_ci * 38762306a36Sopenharmony_ci * Instead of a payload, RTR indicates a remote request. 38862306a36Sopenharmony_ci * 38962306a36Sopenharmony_ci * We will use the spaces and line length to guess the format. 39062306a36Sopenharmony_ci */ 39162306a36Sopenharmony_cistatic int can327_parse_frame(struct can327 *elm, size_t len) 39262306a36Sopenharmony_ci{ 39362306a36Sopenharmony_ci struct can_frame *frame; 39462306a36Sopenharmony_ci struct sk_buff *skb; 39562306a36Sopenharmony_ci int hexlen; 39662306a36Sopenharmony_ci int datastart; 39762306a36Sopenharmony_ci int i; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci lockdep_assert_held(&elm->lock); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci skb = alloc_can_skb(elm->dev, &frame); 40262306a36Sopenharmony_ci if (!skb) 40362306a36Sopenharmony_ci return -ENOMEM; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci /* Find first non-hex and non-space character: 40662306a36Sopenharmony_ci * - In the simplest case, there is none. 40762306a36Sopenharmony_ci * - For RTR frames, 'R' is the first non-hex character. 40862306a36Sopenharmony_ci * - An error message may replace the end of the data line. 40962306a36Sopenharmony_ci */ 41062306a36Sopenharmony_ci for (hexlen = 0; hexlen <= len; hexlen++) { 41162306a36Sopenharmony_ci if (hex_to_bin(elm->rxbuf[hexlen]) < 0 && 41262306a36Sopenharmony_ci elm->rxbuf[hexlen] != ' ') { 41362306a36Sopenharmony_ci break; 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci } 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci /* Sanity check whether the line is really a clean hexdump, 41862306a36Sopenharmony_ci * or terminated by an error message, or contains garbage. 41962306a36Sopenharmony_ci */ 42062306a36Sopenharmony_ci if (hexlen < len && !isdigit(elm->rxbuf[hexlen]) && 42162306a36Sopenharmony_ci !isupper(elm->rxbuf[hexlen]) && '<' != elm->rxbuf[hexlen] && 42262306a36Sopenharmony_ci ' ' != elm->rxbuf[hexlen]) { 42362306a36Sopenharmony_ci /* The line is likely garbled anyway, so bail. 42462306a36Sopenharmony_ci * The main code will restart listening. 42562306a36Sopenharmony_ci */ 42662306a36Sopenharmony_ci kfree_skb(skb); 42762306a36Sopenharmony_ci return -ENODATA; 42862306a36Sopenharmony_ci } 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci /* Use spaces in CAN ID to distinguish 29 or 11 bit address length. 43162306a36Sopenharmony_ci * No out-of-bounds access: 43262306a36Sopenharmony_ci * We use the fact that we can always read from elm->rxbuf. 43362306a36Sopenharmony_ci */ 43462306a36Sopenharmony_ci if (elm->rxbuf[2] == ' ' && elm->rxbuf[5] == ' ' && 43562306a36Sopenharmony_ci elm->rxbuf[8] == ' ' && elm->rxbuf[11] == ' ' && 43662306a36Sopenharmony_ci elm->rxbuf[13] == ' ') { 43762306a36Sopenharmony_ci frame->can_id = CAN_EFF_FLAG; 43862306a36Sopenharmony_ci datastart = 14; 43962306a36Sopenharmony_ci } else if (elm->rxbuf[3] == ' ' && elm->rxbuf[5] == ' ') { 44062306a36Sopenharmony_ci datastart = 6; 44162306a36Sopenharmony_ci } else { 44262306a36Sopenharmony_ci /* This is not a well-formatted data line. 44362306a36Sopenharmony_ci * Assume it's an error message. 44462306a36Sopenharmony_ci */ 44562306a36Sopenharmony_ci kfree_skb(skb); 44662306a36Sopenharmony_ci return -ENODATA; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci if (hexlen < datastart) { 45062306a36Sopenharmony_ci /* The line is too short to be a valid frame hex dump. 45162306a36Sopenharmony_ci * Something interrupted the hex dump or it is invalid. 45262306a36Sopenharmony_ci */ 45362306a36Sopenharmony_ci kfree_skb(skb); 45462306a36Sopenharmony_ci return -ENODATA; 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci /* From here on all chars up to buf[hexlen] are hex or spaces, 45862306a36Sopenharmony_ci * at well-defined offsets. 45962306a36Sopenharmony_ci */ 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci /* Read CAN data length */ 46262306a36Sopenharmony_ci frame->len = (hex_to_bin(elm->rxbuf[datastart - 2]) << 0); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci /* Read CAN ID */ 46562306a36Sopenharmony_ci if (frame->can_id & CAN_EFF_FLAG) { 46662306a36Sopenharmony_ci frame->can_id |= (hex_to_bin(elm->rxbuf[0]) << 28) | 46762306a36Sopenharmony_ci (hex_to_bin(elm->rxbuf[1]) << 24) | 46862306a36Sopenharmony_ci (hex_to_bin(elm->rxbuf[3]) << 20) | 46962306a36Sopenharmony_ci (hex_to_bin(elm->rxbuf[4]) << 16) | 47062306a36Sopenharmony_ci (hex_to_bin(elm->rxbuf[6]) << 12) | 47162306a36Sopenharmony_ci (hex_to_bin(elm->rxbuf[7]) << 8) | 47262306a36Sopenharmony_ci (hex_to_bin(elm->rxbuf[9]) << 4) | 47362306a36Sopenharmony_ci (hex_to_bin(elm->rxbuf[10]) << 0); 47462306a36Sopenharmony_ci } else { 47562306a36Sopenharmony_ci frame->can_id |= (hex_to_bin(elm->rxbuf[0]) << 8) | 47662306a36Sopenharmony_ci (hex_to_bin(elm->rxbuf[1]) << 4) | 47762306a36Sopenharmony_ci (hex_to_bin(elm->rxbuf[2]) << 0); 47862306a36Sopenharmony_ci } 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci /* Check for RTR frame */ 48162306a36Sopenharmony_ci if (elm->rxfill >= hexlen + 3 && 48262306a36Sopenharmony_ci !memcmp(&elm->rxbuf[hexlen], "RTR", 3)) { 48362306a36Sopenharmony_ci frame->can_id |= CAN_RTR_FLAG; 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci /* Is the line long enough to hold the advertised payload? 48762306a36Sopenharmony_ci * Note: RTR frames have a DLC, but no actual payload. 48862306a36Sopenharmony_ci */ 48962306a36Sopenharmony_ci if (!(frame->can_id & CAN_RTR_FLAG) && 49062306a36Sopenharmony_ci (hexlen < frame->len * 3 + datastart)) { 49162306a36Sopenharmony_ci /* Incomplete frame. 49262306a36Sopenharmony_ci * Probably the ELM327's RS232 TX buffer was full. 49362306a36Sopenharmony_ci * Emit an error frame and exit. 49462306a36Sopenharmony_ci */ 49562306a36Sopenharmony_ci frame->can_id = CAN_ERR_FLAG | CAN_ERR_CRTL; 49662306a36Sopenharmony_ci frame->len = CAN_ERR_DLC; 49762306a36Sopenharmony_ci frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; 49862306a36Sopenharmony_ci can327_feed_frame_to_netdev(elm, skb); 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci /* Signal failure to parse. 50162306a36Sopenharmony_ci * The line will be re-parsed as an error line, which will fail. 50262306a36Sopenharmony_ci * However, this will correctly drop the state machine back into 50362306a36Sopenharmony_ci * command mode. 50462306a36Sopenharmony_ci */ 50562306a36Sopenharmony_ci return -ENODATA; 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci /* Parse the data nibbles. */ 50962306a36Sopenharmony_ci for (i = 0; i < frame->len; i++) { 51062306a36Sopenharmony_ci frame->data[i] = 51162306a36Sopenharmony_ci (hex_to_bin(elm->rxbuf[datastart + 3 * i]) << 4) | 51262306a36Sopenharmony_ci (hex_to_bin(elm->rxbuf[datastart + 3 * i + 1])); 51362306a36Sopenharmony_ci } 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci /* Feed the frame to the network layer. */ 51662306a36Sopenharmony_ci can327_feed_frame_to_netdev(elm, skb); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci return 0; 51962306a36Sopenharmony_ci} 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_cistatic void can327_parse_line(struct can327 *elm, size_t len) 52262306a36Sopenharmony_ci{ 52362306a36Sopenharmony_ci lockdep_assert_held(&elm->lock); 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci /* Skip empty lines */ 52662306a36Sopenharmony_ci if (!len) 52762306a36Sopenharmony_ci return; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci /* Skip echo lines */ 53062306a36Sopenharmony_ci if (elm->drop_next_line) { 53162306a36Sopenharmony_ci elm->drop_next_line = 0; 53262306a36Sopenharmony_ci return; 53362306a36Sopenharmony_ci } else if (!memcmp(elm->rxbuf, "AT", 2)) { 53462306a36Sopenharmony_ci return; 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci /* Regular parsing */ 53862306a36Sopenharmony_ci if (elm->state == CAN327_STATE_RECEIVING && 53962306a36Sopenharmony_ci can327_parse_frame(elm, len)) { 54062306a36Sopenharmony_ci /* Parse an error line. */ 54162306a36Sopenharmony_ci can327_parse_error(elm, len); 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci /* Start afresh. */ 54462306a36Sopenharmony_ci can327_kick_into_cmd_mode(elm); 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci} 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_cistatic void can327_handle_prompt(struct can327 *elm) 54962306a36Sopenharmony_ci{ 55062306a36Sopenharmony_ci struct can_frame *frame = &elm->can_frame_to_send; 55162306a36Sopenharmony_ci /* Size this buffer for the largest ELM327 line we may generate, 55262306a36Sopenharmony_ci * which is currently an 8 byte CAN frame's payload hexdump. 55362306a36Sopenharmony_ci * Items in can327_init_script must fit here, too! 55462306a36Sopenharmony_ci */ 55562306a36Sopenharmony_ci char local_txbuf[sizeof("0102030405060708\r")]; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci lockdep_assert_held(&elm->lock); 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci if (!elm->cmds_todo) { 56062306a36Sopenharmony_ci /* Enter CAN monitor mode */ 56162306a36Sopenharmony_ci can327_send(elm, "ATMA\r", 5); 56262306a36Sopenharmony_ci elm->state = CAN327_STATE_RECEIVING; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci /* We will be in the default state once this command is 56562306a36Sopenharmony_ci * sent, so enable the TX packet queue. 56662306a36Sopenharmony_ci */ 56762306a36Sopenharmony_ci netif_wake_queue(elm->dev); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci return; 57062306a36Sopenharmony_ci } 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci /* Reconfigure ELM327 step by step as indicated by elm->cmds_todo */ 57362306a36Sopenharmony_ci if (test_bit(CAN327_TX_DO_INIT, &elm->cmds_todo)) { 57462306a36Sopenharmony_ci snprintf(local_txbuf, sizeof(local_txbuf), "%s", 57562306a36Sopenharmony_ci *elm->next_init_cmd); 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci elm->next_init_cmd++; 57862306a36Sopenharmony_ci if (!(*elm->next_init_cmd)) { 57962306a36Sopenharmony_ci clear_bit(CAN327_TX_DO_INIT, &elm->cmds_todo); 58062306a36Sopenharmony_ci /* Init finished. */ 58162306a36Sopenharmony_ci } 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci } else if (test_and_clear_bit(CAN327_TX_DO_SILENT_MONITOR, &elm->cmds_todo)) { 58462306a36Sopenharmony_ci snprintf(local_txbuf, sizeof(local_txbuf), 58562306a36Sopenharmony_ci "ATCSM%i\r", 58662306a36Sopenharmony_ci !!(elm->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci } else if (test_and_clear_bit(CAN327_TX_DO_RESPONSES, &elm->cmds_todo)) { 58962306a36Sopenharmony_ci snprintf(local_txbuf, sizeof(local_txbuf), 59062306a36Sopenharmony_ci "ATR%i\r", 59162306a36Sopenharmony_ci !(elm->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci } else if (test_and_clear_bit(CAN327_TX_DO_CAN_CONFIG, &elm->cmds_todo)) { 59462306a36Sopenharmony_ci snprintf(local_txbuf, sizeof(local_txbuf), 59562306a36Sopenharmony_ci "ATPC\r"); 59662306a36Sopenharmony_ci set_bit(CAN327_TX_DO_CAN_CONFIG_PART2, &elm->cmds_todo); 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci } else if (test_and_clear_bit(CAN327_TX_DO_CAN_CONFIG_PART2, &elm->cmds_todo)) { 59962306a36Sopenharmony_ci snprintf(local_txbuf, sizeof(local_txbuf), 60062306a36Sopenharmony_ci "ATPB%04X\r", 60162306a36Sopenharmony_ci elm->can_config); 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci } else if (test_and_clear_bit(CAN327_TX_DO_CANID_29BIT_HIGH, &elm->cmds_todo)) { 60462306a36Sopenharmony_ci snprintf(local_txbuf, sizeof(local_txbuf), 60562306a36Sopenharmony_ci "ATCP%02X\r", 60662306a36Sopenharmony_ci (frame->can_id & CAN_EFF_MASK) >> 24); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci } else if (test_and_clear_bit(CAN327_TX_DO_CANID_29BIT_LOW, &elm->cmds_todo)) { 60962306a36Sopenharmony_ci snprintf(local_txbuf, sizeof(local_txbuf), 61062306a36Sopenharmony_ci "ATSH%06X\r", 61162306a36Sopenharmony_ci frame->can_id & CAN_EFF_MASK & ((1 << 24) - 1)); 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci } else if (test_and_clear_bit(CAN327_TX_DO_CANID_11BIT, &elm->cmds_todo)) { 61462306a36Sopenharmony_ci snprintf(local_txbuf, sizeof(local_txbuf), 61562306a36Sopenharmony_ci "ATSH%03X\r", 61662306a36Sopenharmony_ci frame->can_id & CAN_SFF_MASK); 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci } else if (test_and_clear_bit(CAN327_TX_DO_CAN_DATA, &elm->cmds_todo)) { 61962306a36Sopenharmony_ci if (frame->can_id & CAN_RTR_FLAG) { 62062306a36Sopenharmony_ci /* Send an RTR frame. Their DLC is fixed. 62162306a36Sopenharmony_ci * Some chips don't send them at all. 62262306a36Sopenharmony_ci */ 62362306a36Sopenharmony_ci snprintf(local_txbuf, sizeof(local_txbuf), "ATRTR\r"); 62462306a36Sopenharmony_ci } else { 62562306a36Sopenharmony_ci /* Send a regular CAN data frame */ 62662306a36Sopenharmony_ci int i; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci for (i = 0; i < frame->len; i++) { 62962306a36Sopenharmony_ci snprintf(&local_txbuf[2 * i], 63062306a36Sopenharmony_ci sizeof(local_txbuf), "%02X", 63162306a36Sopenharmony_ci frame->data[i]); 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci snprintf(&local_txbuf[2 * i], sizeof(local_txbuf), 63562306a36Sopenharmony_ci "\r"); 63662306a36Sopenharmony_ci } 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci elm->drop_next_line = 1; 63962306a36Sopenharmony_ci elm->state = CAN327_STATE_RECEIVING; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci /* We will be in the default state once this command is 64262306a36Sopenharmony_ci * sent, so enable the TX packet queue. 64362306a36Sopenharmony_ci */ 64462306a36Sopenharmony_ci netif_wake_queue(elm->dev); 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci can327_send(elm, local_txbuf, strlen(local_txbuf)); 64862306a36Sopenharmony_ci} 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_cistatic bool can327_is_ready_char(char c) 65162306a36Sopenharmony_ci{ 65262306a36Sopenharmony_ci /* Bits 0xc0 are sometimes set (randomly), hence the mask. 65362306a36Sopenharmony_ci * Probably bad hardware. 65462306a36Sopenharmony_ci */ 65562306a36Sopenharmony_ci return (c & 0x3f) == CAN327_READY_CHAR; 65662306a36Sopenharmony_ci} 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_cistatic void can327_drop_bytes(struct can327 *elm, size_t i) 65962306a36Sopenharmony_ci{ 66062306a36Sopenharmony_ci lockdep_assert_held(&elm->lock); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci memmove(&elm->rxbuf[0], &elm->rxbuf[i], CAN327_SIZE_RXBUF - i); 66362306a36Sopenharmony_ci elm->rxfill -= i; 66462306a36Sopenharmony_ci} 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_cistatic void can327_parse_rxbuf(struct can327 *elm, size_t first_new_char_idx) 66762306a36Sopenharmony_ci{ 66862306a36Sopenharmony_ci size_t len, pos; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci lockdep_assert_held(&elm->lock); 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci switch (elm->state) { 67362306a36Sopenharmony_ci case CAN327_STATE_NOTINIT: 67462306a36Sopenharmony_ci elm->rxfill = 0; 67562306a36Sopenharmony_ci break; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci case CAN327_STATE_GETDUMMYCHAR: 67862306a36Sopenharmony_ci /* Wait for 'y' or '>' */ 67962306a36Sopenharmony_ci for (pos = 0; pos < elm->rxfill; pos++) { 68062306a36Sopenharmony_ci if (elm->rxbuf[pos] == CAN327_DUMMY_CHAR) { 68162306a36Sopenharmony_ci can327_send(elm, "\r", 1); 68262306a36Sopenharmony_ci elm->state = CAN327_STATE_GETPROMPT; 68362306a36Sopenharmony_ci pos++; 68462306a36Sopenharmony_ci break; 68562306a36Sopenharmony_ci } else if (can327_is_ready_char(elm->rxbuf[pos])) { 68662306a36Sopenharmony_ci can327_send(elm, CAN327_DUMMY_STRING, 1); 68762306a36Sopenharmony_ci pos++; 68862306a36Sopenharmony_ci break; 68962306a36Sopenharmony_ci } 69062306a36Sopenharmony_ci } 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci can327_drop_bytes(elm, pos); 69362306a36Sopenharmony_ci break; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci case CAN327_STATE_GETPROMPT: 69662306a36Sopenharmony_ci /* Wait for '>' */ 69762306a36Sopenharmony_ci if (can327_is_ready_char(elm->rxbuf[elm->rxfill - 1])) 69862306a36Sopenharmony_ci can327_handle_prompt(elm); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci elm->rxfill = 0; 70162306a36Sopenharmony_ci break; 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci case CAN327_STATE_RECEIVING: 70462306a36Sopenharmony_ci /* Find <CR> delimiting feedback lines. */ 70562306a36Sopenharmony_ci len = first_new_char_idx; 70662306a36Sopenharmony_ci while (len < elm->rxfill && elm->rxbuf[len] != '\r') 70762306a36Sopenharmony_ci len++; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci if (len == CAN327_SIZE_RXBUF) { 71062306a36Sopenharmony_ci /* Assume the buffer ran full with garbage. 71162306a36Sopenharmony_ci * Did we even connect at the right baud rate? 71262306a36Sopenharmony_ci */ 71362306a36Sopenharmony_ci netdev_err(elm->dev, 71462306a36Sopenharmony_ci "RX buffer overflow. Faulty ELM327 or UART?\n"); 71562306a36Sopenharmony_ci can327_uart_side_failure(elm); 71662306a36Sopenharmony_ci } else if (len == elm->rxfill) { 71762306a36Sopenharmony_ci if (can327_is_ready_char(elm->rxbuf[elm->rxfill - 1])) { 71862306a36Sopenharmony_ci /* The ELM327's AT ST response timeout ran out, 71962306a36Sopenharmony_ci * so we got a prompt. 72062306a36Sopenharmony_ci * Clear RX buffer and restart listening. 72162306a36Sopenharmony_ci */ 72262306a36Sopenharmony_ci elm->rxfill = 0; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci can327_handle_prompt(elm); 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci /* No <CR> found - we haven't received a full line yet. 72862306a36Sopenharmony_ci * Wait for more data. 72962306a36Sopenharmony_ci */ 73062306a36Sopenharmony_ci } else { 73162306a36Sopenharmony_ci /* We have a full line to parse. */ 73262306a36Sopenharmony_ci can327_parse_line(elm, len); 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci /* Remove parsed data from RX buffer. */ 73562306a36Sopenharmony_ci can327_drop_bytes(elm, len + 1); 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci /* More data to parse? */ 73862306a36Sopenharmony_ci if (elm->rxfill) 73962306a36Sopenharmony_ci can327_parse_rxbuf(elm, 0); 74062306a36Sopenharmony_ci } 74162306a36Sopenharmony_ci } 74262306a36Sopenharmony_ci} 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_cistatic int can327_netdev_open(struct net_device *dev) 74562306a36Sopenharmony_ci{ 74662306a36Sopenharmony_ci struct can327 *elm = netdev_priv(dev); 74762306a36Sopenharmony_ci int err; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci spin_lock_bh(&elm->lock); 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci if (!elm->tty) { 75262306a36Sopenharmony_ci spin_unlock_bh(&elm->lock); 75362306a36Sopenharmony_ci return -ENODEV; 75462306a36Sopenharmony_ci } 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci if (elm->uart_side_failure) 75762306a36Sopenharmony_ci netdev_warn(elm->dev, 75862306a36Sopenharmony_ci "Reopening netdev after a UART side fault has been detected.\n"); 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci /* Clear TTY buffers */ 76162306a36Sopenharmony_ci elm->rxfill = 0; 76262306a36Sopenharmony_ci elm->txleft = 0; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci /* open_candev() checks for elm->can.bittiming.bitrate != 0 */ 76562306a36Sopenharmony_ci err = open_candev(dev); 76662306a36Sopenharmony_ci if (err) { 76762306a36Sopenharmony_ci spin_unlock_bh(&elm->lock); 76862306a36Sopenharmony_ci return err; 76962306a36Sopenharmony_ci } 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci can327_init_device(elm); 77262306a36Sopenharmony_ci spin_unlock_bh(&elm->lock); 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci err = can_rx_offload_add_manual(dev, &elm->offload, CAN327_NAPI_WEIGHT); 77562306a36Sopenharmony_ci if (err) { 77662306a36Sopenharmony_ci close_candev(dev); 77762306a36Sopenharmony_ci return err; 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci can_rx_offload_enable(&elm->offload); 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci elm->can.state = CAN_STATE_ERROR_ACTIVE; 78362306a36Sopenharmony_ci netif_start_queue(dev); 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci return 0; 78662306a36Sopenharmony_ci} 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_cistatic int can327_netdev_close(struct net_device *dev) 78962306a36Sopenharmony_ci{ 79062306a36Sopenharmony_ci struct can327 *elm = netdev_priv(dev); 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci /* Interrupt whatever the ELM327 is doing right now */ 79362306a36Sopenharmony_ci spin_lock_bh(&elm->lock); 79462306a36Sopenharmony_ci can327_send(elm, CAN327_DUMMY_STRING, 1); 79562306a36Sopenharmony_ci spin_unlock_bh(&elm->lock); 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci netif_stop_queue(dev); 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci /* We don't flush the UART TX queue here, as we want final stop 80062306a36Sopenharmony_ci * commands (like the above dummy char) to be flushed out. 80162306a36Sopenharmony_ci */ 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci can_rx_offload_disable(&elm->offload); 80462306a36Sopenharmony_ci elm->can.state = CAN_STATE_STOPPED; 80562306a36Sopenharmony_ci can_rx_offload_del(&elm->offload); 80662306a36Sopenharmony_ci close_candev(dev); 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci return 0; 80962306a36Sopenharmony_ci} 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci/* Send a can_frame to a TTY. */ 81262306a36Sopenharmony_cistatic netdev_tx_t can327_netdev_start_xmit(struct sk_buff *skb, 81362306a36Sopenharmony_ci struct net_device *dev) 81462306a36Sopenharmony_ci{ 81562306a36Sopenharmony_ci struct can327 *elm = netdev_priv(dev); 81662306a36Sopenharmony_ci struct can_frame *frame = (struct can_frame *)skb->data; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci if (can_dev_dropped_skb(dev, skb)) 81962306a36Sopenharmony_ci return NETDEV_TX_OK; 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci /* We shouldn't get here after a hardware fault: 82262306a36Sopenharmony_ci * can_bus_off() calls netif_carrier_off() 82362306a36Sopenharmony_ci */ 82462306a36Sopenharmony_ci if (elm->uart_side_failure) { 82562306a36Sopenharmony_ci WARN_ON_ONCE(elm->uart_side_failure); 82662306a36Sopenharmony_ci goto out; 82762306a36Sopenharmony_ci } 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci netif_stop_queue(dev); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci /* BHs are already disabled, so no spin_lock_bh(). 83262306a36Sopenharmony_ci * See Documentation/networking/netdevices.rst 83362306a36Sopenharmony_ci */ 83462306a36Sopenharmony_ci spin_lock(&elm->lock); 83562306a36Sopenharmony_ci can327_send_frame(elm, frame); 83662306a36Sopenharmony_ci spin_unlock(&elm->lock); 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci dev->stats.tx_packets++; 83962306a36Sopenharmony_ci dev->stats.tx_bytes += frame->can_id & CAN_RTR_FLAG ? 0 : frame->len; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci skb_tx_timestamp(skb); 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ciout: 84462306a36Sopenharmony_ci kfree_skb(skb); 84562306a36Sopenharmony_ci return NETDEV_TX_OK; 84662306a36Sopenharmony_ci} 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_cistatic const struct net_device_ops can327_netdev_ops = { 84962306a36Sopenharmony_ci .ndo_open = can327_netdev_open, 85062306a36Sopenharmony_ci .ndo_stop = can327_netdev_close, 85162306a36Sopenharmony_ci .ndo_start_xmit = can327_netdev_start_xmit, 85262306a36Sopenharmony_ci .ndo_change_mtu = can_change_mtu, 85362306a36Sopenharmony_ci}; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_cistatic const struct ethtool_ops can327_ethtool_ops = { 85662306a36Sopenharmony_ci .get_ts_info = ethtool_op_get_ts_info, 85762306a36Sopenharmony_ci}; 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_cistatic bool can327_is_valid_rx_char(u8 c) 86062306a36Sopenharmony_ci{ 86162306a36Sopenharmony_ci static const bool lut_char_is_valid['z'] = { 86262306a36Sopenharmony_ci ['\r'] = true, 86362306a36Sopenharmony_ci [' '] = true, 86462306a36Sopenharmony_ci ['.'] = true, 86562306a36Sopenharmony_ci ['0'] = true, true, true, true, true, 86662306a36Sopenharmony_ci ['5'] = true, true, true, true, true, 86762306a36Sopenharmony_ci ['<'] = true, 86862306a36Sopenharmony_ci [CAN327_READY_CHAR] = true, 86962306a36Sopenharmony_ci ['?'] = true, 87062306a36Sopenharmony_ci ['A'] = true, true, true, true, true, true, true, 87162306a36Sopenharmony_ci ['H'] = true, true, true, true, true, true, true, 87262306a36Sopenharmony_ci ['O'] = true, true, true, true, true, true, true, 87362306a36Sopenharmony_ci ['V'] = true, true, true, true, true, 87462306a36Sopenharmony_ci ['a'] = true, 87562306a36Sopenharmony_ci ['b'] = true, 87662306a36Sopenharmony_ci ['v'] = true, 87762306a36Sopenharmony_ci [CAN327_DUMMY_CHAR] = true, 87862306a36Sopenharmony_ci }; 87962306a36Sopenharmony_ci BUILD_BUG_ON(CAN327_DUMMY_CHAR >= 'z'); 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci return (c < ARRAY_SIZE(lut_char_is_valid) && lut_char_is_valid[c]); 88262306a36Sopenharmony_ci} 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci/* Handle incoming ELM327 ASCII data. 88562306a36Sopenharmony_ci * This will not be re-entered while running, but other ldisc 88662306a36Sopenharmony_ci * functions may be called in parallel. 88762306a36Sopenharmony_ci */ 88862306a36Sopenharmony_cistatic void can327_ldisc_rx(struct tty_struct *tty, const u8 *cp, 88962306a36Sopenharmony_ci const u8 *fp, size_t count) 89062306a36Sopenharmony_ci{ 89162306a36Sopenharmony_ci struct can327 *elm = tty->disc_data; 89262306a36Sopenharmony_ci size_t first_new_char_idx; 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci if (elm->uart_side_failure) 89562306a36Sopenharmony_ci return; 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci spin_lock_bh(&elm->lock); 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci /* Store old rxfill, so can327_parse_rxbuf() will have 90062306a36Sopenharmony_ci * the option of skipping already checked characters. 90162306a36Sopenharmony_ci */ 90262306a36Sopenharmony_ci first_new_char_idx = elm->rxfill; 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci while (count--) { 90562306a36Sopenharmony_ci if (elm->rxfill >= CAN327_SIZE_RXBUF) { 90662306a36Sopenharmony_ci netdev_err(elm->dev, 90762306a36Sopenharmony_ci "Receive buffer overflowed. Bad chip or wiring? count = %zu", 90862306a36Sopenharmony_ci count); 90962306a36Sopenharmony_ci goto uart_failure; 91062306a36Sopenharmony_ci } 91162306a36Sopenharmony_ci if (fp && *fp++) { 91262306a36Sopenharmony_ci netdev_err(elm->dev, 91362306a36Sopenharmony_ci "Error in received character stream. Check your wiring."); 91462306a36Sopenharmony_ci goto uart_failure; 91562306a36Sopenharmony_ci } 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci /* Ignore NUL characters, which the PIC microcontroller may 91862306a36Sopenharmony_ci * inadvertently insert due to a known hardware bug. 91962306a36Sopenharmony_ci * See ELM327 documentation, which refers to a Microchip PIC 92062306a36Sopenharmony_ci * bug description. 92162306a36Sopenharmony_ci */ 92262306a36Sopenharmony_ci if (*cp) { 92362306a36Sopenharmony_ci /* Check for stray characters on the UART line. 92462306a36Sopenharmony_ci * Likely caused by bad hardware. 92562306a36Sopenharmony_ci */ 92662306a36Sopenharmony_ci if (!can327_is_valid_rx_char(*cp)) { 92762306a36Sopenharmony_ci netdev_err(elm->dev, 92862306a36Sopenharmony_ci "Received illegal character %02x.\n", 92962306a36Sopenharmony_ci *cp); 93062306a36Sopenharmony_ci goto uart_failure; 93162306a36Sopenharmony_ci } 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci elm->rxbuf[elm->rxfill++] = *cp; 93462306a36Sopenharmony_ci } 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci cp++; 93762306a36Sopenharmony_ci } 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci can327_parse_rxbuf(elm, first_new_char_idx); 94062306a36Sopenharmony_ci spin_unlock_bh(&elm->lock); 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci return; 94362306a36Sopenharmony_ciuart_failure: 94462306a36Sopenharmony_ci can327_uart_side_failure(elm); 94562306a36Sopenharmony_ci spin_unlock_bh(&elm->lock); 94662306a36Sopenharmony_ci} 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci/* Write out remaining transmit buffer. 94962306a36Sopenharmony_ci * Scheduled when TTY is writable. 95062306a36Sopenharmony_ci */ 95162306a36Sopenharmony_cistatic void can327_ldisc_tx_worker(struct work_struct *work) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci struct can327 *elm = container_of(work, struct can327, tx_work); 95462306a36Sopenharmony_ci ssize_t written; 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci if (elm->uart_side_failure) 95762306a36Sopenharmony_ci return; 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci spin_lock_bh(&elm->lock); 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci if (elm->txleft) { 96262306a36Sopenharmony_ci written = elm->tty->ops->write(elm->tty, elm->txhead, 96362306a36Sopenharmony_ci elm->txleft); 96462306a36Sopenharmony_ci if (written < 0) { 96562306a36Sopenharmony_ci netdev_err(elm->dev, "Failed to write to tty %s.\n", 96662306a36Sopenharmony_ci elm->tty->name); 96762306a36Sopenharmony_ci can327_uart_side_failure(elm); 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci spin_unlock_bh(&elm->lock); 97062306a36Sopenharmony_ci return; 97162306a36Sopenharmony_ci } 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci elm->txleft -= written; 97462306a36Sopenharmony_ci elm->txhead += written; 97562306a36Sopenharmony_ci } 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci if (!elm->txleft) 97862306a36Sopenharmony_ci clear_bit(TTY_DO_WRITE_WAKEUP, &elm->tty->flags); 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci spin_unlock_bh(&elm->lock); 98162306a36Sopenharmony_ci} 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci/* Called by the driver when there's room for more data. */ 98462306a36Sopenharmony_cistatic void can327_ldisc_tx_wakeup(struct tty_struct *tty) 98562306a36Sopenharmony_ci{ 98662306a36Sopenharmony_ci struct can327 *elm = tty->disc_data; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci schedule_work(&elm->tx_work); 98962306a36Sopenharmony_ci} 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci/* ELM327 can only handle bitrates that are integer divisors of 500 kHz, 99262306a36Sopenharmony_ci * or 7/8 of that. Divisors are 1 to 64. 99362306a36Sopenharmony_ci * Currently we don't implement support for 7/8 rates. 99462306a36Sopenharmony_ci */ 99562306a36Sopenharmony_cistatic const u32 can327_bitrate_const[] = { 99662306a36Sopenharmony_ci 7812, 7936, 8064, 8196, 8333, 8474, 8620, 8771, 99762306a36Sopenharmony_ci 8928, 9090, 9259, 9433, 9615, 9803, 10000, 10204, 99862306a36Sopenharmony_ci 10416, 10638, 10869, 11111, 11363, 11627, 11904, 12195, 99962306a36Sopenharmony_ci 12500, 12820, 13157, 13513, 13888, 14285, 14705, 15151, 100062306a36Sopenharmony_ci 15625, 16129, 16666, 17241, 17857, 18518, 19230, 20000, 100162306a36Sopenharmony_ci 20833, 21739, 22727, 23809, 25000, 26315, 27777, 29411, 100262306a36Sopenharmony_ci 31250, 33333, 35714, 38461, 41666, 45454, 50000, 55555, 100362306a36Sopenharmony_ci 62500, 71428, 83333, 100000, 125000, 166666, 250000, 500000 100462306a36Sopenharmony_ci}; 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_cistatic int can327_ldisc_open(struct tty_struct *tty) 100762306a36Sopenharmony_ci{ 100862306a36Sopenharmony_ci struct net_device *dev; 100962306a36Sopenharmony_ci struct can327 *elm; 101062306a36Sopenharmony_ci int err; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci if (!capable(CAP_NET_ADMIN)) 101362306a36Sopenharmony_ci return -EPERM; 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci if (!tty->ops->write) 101662306a36Sopenharmony_ci return -EOPNOTSUPP; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci dev = alloc_candev(sizeof(struct can327), 0); 101962306a36Sopenharmony_ci if (!dev) 102062306a36Sopenharmony_ci return -ENFILE; 102162306a36Sopenharmony_ci elm = netdev_priv(dev); 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci /* Configure TTY interface */ 102462306a36Sopenharmony_ci tty->receive_room = 65536; /* We don't flow control */ 102562306a36Sopenharmony_ci spin_lock_init(&elm->lock); 102662306a36Sopenharmony_ci INIT_WORK(&elm->tx_work, can327_ldisc_tx_worker); 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci /* Configure CAN metadata */ 102962306a36Sopenharmony_ci elm->can.bitrate_const = can327_bitrate_const; 103062306a36Sopenharmony_ci elm->can.bitrate_const_cnt = ARRAY_SIZE(can327_bitrate_const); 103162306a36Sopenharmony_ci elm->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY; 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci /* Configure netdev interface */ 103462306a36Sopenharmony_ci elm->dev = dev; 103562306a36Sopenharmony_ci dev->netdev_ops = &can327_netdev_ops; 103662306a36Sopenharmony_ci dev->ethtool_ops = &can327_ethtool_ops; 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci /* Mark ldisc channel as alive */ 103962306a36Sopenharmony_ci elm->tty = tty; 104062306a36Sopenharmony_ci tty->disc_data = elm; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci /* Let 'er rip */ 104362306a36Sopenharmony_ci err = register_candev(elm->dev); 104462306a36Sopenharmony_ci if (err) { 104562306a36Sopenharmony_ci free_candev(elm->dev); 104662306a36Sopenharmony_ci return err; 104762306a36Sopenharmony_ci } 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci netdev_info(elm->dev, "can327 on %s.\n", tty->name); 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci return 0; 105262306a36Sopenharmony_ci} 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci/* Close down a can327 channel. 105562306a36Sopenharmony_ci * This means flushing out any pending queues, and then returning. 105662306a36Sopenharmony_ci * This call is serialized against other ldisc functions: 105762306a36Sopenharmony_ci * Once this is called, no other ldisc function of ours is entered. 105862306a36Sopenharmony_ci * 105962306a36Sopenharmony_ci * We also use this function for a hangup event. 106062306a36Sopenharmony_ci */ 106162306a36Sopenharmony_cistatic void can327_ldisc_close(struct tty_struct *tty) 106262306a36Sopenharmony_ci{ 106362306a36Sopenharmony_ci struct can327 *elm = tty->disc_data; 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci /* unregister_netdev() calls .ndo_stop() so we don't have to. */ 106662306a36Sopenharmony_ci unregister_candev(elm->dev); 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci /* Give UART one final chance to flush. 106962306a36Sopenharmony_ci * No need to clear TTY_DO_WRITE_WAKEUP since .write_wakeup() is 107062306a36Sopenharmony_ci * serialised against .close() and will not be called once we return. 107162306a36Sopenharmony_ci */ 107262306a36Sopenharmony_ci flush_work(&elm->tx_work); 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci /* Mark channel as dead */ 107562306a36Sopenharmony_ci spin_lock_bh(&elm->lock); 107662306a36Sopenharmony_ci tty->disc_data = NULL; 107762306a36Sopenharmony_ci elm->tty = NULL; 107862306a36Sopenharmony_ci spin_unlock_bh(&elm->lock); 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci netdev_info(elm->dev, "can327 off %s.\n", tty->name); 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci free_candev(elm->dev); 108362306a36Sopenharmony_ci} 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_cistatic int can327_ldisc_ioctl(struct tty_struct *tty, unsigned int cmd, 108662306a36Sopenharmony_ci unsigned long arg) 108762306a36Sopenharmony_ci{ 108862306a36Sopenharmony_ci struct can327 *elm = tty->disc_data; 108962306a36Sopenharmony_ci unsigned int tmp; 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci switch (cmd) { 109262306a36Sopenharmony_ci case SIOCGIFNAME: 109362306a36Sopenharmony_ci tmp = strnlen(elm->dev->name, IFNAMSIZ - 1) + 1; 109462306a36Sopenharmony_ci if (copy_to_user((void __user *)arg, elm->dev->name, tmp)) 109562306a36Sopenharmony_ci return -EFAULT; 109662306a36Sopenharmony_ci return 0; 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci case SIOCSIFHWADDR: 109962306a36Sopenharmony_ci return -EINVAL; 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci default: 110262306a36Sopenharmony_ci return tty_mode_ioctl(tty, cmd, arg); 110362306a36Sopenharmony_ci } 110462306a36Sopenharmony_ci} 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_cistatic struct tty_ldisc_ops can327_ldisc = { 110762306a36Sopenharmony_ci .owner = THIS_MODULE, 110862306a36Sopenharmony_ci .name = KBUILD_MODNAME, 110962306a36Sopenharmony_ci .num = N_CAN327, 111062306a36Sopenharmony_ci .receive_buf = can327_ldisc_rx, 111162306a36Sopenharmony_ci .write_wakeup = can327_ldisc_tx_wakeup, 111262306a36Sopenharmony_ci .open = can327_ldisc_open, 111362306a36Sopenharmony_ci .close = can327_ldisc_close, 111462306a36Sopenharmony_ci .ioctl = can327_ldisc_ioctl, 111562306a36Sopenharmony_ci}; 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_cistatic int __init can327_init(void) 111862306a36Sopenharmony_ci{ 111962306a36Sopenharmony_ci int status; 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci status = tty_register_ldisc(&can327_ldisc); 112262306a36Sopenharmony_ci if (status) 112362306a36Sopenharmony_ci pr_err("Can't register line discipline\n"); 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci return status; 112662306a36Sopenharmony_ci} 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_cistatic void __exit can327_exit(void) 112962306a36Sopenharmony_ci{ 113062306a36Sopenharmony_ci /* This will only be called when all channels have been closed by 113162306a36Sopenharmony_ci * userspace - tty_ldisc.c takes care of the module's refcount. 113262306a36Sopenharmony_ci */ 113362306a36Sopenharmony_ci tty_unregister_ldisc(&can327_ldisc); 113462306a36Sopenharmony_ci} 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_cimodule_init(can327_init); 113762306a36Sopenharmony_cimodule_exit(can327_exit); 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ciMODULE_ALIAS_LDISC(N_CAN327); 114062306a36Sopenharmony_ciMODULE_DESCRIPTION("ELM327 based CAN interface"); 114162306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 114262306a36Sopenharmony_ciMODULE_AUTHOR("Max Staudt <max@enpas.org>"); 1143