]> rtime.felk.cvut.cz Git - linux-lin.git/commitdiff
sllin: runtime selectable break by baudrate switching.
authorPavel Pisa <pisa@cmp.felk.cvut.cz>
Mon, 29 Jul 2019 17:07:14 +0000 (19:07 +0200)
committerPavel Pisa <pisa@cmp.felk.cvut.cz>
Mon, 29 Jul 2019 17:07:14 +0000 (19:07 +0200)
It is used as fallback for case when provided TTY does
not support break_ctl operation.

Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
sllin/sllin.c

index 91a18c7ffec1e5f6d8833913d6a51f09a354c1c1..ff9b0fe8d22f83f0bb1714ef3581824d01a875f1 100644 (file)
@@ -104,11 +104,18 @@ MODULE_AUTHOR("Pavel Pisa <pisa@cmp.felk.cvut.cz>");
 
 static bool master = true;
 static int baudrate; /* Use LIN_DEFAULT_BAUDRATE when not set */
+#ifndef BREAK_BY_BAUD
+static bool break_by_baud = false;
+#else /*BREAK_BY_BAUD*/
+static bool break_by_baud = true;
+#endif /*BREAK_BY_BAUD*/
 
 module_param(master, bool, 0444);
 MODULE_PARM_DESC(master, "LIN interface is Master device");
 module_param(baudrate, int, 0444);
 MODULE_PARM_DESC(baudrate, "Baudrate of LIN interface");
+module_param(break_by_baud, bool, 0444);
+MODULE_PARM_DESC(break_by_baud, "Break is sent by temporal baudrate switching");
 
 static int maxdev = 10;                /* MAX number of SLLIN channels;
                                   This can be overridden with
@@ -164,6 +171,7 @@ struct sllin {
        int                     tx_lim;         /* actual limit of bytes to Tx */
        int                     tx_cnt;         /* number of already Tx bytes */
        char                    lin_master;     /* node is a master node */
+       bool                    lin_break_by_baud; /* send break character by baudrate switching */
        int                     lin_baud;       /* LIN baudrate */
        int                     lin_state;      /* state */
        char                    id_to_send;     /* there is ID to be sent */
@@ -661,13 +669,14 @@ static void sllin_master_receive_buf(struct tty_struct *tty,
                        }
                }
 
