>From 3a0c02807079b86221503abc8ca010eab109cdd0 Mon Sep 17 00:00:00 2001 From: Ken Mills <[email protected]> Date: Tue, 2 Nov 2010 11:09:06 -0700 Subject: [PATCH 2/2] Bug fixes for the 27.010 mux driver.
This patch addresses Alan Cox's comments. 1. Handle modem control message properly. 2. fix FCS processing on received frame. 3. all printk's changed to pr_debug Signed-off-by: Ken Mills <[email protected]> --- drivers/char/n_gsm.c | 170 +++++++++++++++++++++++++++++++------------------ 1 files changed, 107 insertions(+), 63 deletions(-) diff --git a/drivers/char/n_gsm.c b/drivers/char/n_gsm.c index 79d8464..2d2f681 100644 --- a/drivers/char/n_gsm.c +++ b/drivers/char/n_gsm.c @@ -185,6 +185,9 @@ struct gsm_mux { #define GSM_DATA 5 #define GSM_FCS 6 #define GSM_OVERRUN 7 +#define GSM_LEN0 8 +#define GSM_LEN1 9 +#define GSM_SSOF 10 unsigned int len; unsigned int address; unsigned int count; @@ -192,6 +195,7 @@ struct gsm_mux { int encoding; u8 control; u8 fcs; + u8 received_fcs; u8 *txframe; /* TX framing buffer */ /* Methods for the receiver side */ @@ -430,62 +434,63 @@ static void gsm_print_packet(const char *hdr, int addr, int cr, if (!(debug & 1)) return; - printk(KERN_INFO "%s %d) %c: ", hdr, addr, "RC"[cr]); + pr_debug("%s %d) %c: ", hdr, addr, "RC"[cr]); switch (control & ~PF) { case SABM: - printk(KERN_CONT "SABM"); + pr_debug("SABM"); break; case UA: - printk(KERN_CONT "UA"); + pr_debug("UA"); break; case DISC: - printk(KERN_CONT "DISC"); + pr_debug("DISC"); break; case DM: - printk(KERN_CONT "DM"); + pr_debug("DM"); break; case UI: - printk(KERN_CONT "UI"); + pr_debug("UI"); break; case UIH: - printk(KERN_CONT "UIH"); + pr_debug("UIH"); break; default: if (!(control & 0x01)) { - printk(KERN_CONT "I N(S)%d N(R)%d", + pr_debug("I N(S)%d N(R)%d", (control & 0x0E) >> 1, (control & 0xE) >> 5); } else switch (control & 0x0F) { case RR: - printk("RR(%d)", (control & 0xE0) >> 5); + pr_debug("RR(%d)", (control & 0xE0) >> 5); break; case RNR: - printk("RNR(%d)", (control & 0xE0) >> 5); + pr_debug("RNR(%d)", (control & 0xE0) >> 5); break; case REJ: - printk("REJ(%d)", (control & 0xE0) >> 5); + pr_debug("REJ(%d)", (control & 0xE0) >> 5); break; default: - printk(KERN_CONT "[%02X]", control); + pr_debug("[%02X]", control); } } if (control & PF) - printk(KERN_CONT "(P)"); + pr_debug("(P)"); else - printk(KERN_CONT "(F)"); + pr_debug("(F)"); if (dlen) { int ct = 0; while (dlen--) { if (ct % 8 == 0) - printk(KERN_CONT "\n "); - printk(KERN_CONT "%02X ", *data++); + pr_debug("\n "); + pr_debug("%02X %c ", *data, *data); + data++; ct++; } } - printk(KERN_CONT "\n"); + pr_debug("\n"); } @@ -525,10 +530,11 @@ static void hex_packet(const unsigned char *p, int len) int i; for (i = 0; i < len; i++) { if (i && (i % 16) == 0) - printk(KERN_INFO "\n"); - printk(KERN_INFO "%02X ", *p++); + pr_debug("\n"); + pr_debug("%02X %c ", *p, *p); + p++; } - printk("\n"); + pr_debug("\n"); } /** @@ -678,7 +684,7 @@ static void gsm_data_kick(struct gsm_mux *gsm) } if (debug & 4) { - printk(KERN_INFO "gsm_data_kick:\n"); + pr_debug("gsm_data_kick:\n"); hex_packet(gsm->txframe, len); } @@ -718,8 +724,8 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg) if (msg->len < 128) *--dp = (msg->len << 1) | EA; else { - *--dp = (msg->len >> 6) | EA; - *--dp = (msg->len & 127) << 1; + *--dp = ((msg->len & 127) << 1) | EA; + *--dp = (msg->len >> 6) & 0xfe; } } @@ -987,10 +993,22 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, u8 *data, */ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, - u32 modem) + u32 modem, int clen) { int mlines = 0; - u8 brk = modem >> 6; + u8 brk = 0; + + /* The modem status command can either contain one octet (v.24 signals) + or two octets (v.24 signals + break signals). The length field will + either be 2 or 3 respectively. This is specified in section + 5.4.6.3.7 of the 27.010 mux spec. */ + + if (clen == 2) + modem = modem & 0x7f; + else { + brk = modem & 0x7f; + modem = (modem >> 7) & 0x7f; + }; /* Flow control/ready to communicate */ if (modem & MDM_FC) { @@ -1057,14 +1075,13 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen) if (addr == 0 || addr >= NUM_DLCI || gsm->dlci[addr] == NULL) return; dlci = gsm->dlci[addr]; - while (gsm_read_ea(&modem, *dp++) == 0) { len--; if (len == 0) return; } tty = tty_port_tty_get(&dlci->port); - gsm_process_modem(tty, dlci, modem); + gsm_process_modem(tty, dlci, modem, clen); if (tty) { tty_wakeup(tty); tty_kref_put(tty); @@ -1361,7 +1378,7 @@ static void gsm_dlci_close(struct gsm_dlci *dlci) { del_timer(&dlci->t1); if (debug & 8) - printk(KERN_INFO "DLCI %d goes closed.\n", dlci->addr); + pr_debug("DLCI %d goes closed.\n", dlci->addr); dlci->state = DLCI_CLOSED; if (dlci->addr != 0) { struct tty_struct *tty = tty_port_tty_get(&dlci->port); @@ -1392,7 +1409,7 @@ static void gsm_dlci_open(struct gsm_dlci *dlci) /* This will let a tty open continue */ dlci->state = DLCI_OPEN; if (debug & 8) - printk(KERN_DEBUG "DLCI %d goes open.\n", dlci->addr); + pr_debug("DLCI %d goes open.\n", dlci->addr); wake_up(&dlci->gsm->event); } @@ -1486,15 +1503,17 @@ static void gsm_dlci_begin_close(struct gsm_dlci *dlci) * open we shovel the bits down it, if not we drop them. */ -static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int len) +static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int clen) { /* krefs .. */ struct tty_port *port = &dlci->port; struct tty_struct *tty = tty_port_tty_get(port); unsigned int modem = 0; + int len = clen; if (debug & 16) - printk(KERN_DEBUG "%d bytes for tty %p\n", len, tty); + pr_debug("gsm_dlci_data: %d bytes for tty %p\n", len, tty); + if (tty) { switch (dlci->adaption) { /* Unsupported types */ @@ -1511,7 +1530,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int len) if (len == 0) return; } - gsm_process_modem(tty, dlci, modem); + gsm_process_modem(tty, dlci, modem, clen); /* Line state will go via DLCI 0 controls only */ case 1: default: @@ -1625,7 +1644,6 @@ static void gsm_dlci_free(struct gsm_dlci *dlci) kfree(dlci); } - /* * LAPBish link layer logic */ @@ -1650,10 +1668,12 @@ static void gsm_queue(struct gsm_mux *gsm) if ((gsm->control & ~PF) == UI) gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len); + /* generate final CRC with received FCS */ + gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs); if (gsm->fcs != GOOD_FCS) { gsm->bad_fcs++; if (debug & 4) - printk(KERN_INFO "BAD FCS %02x\n", gsm->fcs); + pr_debug("BAD FCS %02x\n", gsm->fcs); return; } address = gsm->address >> 1; @@ -1748,6 +1768,8 @@ invalid: static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) { + unsigned int len; + switch (gsm->state) { case GSM_SEARCH: /* SOF marker */ if (c == GSM0_SOF) { @@ -1756,8 +1778,8 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) gsm->len = 0; gsm->fcs = INIT_FCS; } - break; /* Address EA */ - case GSM_ADDRESS: + break; + case GSM_ADDRESS: /* Address EA */ gsm->fcs = gsm_fcs_add(gsm->fcs, c); if (gsm_read_ea(&gsm->address, c)) gsm->state = GSM_CONTROL; @@ -1765,9 +1787,9 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) case GSM_CONTROL: /* Control Byte */ gsm->fcs = gsm_fcs_add(gsm->fcs, c); gsm->control = c; - gsm->state = GSM_LEN; + gsm->state = GSM_LEN0; break; - case GSM_LEN: /* Length EA */ + case GSM_LEN0: /* Length EA */ gsm->fcs = gsm_fcs_add(gsm->fcs, c); if (gsm_read_ea(&gsm->len, c)) { if (gsm->len > gsm->mru) { @@ -1776,8 +1798,28 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) break; } gsm->count = 0; - gsm->state = GSM_DATA; + if (!gsm->len) + gsm->state = GSM_FCS; + else + gsm->state = GSM_DATA; + break; } + gsm->state = GSM_LEN1; + break; + case GSM_LEN1: + gsm->fcs = gsm_fcs_add(gsm->fcs, c); + len = c; + gsm->len |= len << 7; + if (gsm->len > gsm->mru) { + gsm->bad_size++; + gsm->state = GSM_SEARCH; + break; + } + gsm->count = 0; + if (!gsm->len) + gsm->state = GSM_FCS; + else + gsm->state = GSM_DATA; break; case GSM_DATA: /* Data */ gsm->buf[gsm->count++] = c; @@ -1785,16 +1827,25 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) gsm->state = GSM_FCS; break; case GSM_FCS: /* FCS follows the packet */ - gsm->fcs = c; + gsm->received_fcs = c; + if (c == GSM0_SOF) { + gsm->state = GSM_SEARCH; + break; + } gsm_queue(gsm); - /* And then back for the next frame */ - gsm->state = GSM_SEARCH; + gsm->state = GSM_SSOF; + break; + case GSM_SSOF: + if (c == GSM0_SOF) { + gsm->state = GSM_SEARCH; + break; + } break; } } /** - * gsm0_receive - perform processing for non-transparency + * gsm1_receive - perform processing for non-transparency * @gsm: gsm data for this ldisc instance * @c: character * @@ -2034,9 +2085,6 @@ struct gsm_mux *gsm_alloc_mux(void) } EXPORT_SYMBOL_GPL(gsm_alloc_mux); - - - /** * gsmld_output - write to link * @gsm: our mux @@ -2053,10 +2101,8 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len) set_bit(TTY_DO_WRITE_WAKEUP, &gsm->tty->flags); return -ENOSPC; } - if (debug & 4) { - printk(KERN_INFO "-->%d bytes out\n", len); + if (debug & 4) hex_packet(data, len); - } gsm->tty->ops->write(gsm->tty, data, len); return len; } @@ -2110,10 +2156,8 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, char buf[64]; char flags; - if (debug & 4) { - printk(KERN_INFO "Inbytes %dd\n", count); + if (debug & 4) hex_packet(cp, count); - } for (i = count, dp = cp, f = fp; i; i--, dp++) { flags = *f++; @@ -2128,7 +2172,7 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, gsm->error(gsm, *dp, flags); break; default: - printk(KERN_ERR "%s: unknown flag %d\n", + pr_debug("%s: unknown flag %d\n", tty_name(tty, buf), flags); break; } @@ -2377,6 +2421,7 @@ static int gsmld_config(struct tty_struct *tty, struct gsm_mux *gsm, gsm->mru = c->mru; gsm->encoding = c->encapsulation; gsm->adaption = c->adaption; + gsm->n2 = c->n2; if (c->i == 1) gsm->ftype = UIH; @@ -2417,7 +2462,7 @@ static int gsmld_ioctl(struct tty_struct *tty, struct file *file, c.i = 1; else c.i = 2; - printk(KERN_INFO "Ftype %d i %d\n", gsm->ftype, c.i); + pr_debug("Ftype %d i %d\n", gsm->ftype, c.i); c.mru = gsm->mru; c.mtu = gsm->mtu; c.k = 0; @@ -2711,15 +2756,15 @@ static int __init gsm_init(void) /* Fill in our line protocol discipline, and register it */ int status = tty_register_ldisc(N_GSM0710, &tty_ldisc_packet); if (status != 0) { - printk(KERN_ERR - "n_gsm: can't register line discipline (err = %d)\n", status); + pr_debug("n_gsm: can't register line discipline (err = %d)\n", + status); return status; } gsm_tty_driver = alloc_tty_driver(256); if (!gsm_tty_driver) { tty_unregister_ldisc(N_GSM0710); - printk(KERN_ERR "gsm_init: tty allocation failed.\n"); + pr_debug("gsm_init: tty allocation failed.\n"); return -EINVAL; } gsm_tty_driver->owner = THIS_MODULE; @@ -2741,10 +2786,10 @@ static int __init gsm_init(void) if (tty_register_driver(gsm_tty_driver)) { put_tty_driver(gsm_tty_driver); tty_unregister_ldisc(N_GSM0710); - printk(KERN_ERR "gsm_init: tty registration failed.\n"); + pr_debug("gsm_init: tty registration failed.\n"); return -EBUSY; } - printk(KERN_INFO "gsm_init: loaded as %d,%d.\n", + pr_debug("gsm_init: loaded as %d,%d.\n", gsm_tty_driver->major, gsm_tty_driver->minor_start); return 0; } @@ -2753,12 +2798,11 @@ static void __exit gsm_exit(void) { int status = tty_unregister_ldisc(N_GSM0710); if (status != 0) - printk(KERN_ERR - "n_gsm: can't unregister line discipline (err = %d)\n", - status); + pr_debug("n_gsm: can't unregister line discipline (err = %d)\n" + , status); tty_unregister_driver(gsm_tty_driver); put_tty_driver(gsm_tty_driver); - printk(KERN_INFO "gsm_init: unloaded.\n"); + pr_debug("gsm_init: unloaded.\n"); } module_init(gsm_init); -- 1.7.0.4
From 3a0c02807079b86221503abc8ca010eab109cdd0 Mon Sep 17 00:00:00 2001 From: Ken Mills <[email protected]> Date: Tue, 2 Nov 2010 11:09:06 -0700 Subject: [PATCH 2/2] Bug fixes for the 27.010 mux driver. 1. Handle modem control message properly. 2. fix FCS processing on received frame. 3. all printk's changed to pr_debug Signed-off-by: Ken Mills <[email protected]> --- drivers/char/n_gsm.c | 170 +++++++++++++++++++++++++++++++------------------ 1 files changed, 107 insertions(+), 63 deletions(-) diff --git a/drivers/char/n_gsm.c b/drivers/char/n_gsm.c index 79d8464..2d2f681 100644 --- a/drivers/char/n_gsm.c +++ b/drivers/char/n_gsm.c @@ -185,6 +185,9 @@ struct gsm_mux { #define GSM_DATA 5 #define GSM_FCS 6 #define GSM_OVERRUN 7 +#define GSM_LEN0 8 +#define GSM_LEN1 9 +#define GSM_SSOF 10 unsigned int len; unsigned int address; unsigned int count; @@ -192,6 +195,7 @@ struct gsm_mux { int encoding; u8 control; u8 fcs; + u8 received_fcs; u8 *txframe; /* TX framing buffer */ /* Methods for the receiver side */ @@ -430,62 +434,63 @@ static void gsm_print_packet(const char *hdr, int addr, int cr, if (!(debug & 1)) return; - printk(KERN_INFO "%s %d) %c: ", hdr, addr, "RC"[cr]); + pr_debug("%s %d) %c: ", hdr, addr, "RC"[cr]); switch (control & ~PF) { case SABM: - printk(KERN_CONT "SABM"); + pr_debug("SABM"); break; case UA: - printk(KERN_CONT "UA"); + pr_debug("UA"); break; case DISC: - printk(KERN_CONT "DISC"); + pr_debug("DISC"); break; case DM: - printk(KERN_CONT "DM"); + pr_debug("DM"); break; case UI: - printk(KERN_CONT "UI"); + pr_debug("UI"); break; case UIH: - printk(KERN_CONT "UIH"); + pr_debug("UIH"); break; default: if (!(control & 0x01)) { - printk(KERN_CONT "I N(S)%d N(R)%d", + pr_debug("I N(S)%d N(R)%d", (control & 0x0E) >> 1, (control & 0xE) >> 5); } else switch (control & 0x0F) { case RR: - printk("RR(%d)", (control & 0xE0) >> 5); + pr_debug("RR(%d)", (control & 0xE0) >> 5); break; case RNR: - printk("RNR(%d)", (control & 0xE0) >> 5); + pr_debug("RNR(%d)", (control & 0xE0) >> 5); break; case REJ: - printk("REJ(%d)", (control & 0xE0) >> 5); + pr_debug("REJ(%d)", (control & 0xE0) >> 5); break; default: - printk(KERN_CONT "[%02X]", control); + pr_debug("[%02X]", control); } } if (control & PF) - printk(KERN_CONT "(P)"); + pr_debug("(P)"); else - printk(KERN_CONT "(F)"); + pr_debug("(F)"); if (dlen) { int ct = 0; while (dlen--) { if (ct % 8 == 0) - printk(KERN_CONT "\n "); - printk(KERN_CONT "%02X ", *data++); + pr_debug("\n "); + pr_debug("%02X %c ", *data, *data); + data++; ct++; } } - printk(KERN_CONT "\n"); + pr_debug("\n"); } @@ -525,10 +530,11 @@ static void hex_packet(const unsigned char *p, int len) int i; for (i = 0; i < len; i++) { if (i && (i % 16) == 0) - printk(KERN_INFO "\n"); - printk(KERN_INFO "%02X ", *p++); + pr_debug("\n"); + pr_debug("%02X %c ", *p, *p); + p++; } - printk("\n"); + pr_debug("\n"); } /** @@ -678,7 +684,7 @@ static void gsm_data_kick(struct gsm_mux *gsm) } if (debug & 4) { - printk(KERN_INFO "gsm_data_kick:\n"); + pr_debug("gsm_data_kick:\n"); hex_packet(gsm->txframe, len); } @@ -718,8 +724,8 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg) if (msg->len < 128) *--dp = (msg->len << 1) | EA; else { - *--dp = (msg->len >> 6) | EA; - *--dp = (msg->len & 127) << 1; + *--dp = ((msg->len & 127) << 1) | EA; + *--dp = (msg->len >> 6) & 0xfe; } } @@ -987,10 +993,22 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, u8 *data, */ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, - u32 modem) + u32 modem, int clen) { int mlines = 0; - u8 brk = modem >> 6; + u8 brk = 0; + + /* The modem status command can either contain one octet (v.24 signals) + or two octets (v.24 signals + break signals). The length field will + either be 2 or 3 respectively. This is specified in section + 5.4.6.3.7 of the 27.010 mux spec. */ + + if (clen == 2) + modem = modem & 0x7f; + else { + brk = modem & 0x7f; + modem = (modem >> 7) & 0x7f; + }; /* Flow control/ready to communicate */ if (modem & MDM_FC) { @@ -1057,14 +1075,13 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen) if (addr == 0 || addr >= NUM_DLCI || gsm->dlci[addr] == NULL) return; dlci = gsm->dlci[addr]; - while (gsm_read_ea(&modem, *dp++) == 0) { len--; if (len == 0) return; } tty = tty_port_tty_get(&dlci->port); - gsm_process_modem(tty, dlci, modem); + gsm_process_modem(tty, dlci, modem, clen); if (tty) { tty_wakeup(tty); tty_kref_put(tty); @@ -1361,7 +1378,7 @@ static void gsm_dlci_close(struct gsm_dlci *dlci) { del_timer(&dlci->t1); if (debug & 8) - printk(KERN_INFO "DLCI %d goes closed.\n", dlci->addr); + pr_debug("DLCI %d goes closed.\n", dlci->addr); dlci->state = DLCI_CLOSED; if (dlci->addr != 0) { struct tty_struct *tty = tty_port_tty_get(&dlci->port); @@ -1392,7 +1409,7 @@ static void gsm_dlci_open(struct gsm_dlci *dlci) /* This will let a tty open continue */ dlci->state = DLCI_OPEN; if (debug & 8) - printk(KERN_DEBUG "DLCI %d goes open.\n", dlci->addr); + pr_debug("DLCI %d goes open.\n", dlci->addr); wake_up(&dlci->gsm->event); } @@ -1486,15 +1503,17 @@ static void gsm_dlci_begin_close(struct gsm_dlci *dlci) * open we shovel the bits down it, if not we drop them. */ -static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int len) +static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int clen) { /* krefs .. */ struct tty_port *port = &dlci->port; struct tty_struct *tty = tty_port_tty_get(port); unsigned int modem = 0; + int len = clen; if (debug & 16) - printk(KERN_DEBUG "%d bytes for tty %p\n", len, tty); + pr_debug("gsm_dlci_data: %d bytes for tty %p\n", len, tty); + if (tty) { switch (dlci->adaption) { /* Unsupported types */ @@ -1511,7 +1530,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int len) if (len == 0) return; } - gsm_process_modem(tty, dlci, modem); + gsm_process_modem(tty, dlci, modem, clen); /* Line state will go via DLCI 0 controls only */ case 1: default: @@ -1625,7 +1644,6 @@ static void gsm_dlci_free(struct gsm_dlci *dlci) kfree(dlci); } - /* * LAPBish link layer logic */ @@ -1650,10 +1668,12 @@ static void gsm_queue(struct gsm_mux *gsm) if ((gsm->control & ~PF) == UI) gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len); + /* generate final CRC with received FCS */ + gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs); if (gsm->fcs != GOOD_FCS) { gsm->bad_fcs++; if (debug & 4) - printk(KERN_INFO "BAD FCS %02x\n", gsm->fcs); + pr_debug("BAD FCS %02x\n", gsm->fcs); return; } address = gsm->address >> 1; @@ -1748,6 +1768,8 @@ invalid: static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) { + unsigned int len; + switch (gsm->state) { case GSM_SEARCH: /* SOF marker */ if (c == GSM0_SOF) { @@ -1756,8 +1778,8 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) gsm->len = 0; gsm->fcs = INIT_FCS; } - break; /* Address EA */ - case GSM_ADDRESS: + break; + case GSM_ADDRESS: /* Address EA */ gsm->fcs = gsm_fcs_add(gsm->fcs, c); if (gsm_read_ea(&gsm->address, c)) gsm->state = GSM_CONTROL; @@ -1765,9 +1787,9 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) case GSM_CONTROL: /* Control Byte */ gsm->fcs = gsm_fcs_add(gsm->fcs, c); gsm->control = c; - gsm->state = GSM_LEN; + gsm->state = GSM_LEN0; break; - case GSM_LEN: /* Length EA */ + case GSM_LEN0: /* Length EA */ gsm->fcs = gsm_fcs_add(gsm->fcs, c); if (gsm_read_ea(&gsm->len, c)) { if (gsm->len > gsm->mru) { @@ -1776,8 +1798,28 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) break; } gsm->count = 0; - gsm->state = GSM_DATA; + if (!gsm->len) + gsm->state = GSM_FCS; + else + gsm->state = GSM_DATA; + break; } + gsm->state = GSM_LEN1; + break; + case GSM_LEN1: + gsm->fcs = gsm_fcs_add(gsm->fcs, c); + len = c; + gsm->len |= len << 7; + if (gsm->len > gsm->mru) { + gsm->bad_size++; + gsm->state = GSM_SEARCH; + break; + } + gsm->count = 0; + if (!gsm->len) + gsm->state = GSM_FCS; + else + gsm->state = GSM_DATA; break; case GSM_DATA: /* Data */ gsm->buf[gsm->count++] = c; @@ -1785,16 +1827,25 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) gsm->state = GSM_FCS; break; case GSM_FCS: /* FCS follows the packet */ - gsm->fcs = c; + gsm->received_fcs = c; + if (c == GSM0_SOF) { + gsm->state = GSM_SEARCH; + break; + } gsm_queue(gsm); - /* And then back for the next frame */ - gsm->state = GSM_SEARCH; + gsm->state = GSM_SSOF; + break; + case GSM_SSOF: + if (c == GSM0_SOF) { + gsm->state = GSM_SEARCH; + break; + } break; } } /** - * gsm0_receive - perform processing for non-transparency + * gsm1_receive - perform processing for non-transparency * @gsm: gsm data for this ldisc instance * @c: character * @@ -2034,9 +2085,6 @@ struct gsm_mux *gsm_alloc_mux(void) } EXPORT_SYMBOL_GPL(gsm_alloc_mux); - - - /** * gsmld_output - write to link * @gsm: our mux @@ -2053,10 +2101,8 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len) set_bit(TTY_DO_WRITE_WAKEUP, &gsm->tty->flags); return -ENOSPC; } - if (debug & 4) { - printk(KERN_INFO "-->%d bytes out\n", len); + if (debug & 4) hex_packet(data, len); - } gsm->tty->ops->write(gsm->tty, data, len); return len; } @@ -2110,10 +2156,8 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, char buf[64]; char flags; - if (debug & 4) { - printk(KERN_INFO "Inbytes %dd\n", count); + if (debug & 4) hex_packet(cp, count); - } for (i = count, dp = cp, f = fp; i; i--, dp++) { flags = *f++; @@ -2128,7 +2172,7 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, gsm->error(gsm, *dp, flags); break; default: - printk(KERN_ERR "%s: unknown flag %d\n", + pr_debug("%s: unknown flag %d\n", tty_name(tty, buf), flags); break; } @@ -2377,6 +2421,7 @@ static int gsmld_config(struct tty_struct *tty, struct gsm_mux *gsm, gsm->mru = c->mru; gsm->encoding = c->encapsulation; gsm->adaption = c->adaption; + gsm->n2 = c->n2; if (c->i == 1) gsm->ftype = UIH; @@ -2417,7 +2462,7 @@ static int gsmld_ioctl(struct tty_struct *tty, struct file *file, c.i = 1; else c.i = 2; - printk(KERN_INFO "Ftype %d i %d\n", gsm->ftype, c.i); + pr_debug("Ftype %d i %d\n", gsm->ftype, c.i); c.mru = gsm->mru; c.mtu = gsm->mtu; c.k = 0; @@ -2711,15 +2756,15 @@ static int __init gsm_init(void) /* Fill in our line protocol discipline, and register it */ int status = tty_register_ldisc(N_GSM0710, &tty_ldisc_packet); if (status != 0) { - printk(KERN_ERR - "n_gsm: can't register line discipline (err = %d)\n", status); + pr_debug("n_gsm: can't register line discipline (err = %d)\n", + status); return status; } gsm_tty_driver = alloc_tty_driver(256); if (!gsm_tty_driver) { tty_unregister_ldisc(N_GSM0710); - printk(KERN_ERR "gsm_init: tty allocation failed.\n"); + pr_debug("gsm_init: tty allocation failed.\n"); return -EINVAL; } gsm_tty_driver->owner = THIS_MODULE; @@ -2741,10 +2786,10 @@ static int __init gsm_init(void) if (tty_register_driver(gsm_tty_driver)) { put_tty_driver(gsm_tty_driver); tty_unregister_ldisc(N_GSM0710); - printk(KERN_ERR "gsm_init: tty registration failed.\n"); + pr_debug("gsm_init: tty registration failed.\n"); return -EBUSY; } - printk(KERN_INFO "gsm_init: loaded as %d,%d.\n", + pr_debug("gsm_init: loaded as %d,%d.\n", gsm_tty_driver->major, gsm_tty_driver->minor_start); return 0; } @@ -2753,12 +2798,11 @@ static void __exit gsm_exit(void) { int status = tty_unregister_ldisc(N_GSM0710); if (status != 0) - printk(KERN_ERR - "n_gsm: can't unregister line discipline (err = %d)\n", - status); + pr_debug("n_gsm: can't unregister line discipline (err = %d)\n" + , status); tty_unregister_driver(gsm_tty_driver); put_tty_driver(gsm_tty_driver); - printk(KERN_INFO "gsm_init: unloaded.\n"); + pr_debug("gsm_init: unloaded.\n"); } module_init(gsm_init); -- 1.7.0.4
_______________________________________________ MeeGo-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
