#include <linux/init.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/atomic.h>
#include <linux/bitops.h>
#include <linux/ctype.h>
-#include <linux/delay.h>
#include <linux/errno.h>
-#include <linux/if_ether.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/lockdep.h>
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
-#include <linux/can/led.h>
#include <linux/can/rx-offload.h>
/* Line discipline ID number.
#define len can_dlc
#endif
-#define ELM327_NAPI_WEIGHT 4
+#define CAN327_NAPI_WEIGHT 4
-#define ELM327_SIZE_RXBUF 224
-#define ELM327_SIZE_TXBUF 32
+#define CAN327_SIZE_TXBUF 32
+#define CAN327_SIZE_RXBUF 1024
-#define ELM327_CAN_CONFIG_SEND_SFF 0x8000
-#define ELM327_CAN_CONFIG_VARIABLE_DLC 0x4000
-#define ELM327_CAN_CONFIG_RECV_BOTH_SFF_EFF 0x2000
-#define ELM327_CAN_CONFIG_BAUDRATE_MULT_8_7 0x1000
+#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 ELM327_DUMMY_CHAR 'y'
-#define ELM327_DUMMY_STRING "y"
-#define ELM327_READY_CHAR '>'
+#define CAN327_DUMMY_CHAR 'y'
+#define CAN327_DUMMY_STRING "y"
+#define CAN327_READY_CHAR '>'
/* Bits in elm->cmds_todo */
-enum elm327_tx_do {
- ELM327_TX_DO_CAN_DATA = 0,
- ELM327_TX_DO_CANID_11BIT,
- ELM327_TX_DO_CANID_29BIT_LOW,
- ELM327_TX_DO_CANID_29BIT_HIGH,
- ELM327_TX_DO_CAN_CONFIG_PART2,
- ELM327_TX_DO_CAN_CONFIG,
- ELM327_TX_DO_RESPONSES,
- ELM327_TX_DO_SILENT_MONITOR,
- ELM327_TX_DO_INIT
+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 {
struct can_rx_offload offload;
/* TTY buffers */
- u8 rxbuf[ELM327_SIZE_RXBUF];
- u8 txbuf[ELM327_SIZE_TXBUF];
+ u8 txbuf[CAN327_SIZE_TXBUF];
+ u8 rxbuf[CAN327_SIZE_RXBUF];
/* Per-channel lock */
spinlock_t lock;
/* State machine */
enum {
- ELM327_STATE_NOTINIT = 0,
- ELM327_STATE_GETDUMMYCHAR,
- ELM327_STATE_GETPROMPT,
- ELM327_STATE_RECEIVING,
+ CAN327_STATE_NOTINIT = 0,
+ CAN327_STATE_GETDUMMYCHAR,
+ CAN327_STATE_GETPROMPT,
+ CAN327_STATE_RECEIVING,
} state;
/* Things we have yet to send */
bool uart_side_failure;
};
-static inline void elm327_uart_side_failure(struct can327 *elm);
+static inline void can327_uart_side_failure(struct can327 *elm);
-static void elm327_send(struct can327 *elm, const void *buf, size_t len)
+static void can327_send(struct can327 *elm, const void *buf, size_t len)
{
int written;
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",
+ netdev_err(elm->dev, "Failed to write to tty %s.\n",
elm->tty->name);
- elm327_uart_side_failure(elm);
+ can327_uart_side_failure(elm);
return;
}
}
/* Take the ELM327 out of almost any state and back into command mode.
- * We send ELM327_DUMMY_CHAR which will either abort any running
+ * 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 elm327_kick_into_cmd_mode(struct can327 *elm)
+static void can327_kick_into_cmd_mode(struct can327 *elm)
{
lockdep_assert_held(&elm->lock);
- if (elm->state != ELM327_STATE_GETDUMMYCHAR &&
- elm->state != ELM327_STATE_GETPROMPT) {
- elm327_send(elm, ELM327_DUMMY_STRING, 1);
+ if (elm->state != CAN327_STATE_GETDUMMYCHAR &&
+ elm->state != CAN327_STATE_GETPROMPT) {
+ can327_send(elm, CAN327_DUMMY_STRING, 1);
- elm->state = ELM327_STATE_GETDUMMYCHAR;
+ elm->state = CAN327_STATE_GETDUMMYCHAR;
}
}
/* Schedule a CAN frame and necessary config changes to be sent to the TTY. */
-static void elm327_send_frame(struct can327 *elm, struct can_frame *frame)
+static void can327_send_frame(struct can327 *elm, struct can_frame *frame)
{
lockdep_assert_held(&elm->lock);
/* 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
- : ELM327_CAN_CONFIG_SEND_SFF)
- | ELM327_CAN_CONFIG_VARIABLE_DLC
- | ELM327_CAN_CONFIG_RECV_BOTH_SFF_EFF
- | elm->can_bitrate_divisor;
-
- set_bit(ELM327_TX_DO_CAN_CONFIG, &elm->cmds_todo);
+ 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(CAN327_TX_DO_CAN_CONFIG, &elm->cmds_todo);
}
if (frame->can_id & CAN_EFF_FLAG) {
- clear_bit(ELM327_TX_DO_CANID_11BIT, &elm->cmds_todo);
- set_bit(ELM327_TX_DO_CANID_29BIT_LOW, &elm->cmds_todo);
- set_bit(ELM327_TX_DO_CANID_29BIT_HIGH, &elm->cmds_todo);
+ clear_bit(CAN327_TX_DO_CANID_11BIT, &elm->cmds_todo);
+ set_bit(CAN327_TX_DO_CANID_29BIT_LOW, &elm->cmds_todo);
+ set_bit(CAN327_TX_DO_CANID_29BIT_HIGH, &elm->cmds_todo);
} else {
- set_bit(ELM327_TX_DO_CANID_11BIT, &elm->cmds_todo);
- clear_bit(ELM327_TX_DO_CANID_29BIT_LOW, &elm->cmds_todo);
- clear_bit(ELM327_TX_DO_CANID_29BIT_HIGH, &elm->cmds_todo);
+ set_bit(CAN327_TX_DO_CANID_11BIT, &elm->cmds_todo);
+ clear_bit(CAN327_TX_DO_CANID_29BIT_LOW,
+ &elm->cmds_todo);
+ clear_bit(CAN327_TX_DO_CANID_29BIT_HIGH,
+ &elm->cmds_todo);
}
}
/* Schedule the CAN frame itself. */
elm->can_frame_to_send = *frame;
- set_bit(ELM327_TX_DO_CAN_DATA, &elm->cmds_todo);
+ set_bit(CAN327_TX_DO_CAN_DATA, &elm->cmds_todo);
- elm327_kick_into_cmd_mode(elm);
+ can327_kick_into_cmd_mode(elm);
}
/* ELM327 initialisation sequence.
- * The line length is limited by the buffer in elm327_handle_prompt().
+ * The line length is limited by the buffer in can327_handle_prompt().
*/
-static char *elm327_init_script[] = {
+static char *can327_init_script[] = {
"AT WS\r", /* v1.0: Warm Start */
"AT PP FF OFF\r", /* v1.0: All Programmable Parameters Off */
"AT M0\r", /* v1.0: Memory Off */
NULL
};
-static void elm327_init(struct can327 *elm)
+static void can327_init_device(struct can327 *elm)
{
lockdep_assert_held(&elm->lock);
- elm->state = ELM327_STATE_NOTINIT;
+ elm->state = CAN327_STATE_NOTINIT;
elm->can_frame_to_send.can_id = 0x7df; /* ELM327 HW default */
elm->rxfill = 0;
elm->drop_next_line = 0;
/* We can only set the bitrate as a fraction of 500000.
- * The bit timing constants in can327_bittiming_const will
+ * The bitrates listed in can327_bitrate_const will
* limit the user to the right values.
*/
elm->can_bitrate_divisor = 500000 / elm->can.bittiming.bitrate;
- elm->can_config = ELM327_CAN_CONFIG_SEND_SFF
- | ELM327_CAN_CONFIG_VARIABLE_DLC
- | ELM327_CAN_CONFIG_RECV_BOTH_SFF_EFF
- | elm->can_bitrate_divisor;
+ elm->can_config =
+ CAN327_CAN_CONFIG_SEND_SFF | CAN327_CAN_CONFIG_VARIABLE_DLC |
+ CAN327_CAN_CONFIG_RECV_BOTH_SFF_EFF | elm->can_bitrate_divisor;
/* Configure ELM327 and then start monitoring */
- elm->next_init_cmd = &elm327_init_script[0];
- set_bit(ELM327_TX_DO_INIT, &elm->cmds_todo);
- set_bit(ELM327_TX_DO_SILENT_MONITOR, &elm->cmds_todo);
- set_bit(ELM327_TX_DO_RESPONSES, &elm->cmds_todo);
- set_bit(ELM327_TX_DO_CAN_CONFIG, &elm->cmds_todo);
+ elm->next_init_cmd = &can327_init_script[0];
+ set_bit(CAN327_TX_DO_INIT, &elm->cmds_todo);
+ set_bit(CAN327_TX_DO_SILENT_MONITOR, &elm->cmds_todo);
+ set_bit(CAN327_TX_DO_RESPONSES, &elm->cmds_todo);
+ set_bit(CAN327_TX_DO_CAN_CONFIG, &elm->cmds_todo);
- elm327_kick_into_cmd_mode(elm);
+ can327_kick_into_cmd_mode(elm);
}
-static void elm327_feed_frame_to_netdev(struct can327 *elm,
+static void can327_feed_frame_to_netdev(struct can327 *elm,
struct sk_buff *skb)
{
lockdep_assert_held(&elm->lock);
}
/* Called when we're out of ideas and just want it all to end. */
-static inline void elm327_uart_side_failure(struct can327 *elm)
+static inline void can327_uart_side_failure(struct can327 *elm)
{
struct can_frame *frame;
struct sk_buff *skb;
elm->can.state = CAN_STATE_BUS_OFF;
can_bus_off(elm->dev);
- netdev_err(elm->dev, "ELM327 misbehaved. Blocking further communication.\n");
+ netdev_err(elm->dev,
+ "ELM327 misbehaved. Blocking further communication.\n");
skb = alloc_can_err_skb(elm->dev, &frame);
if (!skb)
return;
frame->can_id |= CAN_ERR_BUSOFF;
- elm327_feed_frame_to_netdev(elm, skb);
+ can327_feed_frame_to_netdev(elm, skb);
}
-/* 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.
+/* 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.
+ * The reason to use strings is so we can easily include them in the C
+ * code, and to avoid hardcoding lengths.
*/
-static inline int elm327_rxbuf_cmp(const u8 *buf, size_t nbytes, const char *reference)
+static inline bool can327_rxbuf_cmp(const u8 *buf, size_t nbytes,
+ const char *reference)
{
size_t ref_len = strlen(reference);
return (nbytes == ref_len) && !memcmp(buf, reference, ref_len);
}
-static void elm327_parse_error(struct can327 *elm, size_t len)
+static void can327_parse_error(struct can327 *elm, size_t len)
{
struct can_frame *frame;
struct sk_buff *skb;
return;
/* Filter possible error messages based on length of RX'd line */
- if (elm327_rxbuf_cmp(elm->rxbuf, len, "UNABLE TO CONNECT")) {
+ if (can327_rxbuf_cmp(elm->rxbuf, len, "UNABLE TO CONNECT")) {
netdev_err(elm->dev,
"ELM327 reported UNABLE TO CONNECT. Please check your setup.\n");
- } else if (elm327_rxbuf_cmp(elm->rxbuf, len, "BUFFER FULL")) {
+ } else if (can327_rxbuf_cmp(elm->rxbuf, len, "BUFFER FULL")) {
/* This will only happen if the last data line was complete.
- * Otherwise, elm327_parse_frame() will heuristically
+ * Otherwise, can327_parse_frame() will heuristically
* emit this kind of error frame instead.
*/
frame->can_id |= CAN_ERR_CRTL;
frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
- } else if (elm327_rxbuf_cmp(elm->rxbuf, len, "BUS ERROR")) {
+ } else if (can327_rxbuf_cmp(elm->rxbuf, len, "BUS ERROR")) {
frame->can_id |= CAN_ERR_BUSERROR;
- } else if (elm327_rxbuf_cmp(elm->rxbuf, len, "CAN ERROR")) {
+ } else if (can327_rxbuf_cmp(elm->rxbuf, len, "CAN ERROR")) {
frame->can_id |= CAN_ERR_PROT;
- } else if (elm327_rxbuf_cmp(elm->rxbuf, len, "<RX ERROR")) {
+ } else if (can327_rxbuf_cmp(elm->rxbuf, len, "<RX ERROR")) {
frame->can_id |= CAN_ERR_PROT;
- } else if (elm327_rxbuf_cmp(elm->rxbuf, len, "BUS BUSY")) {
+ } else if (can327_rxbuf_cmp(elm->rxbuf, len, "BUS BUSY")) {
frame->can_id |= CAN_ERR_PROT;
frame->data[2] = CAN_ERR_PROT_OVERLOAD;
- } else if (elm327_rxbuf_cmp(elm->rxbuf, len, "FB ERROR")) {
+ } else if (can327_rxbuf_cmp(elm->rxbuf, len, "FB ERROR")) {
frame->can_id |= CAN_ERR_PROT;
frame->data[2] = CAN_ERR_PROT_TX;
} else if (len == 5 && !memcmp(elm->rxbuf, "ERR", 3)) {
*/
}
- elm327_feed_frame_to_netdev(elm, skb);
+ can327_feed_frame_to_netdev(elm, skb);
}
/* Parse CAN frames coming as ASCII from ELM327.
*
* We will use the spaces and line length to guess the format.
*/
-static int elm327_parse_frame(struct can327 *elm, size_t len)
+static int can327_parse_frame(struct can327 *elm, size_t len)
{
struct can_frame *frame;
struct sk_buff *skb;
/* Sanity check whether the line is really a clean hexdump,
* or terminated by an error message, or contains garbage.
*/
- if (hexlen < len &&
- !isdigit(elm->rxbuf[hexlen]) &&
- !isupper(elm->rxbuf[hexlen]) &&
- '<' != elm->rxbuf[hexlen] &&
+ if (hexlen < len && !isdigit(elm->rxbuf[hexlen]) &&
+ !isupper(elm->rxbuf[hexlen]) && '<' != elm->rxbuf[hexlen] &&
' ' != elm->rxbuf[hexlen]) {
/* The line is likely garbled anyway, so bail.
* The main code will restart listening.
*/
+ kfree_skb(skb);
return -ENODATA;
}
/* This is not a well-formatted data line.
* Assume it's an error message.
*/
+ kfree_skb(skb);
return -ENODATA;
}
/* The line is too short to be a valid frame hex dump.
* Something interrupted the hex dump or it is invalid.
*/
+ kfree_skb(skb);
return -ENODATA;
}
/* Read CAN ID */
if (frame->can_id & CAN_EFF_FLAG) {
- frame->can_id |= (hex_to_bin(elm->rxbuf[0]) << 28)
- | (hex_to_bin(elm->rxbuf[1]) << 24)
- | (hex_to_bin(elm->rxbuf[3]) << 20)
- | (hex_to_bin(elm->rxbuf[4]) << 16)
- | (hex_to_bin(elm->rxbuf[6]) << 12)
- | (hex_to_bin(elm->rxbuf[7]) << 8)
- | (hex_to_bin(elm->rxbuf[9]) << 4)
- | (hex_to_bin(elm->rxbuf[10]) << 0);
+ frame->can_id |= (hex_to_bin(elm->rxbuf[0]) << 28) |
+ (hex_to_bin(elm->rxbuf[1]) << 24) |
+ (hex_to_bin(elm->rxbuf[3]) << 20) |
+ (hex_to_bin(elm->rxbuf[4]) << 16) |
+ (hex_to_bin(elm->rxbuf[6]) << 12) |
+ (hex_to_bin(elm->rxbuf[7]) << 8) |
+ (hex_to_bin(elm->rxbuf[9]) << 4) |
+ (hex_to_bin(elm->rxbuf[10]) << 0);
} else {
- frame->can_id |= (hex_to_bin(elm->rxbuf[0]) << 8)
- | (hex_to_bin(elm->rxbuf[1]) << 4)
- | (hex_to_bin(elm->rxbuf[2]) << 0);
+ frame->can_id |= (hex_to_bin(elm->rxbuf[0]) << 8) |
+ (hex_to_bin(elm->rxbuf[1]) << 4) |
+ (hex_to_bin(elm->rxbuf[2]) << 0);
}
/* Check for RTR frame */
frame->can_id = CAN_ERR_FLAG | CAN_ERR_CRTL;
frame->len = CAN_ERR_DLC;
frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
- elm327_feed_frame_to_netdev(elm, skb);
+ can327_feed_frame_to_netdev(elm, skb);
/* Signal failure to parse.
* The line will be re-parsed as an error line, which will fail.
/* Parse the data nibbles. */
for (i = 0; i < frame->len; i++) {
- frame->data[i] = (hex_to_bin(elm->rxbuf[datastart + 3*i]) << 4)
- | (hex_to_bin(elm->rxbuf[datastart + 3*i + 1]));
+ frame->data[i] =
+ (hex_to_bin(elm->rxbuf[datastart + 3 * i]) << 4) |
+ (hex_to_bin(elm->rxbuf[datastart + 3 * i + 1]));
}
/* Feed the frame to the network layer. */
- elm327_feed_frame_to_netdev(elm, skb);
+ can327_feed_frame_to_netdev(elm, skb);
return 0;
}
-static void elm327_parse_line(struct can327 *elm, size_t len)
+static void can327_parse_line(struct can327 *elm, size_t len)
{
lockdep_assert_held(&elm->lock);
}
/* Regular parsing */
- if (elm->state == ELM327_STATE_RECEIVING &&
- elm327_parse_frame(elm, len)) {
+ if (elm->state == CAN327_STATE_RECEIVING &&
+ can327_parse_frame(elm, len)) {
/* Parse an error line. */
- elm327_parse_error(elm, len);
+ can327_parse_error(elm, len);
/* Start afresh. */
- elm327_kick_into_cmd_mode(elm);
+ can327_kick_into_cmd_mode(elm);
}
}
-static void elm327_handle_prompt(struct can327 *elm)
+static void can327_handle_prompt(struct can327 *elm)
{
struct can_frame *frame = &elm->can_frame_to_send;
/* Size this buffer for the largest ELM327 line we may generate,
* which is currently an 8 byte CAN frame's payload hexdump.
- * Items in elm327_init_script must fit here, too!
+ * Items in can327_init_script must fit here, too!
*/
char local_txbuf[sizeof("0102030405060708\r")];
if (!elm->cmds_todo) {
/* Enter CAN monitor mode */
- elm327_send(elm, "ATMA\r", 5);
- elm->state = ELM327_STATE_RECEIVING;
+ can327_send(elm, "ATMA\r", 5);
+ elm->state = CAN327_STATE_RECEIVING;
/* We will be in the default state once this command is
* sent, so enable the TX packet queue.
}
/* Reconfigure ELM327 step by step as indicated by elm->cmds_todo */
- if (test_bit(ELM327_TX_DO_INIT, &elm->cmds_todo)) {
- snprintf(local_txbuf, sizeof(local_txbuf),
- "%s",
+ if (test_bit(CAN327_TX_DO_INIT, &elm->cmds_todo)) {
+ snprintf(local_txbuf, sizeof(local_txbuf), "%s",
*elm->next_init_cmd);
elm->next_init_cmd++;
if (!(*elm->next_init_cmd)) {
- clear_bit(ELM327_TX_DO_INIT, &elm->cmds_todo);
+ clear_bit(CAN327_TX_DO_INIT, &elm->cmds_todo);
/* Init finished. */
}
- } else if (test_and_clear_bit(ELM327_TX_DO_SILENT_MONITOR, &elm->cmds_todo)) {
+ } else if (test_and_clear_bit(CAN327_TX_DO_SILENT_MONITOR, &elm->cmds_todo)) {
snprintf(local_txbuf, sizeof(local_txbuf),
"ATCSM%i\r",
!!(elm->can.ctrlmode & CAN_CTRLMODE_LISTENONLY));
- } else if (test_and_clear_bit(ELM327_TX_DO_RESPONSES, &elm->cmds_todo)) {
+ } else if (test_and_clear_bit(CAN327_TX_DO_RESPONSES, &elm->cmds_todo)) {
snprintf(local_txbuf, sizeof(local_txbuf),
"ATR%i\r",
!(elm->can.ctrlmode & CAN_CTRLMODE_LISTENONLY));
- } else if (test_and_clear_bit(ELM327_TX_DO_CAN_CONFIG, &elm->cmds_todo)) {
+ } else if (test_and_clear_bit(CAN327_TX_DO_CAN_CONFIG, &elm->cmds_todo)) {
snprintf(local_txbuf, sizeof(local_txbuf),
"ATPC\r");
- set_bit(ELM327_TX_DO_CAN_CONFIG_PART2, &elm->cmds_todo);
+ set_bit(CAN327_TX_DO_CAN_CONFIG_PART2, &elm->cmds_todo);
- } else if (test_and_clear_bit(ELM327_TX_DO_CAN_CONFIG_PART2, &elm->cmds_todo)) {
+ } else if (test_and_clear_bit(CAN327_TX_DO_CAN_CONFIG_PART2, &elm->cmds_todo)) {
snprintf(local_txbuf, sizeof(local_txbuf),
"ATPB%04X\r",
elm->can_config);
- } else if (test_and_clear_bit(ELM327_TX_DO_CANID_29BIT_HIGH, &elm->cmds_todo)) {
+ } else if (test_and_clear_bit(CAN327_TX_DO_CANID_29BIT_HIGH, &elm->cmds_todo)) {
snprintf(local_txbuf, sizeof(local_txbuf),
"ATCP%02X\r",
(frame->can_id & CAN_EFF_MASK) >> 24);
- } else if (test_and_clear_bit(ELM327_TX_DO_CANID_29BIT_LOW, &elm->cmds_todo)) {
+ } else if (test_and_clear_bit(CAN327_TX_DO_CANID_29BIT_LOW, &elm->cmds_todo)) {
snprintf(local_txbuf, sizeof(local_txbuf),
"ATSH%06X\r",
frame->can_id & CAN_EFF_MASK & ((1 << 24) - 1));
- } else if (test_and_clear_bit(ELM327_TX_DO_CANID_11BIT, &elm->cmds_todo)) {
+ } else if (test_and_clear_bit(CAN327_TX_DO_CANID_11BIT, &elm->cmds_todo)) {
snprintf(local_txbuf, sizeof(local_txbuf),
"ATSH%03X\r",
frame->can_id & CAN_SFF_MASK);
- } else if (test_and_clear_bit(ELM327_TX_DO_CAN_DATA, &elm->cmds_todo)) {
+ } else if (test_and_clear_bit(CAN327_TX_DO_CAN_DATA, &elm->cmds_todo)) {
if (frame->can_id & CAN_RTR_FLAG) {
/* Send an RTR frame. Their DLC is fixed.
* Some chips don't send them at all.
*/
- snprintf(local_txbuf, sizeof(local_txbuf),
- "ATRTR\r");
+ snprintf(local_txbuf, sizeof(local_txbuf), "ATRTR\r");
} else {
/* Send a regular CAN data frame */
int i;
for (i = 0; i < frame->len; i++) {
- snprintf(&local_txbuf[2 * i], sizeof(local_txbuf),
- "%02X",
+ snprintf(&local_txbuf[2 * i],
+ sizeof(local_txbuf), "%02X",
frame->data[i]);
}
}
elm->drop_next_line = 1;
- elm->state = ELM327_STATE_RECEIVING;
+ elm->state = CAN327_STATE_RECEIVING;
/* We will be in the default state once this command is
* sent, so enable the TX packet queue.
netif_wake_queue(elm->dev);
}
- elm327_send(elm, local_txbuf, strlen(local_txbuf));
+ can327_send(elm, local_txbuf, strlen(local_txbuf));
}
-static bool elm327_is_ready_char(char c)
+static bool can327_is_ready_char(char c)
{
/* Bits 0xc0 are sometimes set (randomly), hence the mask.
* Probably bad hardware.
*/
- return (c & 0x3f) == ELM327_READY_CHAR;
+ return (c & 0x3f) == CAN327_READY_CHAR;
}
-static void elm327_drop_bytes(struct can327 *elm, size_t i)
+static void can327_drop_bytes(struct can327 *elm, size_t i)
{
lockdep_assert_held(&elm->lock);
- memmove(&elm->rxbuf[0], &elm->rxbuf[i], ELM327_SIZE_RXBUF - i);
+ memmove(&elm->rxbuf[0], &elm->rxbuf[i], CAN327_SIZE_RXBUF - i);
elm->rxfill -= i;
}
-static void elm327_parse_rxbuf(struct can327 *elm)
+static void can327_parse_rxbuf(struct can327 *elm, size_t first_new_char_idx)
{
- size_t len;
- int i;
+ size_t len, pos;
lockdep_assert_held(&elm->lock);
switch (elm->state) {
- case ELM327_STATE_NOTINIT:
+ case CAN327_STATE_NOTINIT:
elm->rxfill = 0;
break;
- case ELM327_STATE_GETDUMMYCHAR:
+ case CAN327_STATE_GETDUMMYCHAR:
/* Wait for 'y' or '>' */
- for (i = 0; i < elm->rxfill; i++) {
- if (elm->rxbuf[i] == ELM327_DUMMY_CHAR) {
- elm327_send(elm, "\r", 1);
- elm->state = ELM327_STATE_GETPROMPT;
- i++;
+ for (pos = 0; pos < elm->rxfill; pos++) {
+ if (elm->rxbuf[pos] == CAN327_DUMMY_CHAR) {
+ can327_send(elm, "\r", 1);
+ elm->state = CAN327_STATE_GETPROMPT;
+ pos++;
break;
- } else if (elm327_is_ready_char(elm->rxbuf[i])) {
- elm327_send(elm, ELM327_DUMMY_STRING, 1);
- i++;
+ } else if (can327_is_ready_char(elm->rxbuf[pos])) {
+ can327_send(elm, CAN327_DUMMY_STRING, 1);
+ pos++;
break;
}
}
- elm327_drop_bytes(elm, i);
+ can327_drop_bytes(elm, pos);
break;
- case ELM327_STATE_GETPROMPT:
+ case CAN327_STATE_GETPROMPT:
/* Wait for '>' */
- if (elm327_is_ready_char(elm->rxbuf[elm->rxfill - 1]))
- elm327_handle_prompt(elm);
+ if (can327_is_ready_char(elm->rxbuf[elm->rxfill - 1]))
+ can327_handle_prompt(elm);
elm->rxfill = 0;
break;
- case ELM327_STATE_RECEIVING:
+ case CAN327_STATE_RECEIVING:
/* Find <CR> delimiting feedback lines. */
- len = 0;
+ len = first_new_char_idx;
while (len < elm->rxfill && elm->rxbuf[len] != '\r')
len++;
- if (len == ELM327_SIZE_RXBUF) {
+ if (len == CAN327_SIZE_RXBUF) {
/* Assume the buffer ran full with garbage.
* Did we even connect at the right baud rate?
*/
netdev_err(elm->dev,
"RX buffer overflow. Faulty ELM327 or UART?\n");
- elm327_uart_side_failure(elm);
+ can327_uart_side_failure(elm);
} else if (len == elm->rxfill) {
- if (elm327_is_ready_char(elm->rxbuf[elm->rxfill - 1])) {
+ if (can327_is_ready_char(elm->rxbuf[elm->rxfill - 1])) {
/* The ELM327's AT ST response timeout ran out,
* so we got a prompt.
* Clear RX buffer and restart listening.
*/
elm->rxfill = 0;
- elm327_handle_prompt(elm);
+ can327_handle_prompt(elm);
}
/* No <CR> found - we haven't received a full line yet.
*/
} else {
/* We have a full line to parse. */
- elm327_parse_line(elm, len);
+ can327_parse_line(elm, len);
/* Remove parsed data from RX buffer. */
- elm327_drop_bytes(elm, len + 1);
+ can327_drop_bytes(elm, len + 1);
/* More data to parse? */
if (elm->rxfill)
- elm327_parse_rxbuf(elm);
+ can327_parse_rxbuf(elm, 0);
}
}
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)
-/* Dummy needed to use can_rx_offload */
+/* Dummy needed to use can_rx_offload
+ * Fixed in v5.10 - 728fc9ff73d3
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,5,0)
+static unsigned int *can327_mailbox_read(struct can_rx_offload *offload,
+ struct can_frame *cf,
+ u32 *timestamp, unsigned int n)
+{
+ WARN_ON_ONCE(1); /* This function is a dummy, so don't call it! */
+
+ return -ENOBUFS;
+}
+#else /* Since 4e9c9484b085 (included in v5.5) */
static struct sk_buff *can327_mailbox_read(struct can_rx_offload *offload,
unsigned int n, u32 *timestamp,
bool drop)
return ERR_PTR(-ENOBUFS);
}
#endif
+#endif
static int can327_netdev_open(struct net_device *dev)
{
}
if (elm->uart_side_failure)
- netdev_warn(elm->dev, "Reopening netdev after a UART side fault has been detected.\n");
+ netdev_warn(elm->dev,
+ "Reopening netdev after a UART side fault has been detected.\n");
/* Clear TTY buffers */
elm->rxfill = 0;
return err;
}
- elm327_init(elm);
+ can327_init_device(elm);
spin_unlock_bh(&elm->lock);
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)
elm->offload.mailbox_read = can327_mailbox_read;
- err = can_rx_offload_add_fifo(dev, &elm->offload, ELM327_NAPI_WEIGHT);
+ err = can_rx_offload_add_fifo(dev, &elm->offload, CAN327_NAPI_WEIGHT);
#else
- err = can_rx_offload_add_manual(dev, &elm->offload, ELM327_NAPI_WEIGHT);
+ /* Fixed in v5.10 - 728fc9ff73d3 */
+ err = can_rx_offload_add_manual(dev, &elm->offload, CAN327_NAPI_WEIGHT);
#endif
if (err) {
close_candev(dev);
can_rx_offload_enable(&elm->offload);
- can_led_event(dev, CAN_LED_EVENT_OPEN);
elm->can.state = CAN_STATE_ERROR_ACTIVE;
netif_start_queue(dev);
/* Interrupt whatever the ELM327 is doing right now */
spin_lock_bh(&elm->lock);
- elm327_send(elm, ELM327_DUMMY_STRING, 1);
+ can327_send(elm, CAN327_DUMMY_STRING, 1);
spin_unlock_bh(&elm->lock);
netif_stop_queue(dev);
elm->can.state = CAN_STATE_STOPPED;
can_rx_offload_del(&elm->offload);
close_candev(dev);
- can_led_event(dev, CAN_LED_EVENT_STOP);
return 0;
}
if (can_dropped_invalid_skb(dev, skb))
return NETDEV_TX_OK;
- /* BHs are already disabled, so no spin_lock_bh().
- * See Documentation/networking/netdevices.txt
- */
- spin_lock(&elm->lock);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,0,0)
+ /* Fixed in v6.0 - a6d190f8c767 */
+ if (elm->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+ goto out;
+#endif
/* We shouldn't get here after a hardware fault:
* can_bus_off() calls netif_carrier_off()
*/
- WARN_ON_ONCE(elm->uart_side_failure);
-
- if (!elm->tty ||
- elm->uart_side_failure ||
- elm->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
- spin_unlock(&elm->lock);
+ if (elm->uart_side_failure) {
+ WARN_ON_ONCE(elm->uart_side_failure);
goto out;
}
netif_stop_queue(dev);
- elm327_send_frame(elm, frame);
+ /* BHs are already disabled, so no spin_lock_bh().
+ * See Documentation/networking/netdevices.txt
+ */
+ spin_lock(&elm->lock);
+ can327_send_frame(elm, frame);
spin_unlock(&elm->lock);
dev->stats.tx_packets++;
- dev->stats.tx_bytes += frame->len;
-
- can_led_event(dev, CAN_LED_EVENT_TX);
+ dev->stats.tx_bytes += frame->can_id & CAN_RTR_FLAG ? 0 : frame->len;
out:
kfree_skb(skb);
}
static const struct net_device_ops can327_netdev_ops = {
- .ndo_open = can327_netdev_open,
- .ndo_stop = can327_netdev_close,
- .ndo_start_xmit = can327_netdev_start_xmit,
- .ndo_change_mtu = can_change_mtu,
+ .ndo_open = can327_netdev_open,
+ .ndo_stop = can327_netdev_close,
+ .ndo_start_xmit = can327_netdev_start_xmit,
+ .ndo_change_mtu = can_change_mtu,
};
-static bool can327_is_valid_rx_char(char c)
+static bool can327_is_valid_rx_char(u8 c)
{
- return (isdigit(c) ||
- isupper(c) ||
- c == ELM327_DUMMY_CHAR ||
- c == ELM327_READY_CHAR ||
- c == '<' ||
- c == 'a' ||
- c == 'b' ||
- c == 'v' ||
- c == '.' ||
- c == '?' ||
- c == '\r' ||
- c == ' ');
+ static const bool lut_char_is_valid['z'] = {
+ ['\r'] = true,
+ [' '] = true,
+ ['.'] = true,
+ ['0'] = true, true, true, true, true,
+ ['5'] = true, true, true, true, true,
+ ['<'] = true,
+ [CAN327_READY_CHAR] = true,
+ ['?'] = true,
+ ['A'] = true, true, true, true, true, true, true,
+ ['H'] = true, true, true, true, true, true, true,
+ ['O'] = true, true, true, true, true, true, true,
+ ['V'] = true, true, true, true, true,
+ ['a'] = true,
+ ['b'] = true,
+ ['v'] = true,
+ [CAN327_DUMMY_CHAR] = true,
+ };
+ BUILD_BUG_ON(CAN327_DUMMY_CHAR >= 'z');
+
+ return (c < ARRAY_SIZE(lut_char_is_valid) && lut_char_is_valid[c]);
}
/* Handle incoming ELM327 ASCII data.
#endif
{
struct can327 *elm = (struct can327 *)tty->disc_data;
+ size_t first_new_char_idx;
+
+ if (elm->uart_side_failure)
+ return;
spin_lock_bh(&elm->lock);
- if (elm->uart_side_failure)
- goto out;
+ /* Store old rxfill, so can327_parse_rxbuf() will have
+ * the option of skipping already checked characters.
+ */
+ first_new_char_idx = elm->rxfill;
- while (count-- && elm->rxfill < ELM327_SIZE_RXBUF) {
+ while (count-- && elm->rxfill < CAN327_SIZE_RXBUF) {
if (fp && *fp++) {
- netdev_err(elm->dev, "Error in received character stream. Check your wiring.");
+ netdev_err(elm->dev,
+ "Error in received character stream. Check your wiring.");
- elm327_uart_side_failure(elm);
+ can327_uart_side_failure(elm);
- goto out;
+ spin_unlock_bh(&elm->lock);
+ return;
}
/* Ignore NUL characters, which the PIC microcontroller may
netdev_err(elm->dev,
"Received illegal character %02x.\n",
*cp);
- elm327_uart_side_failure(elm);
+ can327_uart_side_failure(elm);
- goto out;
+ spin_unlock_bh(&elm->lock);
+ return;
}
elm->rxbuf[elm->rxfill++] = *cp;
}
if (count >= 0) {
- netdev_err(elm->dev, "Receive buffer overflowed. Bad chip or wiring?");
+ netdev_err(elm->dev,
+ "Receive buffer overflowed. Bad chip or wiring? count = %i",
+ count);
- elm327_uart_side_failure(elm);
+ can327_uart_side_failure(elm);
- goto out;
+ spin_unlock_bh(&elm->lock);
+ return;
}
- elm327_parse_rxbuf(elm);
-
-out:
+ can327_parse_rxbuf(elm, first_new_char_idx);
spin_unlock_bh(&elm->lock);
}
spin_lock_bh(&elm->lock);
if (elm->txleft) {
- written = elm->tty->ops->write(elm->tty, elm->txhead, elm->txleft);
+ written = elm->tty->ops->write(elm->tty, elm->txhead,
+ elm->txleft);
if (written < 0) {
- netdev_err(elm->dev,
- "Failed to write to tty %s.\n",
+ netdev_err(elm->dev, "Failed to write to tty %s.\n",
elm->tty->name);
- elm327_uart_side_failure(elm);
+ can327_uart_side_failure(elm);
+
spin_unlock_bh(&elm->lock);
return;
}
elm->txhead += written;
}
- if (!elm->txleft) {
+ if (!elm->txleft)
clear_bit(TTY_DO_WRITE_WAKEUP, &elm->tty->flags);
- spin_unlock_bh(&elm->lock);
- } else {
- spin_unlock_bh(&elm->lock);
- }
+
+ spin_unlock_bh(&elm->lock);
}
/* Called by the driver when there's room for more data. */
* 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[64] = {
- 7812, 7936, 8064, 8196, 8333, 8474, 8620, 8771,
- 8928, 9090, 9259, 9433, 9615, 9803, 10000, 10204,
- 10416, 10638, 10869, 11111, 11363, 11627, 11904, 12195,
- 12500, 12820, 13157, 13513, 13888, 14285, 14705, 15151,
- 15625, 16129, 16666, 17241, 17857, 18518, 19230, 20000,
- 20833, 21739, 22727, 23809, 25000, 26315, 27777, 29411,
- 31250, 33333, 35714, 38461, 41666, 45454, 50000, 55555,
+static const u32 can327_bitrate_const[] = {
+ 7812, 7936, 8064, 8196, 8333, 8474, 8620, 8771,
+ 8928, 9090, 9259, 9433, 9615, 9803, 10000, 10204,
+ 10416, 10638, 10869, 11111, 11363, 11627, 11904, 12195,
+ 12500, 12820, 13157, 13513, 13888, 14285, 14705, 15151,
+ 15625, 16129, 16666, 17241, 17857, 18518, 19230, 20000,
+ 20833, 21739, 22727, 23809, 25000, 26315, 27777, 29411,
+ 31250, 33333, 35714, 38461, 41666, 45454, 50000, 55555,
62500, 71428, 83333, 100000, 125000, 166666, 250000, 500000
};
-/* Dummy needed to use bitrate_const */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,0,0)
+/* Dummy needed to use bitrate_const
+ * Fixed in v6.0 - 7e193a42c37c
+ */
static int can327_do_set_bittiming(struct net_device *netdev)
{
return 0;
}
+#endif
static int can327_ldisc_open(struct tty_struct *tty)
{
/* Configure CAN metadata */
elm->can.bitrate_const = can327_bitrate_const;
elm->can.bitrate_const_cnt = ARRAY_SIZE(can327_bitrate_const);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,0,0)
+ /* Fixed in v6.0 - 7e193a42c37c */
elm->can.do_set_bittiming = can327_do_set_bittiming;
+#endif
elm->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY;
/* Configure netdev interface */
elm->tty = tty;
tty->disc_data = elm;
- devm_can_led_init(elm->dev);
-
/* Let 'er rip */
err = register_candev(elm->dev);
- if (err)
- goto out_err;
+ if (err) {
+ free_candev(elm->dev);
+ return err;
+ }
netdev_info(elm->dev, "can327 on %s.\n", tty->name);
return 0;
-
-out_err:
- free_candev(elm->dev);
- return err;
}
/* Close down a can327 channel.
}
static struct tty_ldisc_ops can327_ldisc = {
- .owner = THIS_MODULE,
- .name = "can327",
- .num = N_DEVELOPMENT,
- .receive_buf = can327_ldisc_rx,
- .write_wakeup = can327_ldisc_tx_wakeup,
- .open = can327_ldisc_open,
- .close = can327_ldisc_close,
- .ioctl = can327_ldisc_ioctl,
+ .owner = THIS_MODULE,
+ .name = "can327",
+ .num = N_DEVELOPMENT,
+ .receive_buf = can327_ldisc_rx,
+ .write_wakeup = can327_ldisc_tx_wakeup,
+ .open = can327_ldisc_open,
+ .close = can327_ldisc_close,
+ .ioctl = can327_ldisc_ioctl,
};
static int __init can327_init(void)
MODULE_ALIAS_LDISC(N_DEVELOPMENT);
MODULE_DESCRIPTION("ELM327 based CAN interface");
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Max Staudt <max-linux@enpas.org>");
+MODULE_AUTHOR("Max Staudt <max@enpas.org>");