-#ifndef BREAK_BY_BAUD
-               /* We didn't receive Break character -- fake it! */
-               if ((sl->rx_cnt == SLLIN_BUFF_BREAK) && (*cp == 0x55)) {
-                       netdev_dbg(sl->dev, "LIN_RX[%d]: 0x00\n", sl->rx_cnt);
-                       sl->rx_buff[sl->rx_cnt++] = 0x00;
+               if (!sl->lin_break_by_baud ) {
+                       /* We didn't receive Break character -- fake it! */
+                       if ((sl->rx_cnt == SLLIN_BUFF_BREAK) && (*cp == 0x55)) {
+                               netdev_dbg(sl->dev, "LIN_RX[%d]: 0x00\n",
+                                       sl->rx_cnt);
+                               sl->rx_buff[sl->rx_cnt++] = 0x00;
+                       }
                }
-#endif /* BREAK_BY_BAUD */
 
                if (sl->rx_cnt < SLLIN_BUFF_LEN) {
                        netdev_dbg(sl->dev, "LIN_RX[%d]: 0x%02x\n", sl->rx_cnt, *cp);
@@ -1025,14 +1034,14 @@ static int sllin_send_tx_buff(struct sllin *sl)
                smp_mb__after_atomic();
 #endif
 
-#ifdef BREAK_BY_BAUD
-               if (sl->lin_state != SLSTATE_BREAK_SENT)
+               if (sl->lin_break_by_baud) {
+                       if (sl->lin_state != SLSTATE_BREAK_SENT)
+                               remains = sl->tx_lim - sl->tx_cnt;
+                       else
+                               remains = 1;
+               } else {
                        remains = sl->tx_lim - sl->tx_cnt;
-               else
-                       remains = 1;
-#else
-               remains = sl->tx_lim - sl->tx_cnt;
-#endif
+               }
 
                res = tty->ops->write(tty, sl->tx_buff + sl->tx_cnt, remains);
                if (res < 0)
@@ -1077,8 +1086,7 @@ error_in_write:
 
 }
 
-#ifdef BREAK_BY_BAUD
-static int sllin_send_break(struct sllin *sl)
+static int sllin_send_break_by_baud(struct sllin *sl)
 {
        struct tty_struct *tty = sl->tty;
        unsigned long break_baud;
@@ -1087,7 +1095,7 @@ static int sllin_send_break(struct sllin *sl)
        break_baud = ((sl->lin_baud * 2) / 3);
        sltty_change_speed(tty, break_baud);
 
-       if (tty != NULL && tty->ops != NULL && tty->ops->flush_buffer != NULL) {
+       if (tty->ops->flush_buffer != NULL) {
                tty->ops->flush_buffer(tty);
        } else {
                netdev_dbg(sl->dev, "flush_buffer is not implemented.\n");
@@ -1105,9 +1113,8 @@ static int sllin_send_break(struct sllin *sl)
 
        return 0;
 }
-#else /* BREAK_BY_BAUD */
 
-static int sllin_send_break(struct sllin *sl)
+static int sllin_send_break_by_usleep(struct sllin *sl)
 {
        struct tty_struct *tty = sl->tty;
        int retval;
@@ -1150,8 +1157,14 @@ static int sllin_send_break(struct sllin *sl)
 
        return 0;
 }
-#endif /* BREAK_BY_BAUD */
 
+static int sllin_send_break(struct sllin *sl)
+{
+       if (sl->lin_break_by_baud)
+               return sllin_send_break_by_baud(sl);
+       else
+               return sllin_send_break_by_usleep(sl);
+}
 
 static enum hrtimer_restart sllin_rx_timeout_handler(struct hrtimer *hrtimer)
 {
@@ -1331,12 +1344,12 @@ static int sllin_kwthread(void *ptr)
                        break;
 
                case SLSTATE_BREAK_SENT:
-#ifdef BREAK_BY_BAUD
-                       if (sl->rx_cnt <= SLLIN_BUFF_BREAK)
-                               continue;
+                       if (sl->lin_break_by_baud) {
+                               if (sl->rx_cnt <= SLLIN_BUFF_BREAK)
+                                       continue;
 
-                       res = sltty_change_speed(tty, sl->lin_baud);
-#endif
+                               sltty_change_speed(tty, sl->lin_baud);
+                       }
 
                        sl->lin_state = SLSTATE_ID_SENT;
                        sllin_send_tx_buff(sl);
@@ -1636,6 +1649,13 @@ static int sllin_open(struct tty_struct *tty)
                sl->lin_baud = (baudrate == 0) ? LIN_DEFAULT_BAUDRATE : baudrate;
                pr_debug("sllin: Baudrate set to %u\n", sl->lin_baud);
 
+               sl->lin_break_by_baud = break_by_baud;
+
+               if (tty->ops->break_ctl == NULL && !sl->lin_break_by_baud) {
+                       sl->lin_break_by_baud = true;
+                       pr_notice ("sllin: break_ctl, switching to break_by_baud\n");
+               }
+
                sl->lin_state = SLSTATE_IDLE;
 
                hrtimer_init(&sl->rx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
@@ -1784,11 +1804,10 @@ static int __init sllin_init(void)
                kfree(sllin_devs);
        }
 
-#ifdef BREAK_BY_BAUD
-       pr_debug("sllin: Break is generated by baud-rate change.");
-#else
-       pr_debug("sllin: Break is generated manually with tiny sleep.");
-#endif
+       if (break_by_baud)
+               pr_debug("sllin: Break is generated by baud-rate change.");
+       else
+               pr_debug("sllin: Break is generated manually with tiny sleep.");
 
        return status;
 }