#define ELM327_NAPI_WEIGHT 4
-#define ELM327_SIZE_RXBUF 224
+#define ELM327_SIZE_RXBUF 992
#define ELM327_SIZE_TXBUF 32
#define ELM327_CAN_CONFIG_SEND_SFF 0x8000
* 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 elm327_rxbuf_cmp(const u8 *buf, size_t nbytes, const char *reference)
{
size_t ref_len = strlen(reference);
elm->rxfill -= i;
}
-static void elm327_parse_rxbuf(struct can327 *elm)
+static void elm327_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);
case ELM327_STATE_GETDUMMYCHAR:
/* Wait for 'y' or '>' */
- for (i = 0; i < elm->rxfill; i++) {
- if (elm->rxbuf[i] == ELM327_DUMMY_CHAR) {
+ for (pos = 0; pos < elm->rxfill; pos++) {
+ if (elm->rxbuf[pos] == ELM327_DUMMY_CHAR) {
elm327_send(elm, "\r", 1);
elm->state = ELM327_STATE_GETPROMPT;
- i++;
+ pos++;
break;
- } else if (elm327_is_ready_char(elm->rxbuf[i])) {
+ } else if (elm327_is_ready_char(elm->rxbuf[pos])) {
elm327_send(elm, ELM327_DUMMY_STRING, 1);
- i++;
+ pos++;
break;
}
}
- elm327_drop_bytes(elm, i);
+ elm327_drop_bytes(elm, pos);
break;
case ELM327_STATE_GETPROMPT:
case ELM327_STATE_RECEIVING:
/* Find <CR> delimiting feedback lines. */
- len = 0;
+ len = first_new_char_idx;
while (len < elm->rxfill && elm->rxbuf[len] != '\r')
len++;
/* More data to parse? */
if (elm->rxfill)
- elm327_parse_rxbuf(elm);
+ elm327_parse_rxbuf(elm, 0);
}
}
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)
/* Dummy needed to use can_rx_offload */
+#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)
{
.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,
+ [ELM327_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,
+ [ELM327_DUMMY_CHAR] = true,
+ };
+ BUILD_BUG_ON(ELM327_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);
+ /* Store old rxfill, so elm327_parse_rxbuf() will have
+ * the option of skipping already checked characters.
+ */
+ first_new_char_idx = elm->rxfill;
+
while (count-- && elm->rxfill < ELM327_SIZE_RXBUF) {
if (fp && *fp++) {
netdev_err(elm->dev, "Error in received character stream. Check your wiring.");
}
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);
return;
}
- elm327_parse_rxbuf(elm);
+ elm327_parse_rxbuf(elm, first_new_char_idx);
spin_unlock_bh(&elm->lock);
}