char resp_len_known; /* Length of the response is known */
char header_received;/* In Slave mode, set when header was already
received */
+ char rx_len_unknown; /* We are not sure how much data will be sent to us --
+ we just guess the length */
unsigned long flags; /* Flag values/ mode etc */
#define SLF_INUSE 0 /* Channel in use */
*/
static void sll_bump(struct sllin *sl)
{
+ int len = sl->rx_cnt - SLLIN_BUFF_DATA - 1; /* without checksum */
+ len = (len < 0) ? 0 : len;
+
sllin_send_canfr(sl, sl->rx_buff[SLLIN_BUFF_ID] & LIN_ID_MASK,
- sl->rx_buff + SLLIN_BUFF_DATA,
- sl->rx_cnt - SLLIN_BUFF_DATA - 1); /* without checksum */
+ sl->rx_buff + SLLIN_BUFF_DATA, len);
}
static void sll_send_rtr(struct sllin *sl)
/******************************************
Routines looking at TTY side.
******************************************/
+#define SLL_RESPONSE_RECEIVED ((sl->header_received == true) && \
+ ((sl->rx_cnt >= sl->rx_expect) || \
+ ((sl->rx_len_unknown == true) && (count == 0))))
+
+#define SLL_HEADER_RECEIVED ((sl->header_received == false) && \
+ (sl->rx_cnt >= (SLLIN_BUFF_ID + 1)))
static void sllin_receive_buf(struct tty_struct *tty,
const unsigned char *cp, char *fp, int count)
{
struct sllin *sl = (struct sllin *) tty->disc_data;
-
pr_debug("sllin: sllin_receive_buf invoked, count = %u\n", count);
if (!sl || sl->magic != SLLIN_MAGIC || !netif_running(sl->dev))
/* Read the characters out of the buffer */
while (count--) {
if (fp && *fp++) {
- if (sl->rx_cnt > SLLIN_BUFF_BREAK) {
- set_bit(SLF_ERROR, &sl->flags);
-
- pr_debug("sllin: sllin_receive_buf char 0x%02x ignored "
- "due marker 0x%02x, flags 0x%lx\n",
- *cp, *(fp-1), sl->flags);
-
- if (sl->lin_master == true) {
- wake_up(&sl->kwt_wq);
- return;
- } else {
- sl->rx_cnt = 0;
- sl->rx_expect = SLLIN_BUFF_ID + 1;
- sl->header_received = false;
- return;
- }
+ pr_debug("sllin: sllin_receive_buf char 0x%02x ignored "
+ "due marker 0x%02x, flags 0x%lx\n",
+ *cp, *(fp-1), sl->flags);
- cp++;
- continue;
+ if (sl->lin_master == true) { /* Report error */
+ set_bit(SLF_ERROR, &sl->flags);
+ wake_up(&sl->kwt_wq);
+ return;
+ } else { /* Received Break */
+ sl->rx_cnt = 0;
+ sl->rx_expect = SLLIN_BUFF_ID + 1;
+ sl->rx_len_unknown = false; /* We do know exact length of the header */
+ sl->header_received = false;
}
}
- if (sl->rx_cnt < SLLIN_BUFF_LEN) {
#ifndef BREAK_BY_BAUD
- /* We didn't receive Break character -- fake it! */
- if ((sl->rx_cnt == SLLIN_BUFF_BREAK) && (*cp == 0x55)) {
- pr_debug("sllin: LIN_RX[%d]: 0x00\n", sl->rx_cnt);
- sl->rx_buff[sl->rx_cnt++] = 0x00;
- }
+ /* We didn't receive Break character -- fake it! */
+ if ((sl->rx_cnt == SLLIN_BUFF_BREAK) && (*cp == 0x55)) {
+ pr_debug("sllin: LIN_RX[%d]: 0x00\n", sl->rx_cnt);
+ sl->rx_buff[sl->rx_cnt++] = 0x00;
+ }
#endif
+ if (sl->rx_cnt < SLLIN_BUFF_LEN) {
pr_debug("sllin: LIN_RX[%d]: 0x%02x\n", sl->rx_cnt, *cp);
sl->rx_buff[sl->rx_cnt++] = *cp++;
}
- }
- if (sl->lin_master == true) {
- if (sl->rx_cnt >= sl->rx_expect) { /* Probably whole frame was received */
- set_bit(SLF_RXEVENT, &sl->flags);
- wake_up(&sl->kwt_wq);
- pr_debug("sllin: sllin_receive_buf count %d, wakeup\n", sl->rx_cnt);
- } else {
- pr_debug("sllin: sllin_receive_buf count %d, waiting\n", sl->rx_cnt);
- }
- } else { /* LIN slave */
- int lin_id;
- struct sllin_conf_entry *sce;
-
- /* Received whole header */
- if ((sl->rx_cnt >= (SLLIN_BUFF_ID + 1)) &&
- (sl->header_received == false))
- {
- lin_id = sl->rx_buff[SLLIN_BUFF_ID] & LIN_ID_MASK;
- sce = &sl->linfr_cache[lin_id];
-
- /* Is the length of data set in frame cache? */
- if (sce->frame_fl & LIN_LOC_SLAVE_CACHE)
- sl->rx_expect += sce->dlc;
- else
- sl->rx_expect += 2; /* 1 data byte + checksum */
-
- sl->header_received = true;
- sll_send_rtr(sl);
- }
+ if (sl->lin_master == true) {
+ if (SLL_RESPONSE_RECEIVED) {
+ set_bit(SLF_RXEVENT, &sl->flags);
+ wake_up(&sl->kwt_wq);
+ pr_debug("sllin: sllin_receive_buf count %d, wakeup\n", sl->rx_cnt);
+ } else {
+ pr_debug("sllin: sllin_receive_buf count %d, waiting\n", sl->rx_cnt);
+ }
+ } else { /* LIN slave */
+ int lin_id;
+ struct sllin_conf_entry *sce;
+
+ pr_debug("sllin: rx_cnt = %u; header_received = %u\n",
+ sl->rx_cnt, sl->header_received);
+
+ if (SLL_HEADER_RECEIVED) {
+ lin_id = sl->rx_buff[SLLIN_BUFF_ID] & LIN_ID_MASK;
+ sce = &sl->linfr_cache[lin_id];
- /* Probably whole frame was received */
- if ((sl->rx_cnt >= sl->rx_expect) && (sl->rx_cnt > SLLIN_BUFF_DATA)) {
- sll_bump(sl);
- pr_debug("sllin: Received LIN header & LIN response. "
- "rx_cnt = %u, rx_expect = %u\n", sl->rx_cnt,
- sl->rx_expect);
- sl->rx_cnt = 0;
- sl->rx_expect = SLLIN_BUFF_ID + 1;
- sl->header_received = false;
+ /* Is the length of data set in frame cache? */
+ if (sce->frame_fl & LIN_LOC_SLAVE_CACHE) {
+ sl->rx_expect += sce->dlc;
+ sl->rx_len_unknown = false;
+ } else {
+ sl->rx_expect += SLLIN_DATA_MAX + 1; /* + checksum */
+ sl->rx_len_unknown = true;
+ }
+
+ sl->header_received = true;
+ sll_send_rtr(sl);
+ continue;
+ }
+
+ if (SLL_RESPONSE_RECEIVED) {
+ sll_bump(sl);
+ pr_debug("sllin: Received LIN header & LIN response. "
+ "rx_cnt = %u, rx_expect = %u\n", sl->rx_cnt,
+ sl->rx_expect);
+
+ /* Prepare for reception of new header */
+ sl->rx_cnt = 0;
+ sl->rx_expect = SLLIN_BUFF_ID + 1;
+ sl->rx_len_unknown = false; /* We do know exact length of the header */
+ sl->header_received = false;
+ }
}
}
}