One way how to generate Break is by manually controlling break signal
while sleeping with timer.
Another way is to slower baud-rate of an UART and send 0x00.
MODULE_AUTHOR("Oliver Hartkopp <socketcan@hartkopp.net>");
#define SLLIN_MAGIC 0x53CA
MODULE_AUTHOR("Oliver Hartkopp <socketcan@hartkopp.net>");
#define SLLIN_MAGIC 0x53CA
+// #define BREAK_BY_BAUD
static int maxdev = 10; /* MAX number of SLLIN channels;
This can be overridden with
static int maxdev = 10; /* MAX number of SLLIN channels;
This can be overridden with
if (tty->ops->set_termios)
tty->ops->set_termios(tty, &old_termios);
if (tty->ops->set_termios)
tty->ops->set_termios(tty, &old_termios);
- //priv->io.speed = speed;
mutex_unlock(&tty->termios_mutex);
return 0;
mutex_unlock(&tty->termios_mutex);
return 0;
if (fp && *fp++) {
if (!test_and_set_bit(SLF_ERROR, &sl->flags))
sl->dev->stats.rx_errors++;
if (fp && *fp++) {
if (!test_and_set_bit(SLF_ERROR, &sl->flags))
sl->dev->stats.rx_errors++;
- printk(KERN_INFO "sllin_receive_buf char 0x%02x ignored due marker 0x%02x, flags 0x%lx\n",
+ printk(KERN_INFO "sllin_receive_buf char 0x%02x ignored "
+ "due marker 0x%02x, flags 0x%lx\n",
*cp, *(fp-1), sl->flags);
cp++;
continue;
}
*cp, *(fp-1), sl->flags);
cp++;
continue;
}
- if (sl->rx_cnt < SLLIN_BUFF_LEN) {
+ if (sl->rx_cnt < SLLIN_BUFF_LEN) {
+#ifndef BREAK_BY_BAUD
+ /* We didn't receive Break character */
+ if ((sl->rx_cnt == SLLIN_BUFF_BREAK) && (*cp == 0x55)) {
+ sl->rx_buff[sl->rx_cnt++] = 0x00;
+ }
+#endif
+ printk(KERN_INFO "LIN_RX[%d]: 0x%02x\n", sl->rx_cnt, *cp);
sl->rx_buff[sl->rx_cnt++] = *cp++;
}
}
sl->rx_buff[sl->rx_cnt++] = *cp++;
}
}
- if(sl->rx_cnt >= sl->rx_expect) {
+ if (sl->rx_cnt >= sl->rx_expect) {
set_bit(SLF_RXEVENT, &sl->flags);
wake_up(&sl->kwt_wq);
printk(KERN_INFO "sllin_receive_buf count %d, wakeup\n", sl->rx_cnt);
set_bit(SLF_RXEVENT, &sl->flags);
wake_up(&sl->kwt_wq);
printk(KERN_INFO "sllin_receive_buf count %d, wakeup\n", sl->rx_cnt);
if (sl->lin_state != SLSTATE_BREAK_SENT)
remains = sl->tx_lim - sl->tx_cnt;
else
remains = 1;
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;
+#endif
res = tty->ops->write(tty, sl->tx_buff + sl->tx_cnt, remains);
if (res < 0)
res = tty->ops->write(tty, sl->tx_buff + sl->tx_cnt, remains);
if (res < 0)
int sllin_send_break(struct sllin *sl)
{
struct tty_struct *tty = sl->tty;
int sllin_send_break(struct sllin *sl)
{
struct tty_struct *tty = sl->tty;
- unsigned long break_baud = sl->lin_baud;
- spinlock_t mr_lock = SPIN_LOCK_UNLOCKED;
- unsigned long flags;
- int retval;
+ unsigned long break_baud;
+ int res;
-#if 0
- break_baud = ((break_baud * 2) / 3);
+ break_baud = ((sl->lin_baud * 2) / 3);
sltty_change_speed(tty, break_baud);
sltty_change_speed(tty, break_baud);
+ tty->ops->flush_buffer(tty);
+ sl->rx_cnt = SLLIN_BUFF_BREAK;
+
sl->rx_expect = SLLIN_BUFF_BREAK + 1;
sl->lin_state = SLSTATE_BREAK_SENT;
sl->rx_expect = SLLIN_BUFF_BREAK + 1;
sl->lin_state = SLSTATE_BREAK_SENT;
- retval = sllin_send_tx_buff(sl);
- if (retval < 0) {
+ res = sllin_send_tx_buff(sl);
+ if (res < 0) {
sl->lin_state = SLSTATE_IDLE;
return res;
}
sl->lin_state = SLSTATE_IDLE;
return res;
}
+
+ return 0;
+}
+#else /* BREAK_BY_BAUD */
+
+int sllin_send_break(struct sllin *sl)
+{
+ struct tty_struct *tty = sl->tty;
+ unsigned long break_baud;
+ unsigned long flags;
+ int retval;
+
+ sl->rx_cnt = SLLIN_BUFF_BREAK;
+ sl->rx_expect = SLLIN_BUFF_BREAK + 1;
+ sl->lin_state = SLSTATE_BREAK_SENT;
+
/* Do the break ourselves; Inspired by
http://lxr.linux.no/#linux+v3.1.2/drivers/tty/tty_io.c#L2452 */
/* Do the break ourselves; Inspired by
http://lxr.linux.no/#linux+v3.1.2/drivers/tty/tty_io.c#L2452 */
-
- spin_lock_irqsave(&mr_lock, flags);
retval = tty->ops->break_ctl(tty, -1);
if (retval)
retval = tty->ops->break_ctl(tty, -1);
if (retval)
- udelay(712);
- //usleep_range(650, 750);
+ //udelay(712);
+ usleep_range(650, 750);
retval = tty->ops->break_ctl(tty, 0);
retval = tty->ops->break_ctl(tty, 0);
-out:
- spin_unlock_irqrestore(&mr_lock, flags);
+ usleep_range(50, 100);
+
+ tty->ops->flush_buffer(tty);
+
+ sl->tx_cnt = SLLIN_BUFF_SYNC;
+ set_bit(SLF_RXEVENT, &sl->flags);
+ wake_up(&sl->kwt_wq);
- sl->lin_state = SLSTATE_BREAK_SENT;
-#endif
- //return retval;
+#endif /* BREAK_BY_BAUD */
/*****************************************
* sllin_kwthread - kernel worker thread
/*****************************************
* sllin_kwthread - kernel worker thread
{
struct sllin *sl = (struct sllin *)ptr;
struct tty_struct *tty = sl->tty;
{
struct sllin *sl = (struct sllin *)ptr;
struct tty_struct *tty = sl->tty;
+ struct sched_param schparam = { .sched_priority = 40 };
+ unsigned char buff[8] = {0x2, 0x3, 0x4, 0x5};
printk(KERN_INFO "sllin: sllin_kwthread started.\n");
printk(KERN_INFO "sllin: sllin_kwthread started.\n");
+ sched_setscheduler(current, SCHED_FIFO, &schparam);
clear_bit(SLF_ERROR, &sl->flags);
clear_bit(SLF_ERROR, &sl->flags);
sltty_change_speed(tty, sl->lin_baud);
sltty_change_speed(tty, sl->lin_baud);
- sllin_setup_msg(sl, 0, 0x33, NULL, 0);
- sl->id_to_send = 1;
+ //sllin_setup_msg(sl, 0, 0x01, NULL, 0);
+ sllin_setup_msg(sl, 0, 0x02, buff, 4);
+ sl->id_to_send = true;
while (!kthread_should_stop()) {
while (!kthread_should_stop()) {
if ((sl->lin_state == SLSTATE_IDLE) && sl->lin_master &&
sl->id_to_send) {
if ((sl->lin_state == SLSTATE_IDLE) && sl->lin_master &&
sl->id_to_send) {
- if(sllin_send_break(sl)<0) {
+ if(sllin_send_break(sl) < 0) {
}
wait_event_killable(sl->kwt_wq, kthread_should_stop() ||
}
wait_event_killable(sl->kwt_wq, kthread_should_stop() ||
case SLSTATE_BREAK_SENT:
if (sl->rx_cnt <= SLLIN_BUFF_BREAK)
continue;
case SLSTATE_BREAK_SENT:
if (sl->rx_cnt <= SLLIN_BUFF_BREAK)
continue;
-
- //res = sltty_change_speed(tty, sl->lin_baud);
-
- sllin_send_tx_buff(sl);
+#ifdef BREAK_BY_BAUD
+ res = sltty_change_speed(tty, sl->lin_baud);
+#endif
sl->lin_state = SLSTATE_ID_SENT;
sl->lin_state = SLSTATE_ID_SENT;
+ sllin_send_tx_buff(sl);
+ sl->id_to_send = false;
sl->lin_state = SLSTATE_IDLE;
break;
}
sl->lin_state = SLSTATE_IDLE;
break;
}
/* Perform the low-level SLLIN initialization. */
sl->rx_cnt = 0;
sl->rx_expect = 0;
/* Perform the low-level SLLIN initialization. */
sl->rx_cnt = 0;
sl->rx_expect = 0;
sl->tx_cnt = 0;
sl->tx_lim = 0;
sl->tx_cnt = 0;
sl->tx_lim = 0;