summaryrefslogtreecommitdiffstats
path: root/src/target/firmware/comm/sercomm.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2010-03-27 12:18:26 +0800
committerHarald Welte <laforge@gnumonks.org>2010-03-27 12:24:26 +0800
commitbbe405b7fe3251978be30e81e068a9ad7376c92d (patch)
tree27da13c2fe92c0c2b20a5ab124e758d67d313a52 /src/target/firmware/comm/sercomm.c
parent131e3320d9f4e70615d5104e361126ac16c45da9 (diff)
sercomm: Fix ESCAPE'd character at end of buffer
If we're transmitting a to-be-escaped character as the last byte of the buffer, the code generated the sequence ESCAPE FLAG rather than ESCAPE last_byte FLAG. This fixes the bug.
Diffstat (limited to 'src/target/firmware/comm/sercomm.c')
-rw-r--r--src/target/firmware/comm/sercomm.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/src/target/firmware/comm/sercomm.c b/src/target/firmware/comm/sercomm.c
index d616e31c..2b3586e8 100644
--- a/src/target/firmware/comm/sercomm.c
+++ b/src/target/firmware/comm/sercomm.c
@@ -62,6 +62,7 @@ static struct {
struct {
struct llist_head dlci_queues[_SC_DLCI_MAX];
struct msgb *msg;
+ enum rx_state state;
uint8_t *next_char;
} tx;
@@ -153,14 +154,12 @@ int sercomm_drv_pull(uint8_t *ch)
}
}
- /* escaping for the two control octets */
- if (*sercomm.tx.next_char == HDLC_FLAG ||
- *sercomm.tx.next_char == HDLC_ESCAPE) {
- /* send an escape octet */
- *ch = HDLC_ESCAPE;
- /* invert bit 5 of the next octet to be sent */
- *sercomm.tx.next_char ^= (1 << 5);
- } else if (sercomm.tx.next_char == sercomm.tx.msg->tail) {
+ if (sercomm.tx.state == RX_ST_ESCAPE) {
+ /* we've already transmitted the ESCAPE octet,
+ * we now need to trnsmit the escaped data */
+ *ch = *sercomm.tx.next_char++;
+ sercomm.tx.state = RX_ST_DATA;
+ } else if (sercomm.tx.next_char >= sercomm.tx.msg->tail) {
/* last character has already been transmitted,
* send end-of-message octet */
*ch = HDLC_FLAG;
@@ -168,6 +167,14 @@ int sercomm_drv_pull(uint8_t *ch)
msgb_free(sercomm.tx.msg);
sercomm.tx.msg = NULL;
sercomm.tx.next_char = NULL;
+ /* escaping for the two control octets */
+ } else if (*sercomm.tx.next_char == HDLC_FLAG ||
+ *sercomm.tx.next_char == HDLC_ESCAPE) {
+ /* send an escape octet */
+ *ch = HDLC_ESCAPE;
+ /* invert bit 5 of the next octet to be sent */
+ *sercomm.tx.next_char ^= (1 << 5);
+ sercomm.tx.state = RX_ST_ESCAPE;
} else {
/* standard case, simply send next octet */
*ch = *sercomm.tx.next_char++;