X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=module%2Felmcan.c;h=8b27c85fa60046a90fdfe07d5d1e41d994460706;hb=455c430003db1fbd4030ec3deba4cdf67e0a3158;hp=516c22a2f24a3ecac9f26c0ab415939372545a46;hpb=8fff8608a57e1261df0ea709c57db43c84fa8c55;p=elmcan.git diff --git a/module/elmcan.c b/module/elmcan.c index 516c22a..8b27c85 100644 --- a/module/elmcan.c +++ b/module/elmcan.c @@ -60,6 +60,9 @@ MODULE_PARM_DESC(accept_flaky_uart, "Don't bail at the first invalid character. #define N_ELMCAN 29 #endif +#define ELM327_SIZE_RXBUF 256 +#define ELM327_SIZE_TXBUF 32 + #define ELM327_CAN_CONFIG_SEND_SFF 0x8000 #define ELM327_CAN_CONFIG_VARIABLE_DLC 0x4000 #define ELM327_CAN_CONFIG_RECV_BOTH_SFF_EFF 0x2000 @@ -111,12 +114,12 @@ struct elmcan { /* TTY TX helpers */ struct work_struct tx_work; /* Flushes TTY TX buffer */ - unsigned char txbuf[32]; + unsigned char *txbuf; unsigned char *txhead; /* Pointer to next TX byte */ int txleft; /* Bytes left to TX */ /* TTY RX helpers */ - unsigned char rxbuf[256]; + unsigned char *rxbuf; int rxfill; /* State machine */ @@ -156,11 +159,11 @@ static inline void elm327_hw_failure(struct elmcan *elm); - /************************************************************************ - * ELM327: Transmission * - * * - * (all functions assume elm->lock taken) * - ************************************************************************/ + /*********************************************************************** + * ELM327: Transmission * + * * + * (all functions assume elm->lock taken) * + ***********************************************************************/ static void elm327_send(struct elmcan *elm, const void *buf, size_t len) { @@ -194,7 +197,11 @@ static void elm327_send(struct elmcan *elm, const void *buf, size_t len) } -/* Take the ELM327 out of almost any state and back into command mode. */ +/* Take the ELM327 out of almost any state and back into command mode. + * We send ELM327_MAGIC_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 elmcan *elm) { if (elm->state != ELM_GETMAGICCHAR && elm->state != ELM_GETPROMPT) { @@ -243,11 +250,11 @@ static void elm327_send_frame(struct elmcan *elm, struct can_frame *frame) - /************************************************************************ - * ELM327: Initialization sequence * - * * - * (assumes elm->lock taken) * - ************************************************************************/ + /*********************************************************************** + * ELM327: Initialization sequence * + * * + * (assumes elm->lock taken) * + ***********************************************************************/ static char *elm327_init_script[] = { "AT WS\r", /* v1.0: Warm Start */ @@ -301,11 +308,11 @@ static void elm327_init(struct elmcan *elm) - /************************************************************************ - * ELM327: Reception -> netdev glue * - * * - * (assumes elm->lock taken) * - ************************************************************************/ + /*********************************************************************** + * ELM327: Reception -> netdev glue * + * * + * (assumes elm->lock taken) * + ***********************************************************************/ static void elm327_feed_frame_to_netdev(struct elmcan *elm, const struct can_frame *frame) @@ -332,11 +339,11 @@ static void elm327_feed_frame_to_netdev(struct elmcan *elm, - /************************************************************************ - * ELM327: "Panic" handler * - * * - * (assumes elm->lock taken) * - ************************************************************************/ + /*********************************************************************** + * ELM327: "Panic" handler * + * * + * (assumes elm->lock taken) * + ***********************************************************************/ /* Called when we're out of ideas and just want it all to end. */ static inline void elm327_hw_failure(struct elmcan *elm) @@ -359,11 +366,11 @@ static inline void elm327_hw_failure(struct elmcan *elm) - /************************************************************************ - * ELM327: Reception parser * - * * - * (assumes elm->lock taken) * - ************************************************************************/ + /*********************************************************************** + * ELM327: Reception parser * + * * + * (assumes elm->lock taken) * + ***********************************************************************/ static void elm327_parse_error(struct elmcan *elm, int len) { @@ -683,7 +690,7 @@ static bool elm327_is_ready_char(char c) static void elm327_drop_bytes(struct elmcan *elm, int i) { - memmove(&elm->rxbuf[0], &elm->rxbuf[i], sizeof(elm->rxbuf) - i); + memmove(&elm->rxbuf[0], &elm->rxbuf[i], ELM327_SIZE_RXBUF - i); elm->rxfill -= i; } @@ -694,7 +701,7 @@ static void elm327_parse_rxbuf(struct elmcan *elm) switch (elm->state) { case ELM_NOTINIT: elm->rxfill = 0; - return; + break; case ELM_GETMAGICCHAR: { @@ -716,7 +723,7 @@ static void elm327_parse_rxbuf(struct elmcan *elm) elm327_drop_bytes(elm, i); - return; + break; } case ELM_GETPROMPT: @@ -725,7 +732,7 @@ static void elm327_parse_rxbuf(struct elmcan *elm) elm327_handle_prompt(elm); elm->rxfill = 0; - return; + break; case ELM_RECEIVING: /* Find delimiting feedback lines. */ @@ -735,14 +742,14 @@ static void elm327_parse_rxbuf(struct elmcan *elm) /* empty loop */ } - if (len == sizeof(elm->rxbuf)) { + if (len == ELM327_SIZE_RXBUF) { /* Line exceeds buffer. It's probably all garbage. * Did we even connect at the right baud rate? */ netdev_err(elm->dev, "RX buffer overflow. Faulty ELM327 or UART?\n"); elm327_hw_failure(elm); - return; + break; } else if (len == elm->rxfill) { if (elm327_is_ready_char(elm->rxbuf[elm->rxfill - 1])) { /* The ELM327's AT ST response timeout ran out, @@ -752,13 +759,13 @@ static void elm327_parse_rxbuf(struct elmcan *elm) elm->rxfill = 0; elm327_handle_prompt(elm); - return; + break; } /* No found - we haven't received a full line yet. * Wait for more data. */ - return; + break; } /* We have a full line to parse. */ @@ -777,11 +784,11 @@ static void elm327_parse_rxbuf(struct elmcan *elm) - /************************************************************************ - * netdev * - * * - * (takes elm->lock) * - ************************************************************************/ + /*********************************************************************** + * netdev * + * * + * (takes elm->lock) * + ***********************************************************************/ static int elmcan_netdev_open(struct net_device *dev) { @@ -905,11 +912,11 @@ static const struct net_device_ops elmcan_netdev_ops = { - /************************************************************************ - * Line discipline * - * * - * (takes elm->lock) * - ************************************************************************/ + /*********************************************************************** + * Line discipline * + * * + * (takes elm->lock) * + ***********************************************************************/ /* Get a reference to our struct, taking into account locks/refcounts. * This is to ensure ordering in case we are shutting down, and to ensure @@ -945,6 +952,23 @@ static void put_elm(struct elmcan *elm) } +static bool elmcan_is_valid_rx_char(char c) +{ + return (accept_flaky_uart + || isdigit(c) + || isupper(c) + || ELM327_MAGIC_CHAR == c + || ELM327_READY_CHAR == c + || '<' == c + || 'a' == c + || 'b' == c + || 'v' == c + || '.' == c + || '?' == c + || '\r' == c + || ' ' == c); +} + /* Handle incoming ELM327 ASCII data. * This will not be re-entered while running, but other ldisc * functions may be called in parallel. @@ -958,22 +982,18 @@ static void elmcan_ldisc_rx(struct tty_struct *tty, return; spin_lock_bh(&elm->lock); - if (elm->hw_failure) { - spin_unlock_bh(&elm->lock); - put_elm(elm); - return; + if (elm->hw_failure) { + goto out; } - while (count-- && elm->rxfill < sizeof(elm->rxbuf)) { + while (count-- && elm->rxfill < ELM327_SIZE_RXBUF) { if (fp && *fp++) { netdev_err(elm->dev, "Error in received character stream. Check your wiring."); elm327_hw_failure(elm); - spin_unlock_bh(&elm->lock); - put_elm(elm); - return; + goto out; } /* Ignore NUL characters, which the PIC microcontroller may @@ -985,27 +1005,13 @@ static void elmcan_ldisc_rx(struct tty_struct *tty, /* Check for stray characters on the UART line. * Likely caused by bad hardware. */ - 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) { + if (!elmcan_is_valid_rx_char(*cp)) { netdev_err(elm->dev, "Received illegal character %02x.\n", *cp); elm327_hw_failure(elm); - spin_unlock_bh(&elm->lock); - put_elm(elm); - return; + goto out; } elm->rxbuf[elm->rxfill++] = *cp; @@ -1018,15 +1024,14 @@ static void elmcan_ldisc_rx(struct tty_struct *tty, netdev_err(elm->dev, "Receive buffer overflowed. Bad chip or wiring?"); elm327_hw_failure(elm); - spin_unlock_bh(&elm->lock); - put_elm(elm); - return; + goto out; } elm327_parse_rxbuf(elm); - spin_unlock_bh(&elm->lock); +out: + spin_unlock_bh(&elm->lock); put_elm(elm); } @@ -1111,6 +1116,8 @@ static const u32 elmcan_bitrate_const[64] = { /* Dummy needed to use bitrate_const */ static int elmcan_do_set_bittiming(struct net_device *netdev) { + (void)netdev; + return 0; } @@ -1133,6 +1140,13 @@ static int elmcan_ldisc_open(struct tty_struct *tty) return -ENFILE; elm = netdev_priv(dev); + elm->rxbuf = kmalloc(ELM327_SIZE_RXBUF, GFP_KERNEL); + elm->txbuf = kmalloc(ELM327_SIZE_TXBUF, GFP_KERNEL); + if (!elm->rxbuf || !elm->txbuf) { + err = -ENOMEM; + goto out_err; + } + /* Configure TTY interface */ tty->receive_room = 65536; /* We don't flow control */ elm->txleft = 0; /* Clear TTY TX buffer */ @@ -1159,14 +1173,20 @@ static int elmcan_ldisc_open(struct tty_struct *tty) /* Let 'er rip */ err = register_candev(elm->dev); - if (err) { - free_candev(elm->dev); - return err; - } + if (err) + goto out_err; netdev_info(elm->dev, "elmcan on %s.\n", tty->name); return 0; + +out_err: + if (elm->txbuf) + kfree(elm->txbuf); + if (elm->rxbuf) + kfree(elm->rxbuf); + free_candev(elm->dev); + return err; } /* Close down an elmcan channel. @@ -1208,6 +1228,8 @@ static void elmcan_ldisc_close(struct tty_struct *tty) netdev_info(elm->dev, "elmcan off %s.\n", tty->name); + kfree(elm->txbuf); + kfree(elm->rxbuf); free_candev(elm->dev); } @@ -1261,12 +1283,6 @@ static struct tty_ldisc_ops elmcan_ldisc = { - - - /************************************************************************ - * Module init/exit * - ************************************************************************/ - static int __init elmcan_init(void) { int status;