*
* This file is derived from linux/drivers/net/can/slcan.c
*
- * elmcan.c Author : Max Staudt <elmcan@enpas.org>
+ * elmcan.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>
#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>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Max Staudt <max-linux@enpas.org>");
+/* If this is enabled, we'll try to make the best of the situation
+ * even if we receive unexpected characters on the line.
+ * No guarantees.
+ * Handle with care, it's likely your hardware is unreliable!
+ */
+static bool accept_flaky_uart = false;
+module_param_named(accept_flaky_uart, accept_flaky_uart, bool, 0444);
+MODULE_PARM_DESC(accept_flaky_uart, "Don't bail at the first invalid character. Behavior undefined.");
+
+
/* Line discipline ID number */
#ifndef N_ELMCAN
#define N_ELMCAN 29
ELM_TODO_CANID_11BIT,
ELM_TODO_CANID_29BIT_LOW,
ELM_TODO_CANID_29BIT_HIGH,
+ ELM_TODO_CAN_CONFIG_PART2,
ELM_TODO_CAN_CONFIG,
ELM_TODO_RESPONSES,
ELM_TODO_SILENT_MONITOR,
elm327_send(elm, ELM327_MAGIC_STRING, 1);
elm->state = ELM_GETMAGICCHAR;
- elm->rxfill = 0;
}
}
* (assumes elm->lock taken) *
************************************************************************/
+static bool elm327_is_ready_char(char c)
+{
+ /* Bits 0xc0 are sometimes set (randomly), hence the mask.
+ * Probably bad hardware.
+ */
+ return (c & 0x3f) == ELM327_READY_CHAR;
+}
+
+
static void elm327_parse_error(struct elmcan *elm, int len)
{
struct can_frame frame;
}
}
+ /* If we accept stray characters coming in:
+ * Check for stray characters on a payload line.
+ * No idea what causes this.
+ */
+ if (accept_flaky_uart
+ && 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.
+ */
+ elm327_kick_into_cmd_mode(elm);
+ return 3;
+ }
+
/* Use spaces in CAN ID to distinguish 29 or 11 bit address length.
* No out-of-bounds access:
* We use the fact that we can always read from elm->rxbuf.
/* Parse an error line. */
elm327_parse_error(elm, len);
- /* After the error line, we expect a prompt. */
- elm->state = ELM_GETPROMPT;
+ /* Start afresh. */
+ elm327_kick_into_cmd_mode(elm);
}
break;
default:
!(elm->can.ctrlmode & CAN_CTRLMODE_LISTENONLY));
} else if (test_and_clear_bit(ELM_TODO_CAN_CONFIG, &elm->cmds_todo)) {
+ sprintf(local_txbuf, "ATPC\r");
+ set_bit(ELM_TODO_CAN_CONFIG_PART2, &elm->cmds_todo);
+
+ } else if (test_and_clear_bit(ELM_TODO_CAN_CONFIG_PART2, &elm->cmds_todo)) {
sprintf(local_txbuf, "ATPB%04X\r",
elm->can_config);
elm->state = ELM_GETPROMPT;
i++;
break;
- } else if (elm->rxbuf[i] == ELM327_READY_CHAR) {
+ } else if (elm327_is_ready_char(elm->rxbuf[i])) {
elm327_send(elm, ELM327_MAGIC_STRING, 1);
i++;
break;
case ELM_GETPROMPT:
/* Wait for '>' */
- if (elm->rxbuf[elm->rxfill - 1] == ELM327_READY_CHAR) {
+ if (elm327_is_ready_char(elm->rxbuf[elm->rxfill - 1])) {
elm327_handle_prompt(elm);
}
return;
} else if (len == elm->rxfill) {
if (elm->state == ELM_RECEIVING
- && elm->rxbuf[elm->rxfill - 1] == ELM327_READY_CHAR) {
+ && elm327_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.
if (!elm)
return;
+ spin_lock_bh(&elm->lock);
+ if (elm->hw_failure) {
+ spin_unlock_bh(&elm->lock);
+
+ put_elm(elm);
+ return;
+ }
+
/* Read the characters out of the buffer */
while (count-- && elm->rxfill < sizeof(elm->rxbuf)) {
if (fp && *fp++) {
put_elm(elm);
return;
}
+
+ /* Ignore NUL characters, which the PIC microcontroller may
+ * inadvertently insert due to a known hardware bug.
+ * See ELM327 documentation, which refers to a Microchip PIC
+ * bug description.
+ */
if (*cp != 0) {
+ /* Check for stray characters on the UART line.
+ * No idea what causes this.
+ */
+ if (!accept_flaky_uart
+ && !isdigit(*cp)
+ && !isupper(*cp)
+ && ELM327_MAGIC_CHAR != *cp
+ && ELM327_READY_CHAR != *cp
+ && '<' != *cp
+ && 'a' != *cp
+ && 'b' != *cp
+ && 'v' != *cp
+ && '.' != *cp
+ && '?' != *cp
+ && '\r' != *cp
+ && ' ' != *cp) {
+ /* We've received an invalid character, so bail.
+ * There's something wrong with the ELM327, or
+ * with the UART line.
+ */
+ netdev_err(elm->dev,
+ "Received illegal character %02x.\n",
+ *cp);
+ elm327_hw_failure(elm);
+ spin_unlock_bh(&elm->lock);
+
+ put_elm(elm);
+ return;
+ }
+
elm->rxbuf[elm->rxfill++] = *cp;
}
+
cp++;
}
if (count >= 0) {
netdev_err(elm->dev, "Receive buffer overflowed. Bad chip or wiring?");
- spin_lock_bh(&elm->lock);
elm327_hw_failure(elm);
spin_unlock_bh(&elm->lock);
return;
}
- spin_lock_bh(&elm->lock);
elm327_parse_rxbuf(elm);
spin_unlock_bh(&elm->lock);
-/* Some fake bit timings to allow bitrate setting */
-static const struct can_bittiming_const elmcan_bittiming_const = {
- .name = "elmcan",
- .tseg1_min = 1,
- .tseg1_max = 1,
- .tseg2_min = 0,
- .tseg2_max = 0,
- .sjw_max = 1,
- .brp_min = 1,
- .brp_max = 500,
- .brp_inc = 1,
+/* ELM327 can only handle bitrates that are integer divisors of 500 kHz,
+ * or 7/8 of that. Divisors are 1 to 64.
+ * Currently we don't implement support for 7/8 rates.
+ */
+static const u32 elmcan_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,
+ 62500, 71428, 83333, 100000, 125000, 166666, 250000, 500000
};
+/* Dummy function to claim we're changing the bitrate.
+ * We actually do this when opening the net device.
+ */
+static int elmcan_do_set_bittiming(struct net_device *netdev)
+{
+ return 0;
+}
+
+
/*
* Open the high-level part of the elmcan channel.
* This function is called by the TTY module when the
/* Configure CAN metadata */
elm->can.state = CAN_STATE_STOPPED;
- elm->can.clock.freq = 1000000;
- elm->can.bittiming_const = &elmcan_bittiming_const;
+ elm->can.bitrate_const = elmcan_bitrate_const;
+ elm->can.bitrate_const_cnt = ARRAY_SIZE(elmcan_bitrate_const);
+ elm->can.do_set_bittiming = elmcan_do_set_bittiming;
elm->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY;
/* Configure netlink interface */