These fixes have been verified with the IFX6160 modem.

Signed-off-by: kmills <[email protected]>
---
 drivers/char/n_gsm.c |  136 ++++++++++++++++++++++++++++++++++----------------
 1 files changed, 93 insertions(+), 43 deletions(-)

diff --git a/drivers/char/n_gsm.c b/drivers/char/n_gsm.c
index 79d8464..c377b32 100644
--- a/drivers/char/n_gsm.c
+++ b/drivers/char/n_gsm.c
@@ -78,6 +78,8 @@ module_param(debug, int, 0600);
    limits so this is plenty */
 #define MAX_MRU 512
 #define MAX_MTU 512
+#define GSM_DEFAULT_MTU 512
+#define GSM_DEFAULT_MRU GSM_DEFAULT_MTU
 
 /*
  *     Each block of data we have queued to go out is in the form of
@@ -185,6 +187,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 +197,7 @@ struct gsm_mux {
        int encoding;
        u8 control;
        u8 fcs;
+       u8 good_fcs;
        u8 *txframe;                    /* TX framing buffer */
 
        /* Methods for the receiver side */
@@ -294,6 +300,7 @@ static spinlock_t gsm_mux_lock;
 #define XOFF                   0x13
 
 static const struct tty_port_operations gsm_port_ops;
+static void gsm_dlci_data_kick(struct gsm_dlci *dlci);
 
 /*
  *     CRC table for GSM 0710
@@ -430,7 +437,7 @@ 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]);
+       printk(KERN_CONT "%s %d) %c: ", hdr, addr, "RC"[cr]);
 
        switch (control & ~PF) {
        case SABM:
@@ -458,13 +465,13 @@ static void gsm_print_packet(const char *hdr, int addr, 
int cr,
                } else
                switch (control & 0x0F) {
                case RR:
-                       printk("RR(%d)", (control & 0xE0) >> 5);
+                       printk(KERN_CONT "RR(%d)", (control & 0xE0) >> 5);
                        break;
                case RNR:
-                       printk("RNR(%d)", (control & 0xE0) >> 5);
+                       printk(KERN_CONT "RNR(%d)", (control & 0xE0) >> 5);
                        break;
                case REJ:
-                       printk("REJ(%d)", (control & 0xE0) >> 5);
+                       printk(KERN_CONT "REJ(%d)", (control & 0xE0) >> 5);
                        break;
                default:
                        printk(KERN_CONT "[%02X]", control);
@@ -481,7 +488,8 @@ static void gsm_print_packet(const char *hdr, int addr, int 
cr,
                while (dlen--) {
                        if (ct % 8 == 0)
                                printk(KERN_CONT "\n    ");
-                       printk(KERN_CONT "%02X ", *data++);
+                       printk(KERN_CONT "%02X %c ", *data, *data);
+                       data++;
                        ct++;
                }
        }
@@ -525,8 +533,9 @@ 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++);
+                       printk(KERN_CONT "\n");
+               printk(KERN_CONT "%02X %c ", *p, *p);
+               p++;
        }
        printk("\n");
 }
@@ -718,8 +727,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;
                }
        }
 
@@ -986,13 +995,23 @@ static void gsm_control_reply(struct gsm_mux *gsm, int 
cmd, u8 *data,
  *     layer 2 is processed. Sort out the local modem state and throttles
  */
 
+#define TWO_OCTETS 0x4000
 static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci,
-                                                       u32 modem)
+                                                       u32 _modem)
 {
        int  mlines = 0;
-       u8 brk = modem >> 6;
+       u8 modem;
+       u8 brk = 0;
+
+       /* only two octets are defined at this time (control and break) */
+       if (_modem & TWO_OCTETS) {
+               modem = (_modem >> 7) & 0x7f;
+               brk = _modem & 0x7f;
+       } else
+               modem = _modem & 0x7f;
 
        /* Flow control/ready to communicate */
+
        if (modem & MDM_FC) {
                /* Need to throttle our output on this device */
                dlci->constipated = 1;
@@ -1019,6 +1038,10 @@ static void gsm_process_modem(struct tty_struct *tty, 
struct gsm_dlci *dlci,
                        tty_insert_flip_char(tty, 0, TTY_BREAK);
        }
        dlci->modem_rx = mlines;
+       if (tty && (mlines & TIOCM_RTS)) {
+               pr_debug("wake up port\n");
+               wake_up_interruptible(&dlci->port.open_wait);
+       }
 }
 
 /**
@@ -1036,7 +1059,7 @@ static void gsm_process_modem(struct tty_struct *tty, 
struct gsm_dlci *dlci,
 static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen)
 {
        unsigned int addr = 0;
-       unsigned int modem = 0;
+       unsigned int modem = 1;
        struct gsm_dlci *dlci;
        int len = clen;
        u8 *dp = data;
@@ -1057,7 +1080,6 @@ 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)
@@ -1340,7 +1362,6 @@ static int gsm_control_wait(struct gsm_mux *gsm, struct 
gsm_control *control)
        return err;
 }
 
-
 /*
  *     DLCI level handling: Needs krefs
  */
@@ -1392,7 +1413,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);
+               printk(KERN_INFO "DLCI %d goes open.\n", dlci->addr);
        wake_up(&dlci->gsm->event);
 }
 
@@ -1491,10 +1512,11 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, u8 
*data, int len)
        /* krefs .. */
        struct tty_port *port = &dlci->port;
        struct tty_struct *tty = tty_port_tty_get(port);
-       unsigned int modem = 0;
+       unsigned int modem = 1;
 
        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 */
@@ -1625,7 +1647,6 @@ static void gsm_dlci_free(struct gsm_dlci *dlci)
        kfree(dlci);
 }
 
-
 /*
  *     LAPBish link layer logic
  */
@@ -1644,16 +1665,20 @@ static void gsm_queue(struct gsm_mux *gsm)
 {
        struct gsm_dlci *dlci;
        u8 cr;
+       u8 fcs;
        int address;
        /* We have to sneak a look at the packet body to do the FCS.
           A somewhat layering violation in the spec */
 
+       pr_debug("gsm_queue: ctl:%x dlci:%d\n", gsm->control,
+               gsm->address >> 1);
        if ((gsm->control & ~PF) == UI)
                gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len);
-       if (gsm->fcs != GOOD_FCS) {
+       fcs = ~gsm->fcs;
+       if (fcs != gsm->good_fcs) {
                gsm->bad_fcs++;
                if (debug & 4)
-                       printk(KERN_INFO "BAD FCS %02x\n", gsm->fcs);
+                       pr_debug("BAD FCS %02x (!%02x)\n", fcs, gsm->good_fcs);
                return;
        }
        address = gsm->address >> 1;
@@ -1737,7 +1762,6 @@ invalid:
        return;
 }
 
-
 /**
  *     gsm0_receive    -       perform processing for non-transparency
  *     @gsm: gsm data for this ldisc instance
@@ -1748,6 +1772,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) {
@@ -1755,9 +1781,10 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned 
char c)
                        gsm->address = 0;
                        gsm->len = 0;
                        gsm->fcs = INIT_FCS;
+                       gsm->good_fcs = 0;
                }
-               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 +1792,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 +1803,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 +1832,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;
+               if (c == GSM0_SOF) {
+                       gsm->state = GSM_SEARCH;
+                       break;
+               }
+               gsm->good_fcs = c;
                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
  *
@@ -2025,18 +2081,15 @@ struct gsm_mux *gsm_alloc_mux(void)
        gsm->ftype = UIH;
        gsm->initiator = 0;
        gsm->adaption = 1;
-       gsm->encoding = 1;
-       gsm->mru = 64;  /* Default to encoding 1 so these should be 64 */
-       gsm->mtu = 64;
+       gsm->encoding = 0;
+       gsm->mru = GSM_DEFAULT_MTU;
+       gsm->mtu = GSM_DEFAULT_MTU;
        gsm->dead = 1;  /* Avoid early tty opens */
 
        return gsm;
 }
 EXPORT_SYMBOL_GPL(gsm_alloc_mux);
 
-
-
-
 /**
  *     gsmld_output            -       write to link
  *     @gsm: our mux
@@ -2053,10 +2106,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 +2161,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++;
@@ -2212,7 +2261,7 @@ static int gsmld_open(struct tty_struct *tty)
        tty->receive_room = 65536;
 
        /* Attach the initial passive connection */
-       gsm->encoding = 1;
+       /*gsm->encoding = 1; */
        return gsmld_attach_gsm(tty, gsm);
 }
 
@@ -2377,6 +2426,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;
-- 
1.7.0.4
From 1a3e3da2180cbe39a5259297885861ef1ffa1b7b Mon Sep 17 00:00:00 2001
From: kmills <[email protected]>
Date: Wed, 27 Oct 2010 18:18:23 -0700
Subject: [PATCH 2/2] Mux bug fixes.
 These fixes have been verified with the IFX6160 modem.

Signed-off-by: kmills <[email protected]>
---
 drivers/char/n_gsm.c |  136 ++++++++++++++++++++++++++++++++++----------------
 1 files changed, 93 insertions(+), 43 deletions(-)

diff --git a/drivers/char/n_gsm.c b/drivers/char/n_gsm.c
index 79d8464..c377b32 100644
--- a/drivers/char/n_gsm.c
+++ b/drivers/char/n_gsm.c
@@ -78,6 +78,8 @@ module_param(debug, int, 0600);
    limits so this is plenty */
 #define MAX_MRU 512
 #define MAX_MTU 512
+#define GSM_DEFAULT_MTU 512
+#define GSM_DEFAULT_MRU GSM_DEFAULT_MTU
 
 /*
  *	Each block of data we have queued to go out is in the form of
@@ -185,6 +187,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 +197,7 @@ struct gsm_mux {
 	int encoding;
 	u8 control;
 	u8 fcs;
+	u8 good_fcs;
 	u8 *txframe;			/* TX framing buffer */
 
 	/* Methods for the receiver side */
@@ -294,6 +300,7 @@ static spinlock_t gsm_mux_lock;
 #define XOFF			0x13
 
 static const struct tty_port_operations gsm_port_ops;
+static void gsm_dlci_data_kick(struct gsm_dlci *dlci);
 
 /*
  *	CRC table for GSM 0710
@@ -430,7 +437,7 @@ 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]);
+	printk(KERN_CONT "%s %d) %c: ", hdr, addr, "RC"[cr]);
 
 	switch (control & ~PF) {
 	case SABM:
@@ -458,13 +465,13 @@ static void gsm_print_packet(const char *hdr, int addr, int cr,
 		} else
 		switch (control & 0x0F) {
 		case RR:
-			printk("RR(%d)", (control & 0xE0) >> 5);
+			printk(KERN_CONT "RR(%d)", (control & 0xE0) >> 5);
 			break;
 		case RNR:
-			printk("RNR(%d)", (control & 0xE0) >> 5);
+			printk(KERN_CONT "RNR(%d)", (control & 0xE0) >> 5);
 			break;
 		case REJ:
-			printk("REJ(%d)", (control & 0xE0) >> 5);
+			printk(KERN_CONT "REJ(%d)", (control & 0xE0) >> 5);
 			break;
 		default:
 			printk(KERN_CONT "[%02X]", control);
@@ -481,7 +488,8 @@ static void gsm_print_packet(const char *hdr, int addr, int cr,
 		while (dlen--) {
 			if (ct % 8 == 0)
 				printk(KERN_CONT "\n    ");
-			printk(KERN_CONT "%02X ", *data++);
+			printk(KERN_CONT "%02X %c ", *data, *data);
+			data++;
 			ct++;
 		}
 	}
@@ -525,8 +533,9 @@ 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++);
+			printk(KERN_CONT "\n");
+		printk(KERN_CONT "%02X %c ", *p, *p);
+		p++;
 	}
 	printk("\n");
 }
@@ -718,8 +727,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;
 		}
 	}
 
@@ -986,13 +995,23 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, u8 *data,
  *	layer 2 is processed. Sort out the local modem state and throttles
  */
 
+#define TWO_OCTETS 0x4000
 static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci,
-							u32 modem)
+							u32 _modem)
 {
 	int  mlines = 0;
-	u8 brk = modem >> 6;
+	u8 modem;
+	u8 brk = 0;
+
+	/* only two octets are defined at this time (control and break) */
+	if (_modem & TWO_OCTETS) {
+		modem = (_modem >> 7) & 0x7f;
+		brk = _modem & 0x7f;
+	} else
+		modem = _modem & 0x7f;
 
 	/* Flow control/ready to communicate */
+
 	if (modem & MDM_FC) {
 		/* Need to throttle our output on this device */
 		dlci->constipated = 1;
@@ -1019,6 +1038,10 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci,
 			tty_insert_flip_char(tty, 0, TTY_BREAK);
 	}
 	dlci->modem_rx = mlines;
+	if (tty && (mlines & TIOCM_RTS)) {
+		pr_debug("wake up port\n");
+		wake_up_interruptible(&dlci->port.open_wait);
+	}
 }
 
 /**
@@ -1036,7 +1059,7 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci,
 static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen)
 {
 	unsigned int addr = 0;
-	unsigned int modem = 0;
+	unsigned int modem = 1;
 	struct gsm_dlci *dlci;
 	int len = clen;
 	u8 *dp = data;
@@ -1057,7 +1080,6 @@ 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)
@@ -1340,7 +1362,6 @@ static int gsm_control_wait(struct gsm_mux *gsm, struct gsm_control *control)
 	return err;
 }
 
-
 /*
  *	DLCI level handling: Needs krefs
  */
@@ -1392,7 +1413,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);
+		printk(KERN_INFO "DLCI %d goes open.\n", dlci->addr);
 	wake_up(&dlci->gsm->event);
 }
 
@@ -1491,10 +1512,11 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int len)
 	/* krefs .. */
 	struct tty_port *port = &dlci->port;
 	struct tty_struct *tty = tty_port_tty_get(port);
-	unsigned int modem = 0;
+	unsigned int modem = 1;
 
 	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 */
@@ -1625,7 +1647,6 @@ static void gsm_dlci_free(struct gsm_dlci *dlci)
 	kfree(dlci);
 }
 
-
 /*
  *	LAPBish link layer logic
  */
@@ -1644,16 +1665,20 @@ static void gsm_queue(struct gsm_mux *gsm)
 {
 	struct gsm_dlci *dlci;
 	u8 cr;
+	u8 fcs;
 	int address;
 	/* We have to sneak a look at the packet body to do the FCS.
 	   A somewhat layering violation in the spec */
 
+	pr_debug("gsm_queue: ctl:%x dlci:%d\n", gsm->control,
+		gsm->address >> 1);
 	if ((gsm->control & ~PF) == UI)
 		gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len);
-	if (gsm->fcs != GOOD_FCS) {
+	fcs = ~gsm->fcs;
+	if (fcs != gsm->good_fcs) {
 		gsm->bad_fcs++;
 		if (debug & 4)
-			printk(KERN_INFO "BAD FCS %02x\n", gsm->fcs);
+			pr_debug("BAD FCS %02x (!%02x)\n", fcs, gsm->good_fcs);
 		return;
 	}
 	address = gsm->address >> 1;
@@ -1737,7 +1762,6 @@ invalid:
 	return;
 }
 
-
 /**
  *	gsm0_receive	-	perform processing for non-transparency
  *	@gsm: gsm data for this ldisc instance
@@ -1748,6 +1772,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) {
@@ -1755,9 +1781,10 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c)
 			gsm->address = 0;
 			gsm->len = 0;
 			gsm->fcs = INIT_FCS;
+			gsm->good_fcs = 0;
 		}
-		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 +1792,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 +1803,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 +1832,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;
+		if (c == GSM0_SOF) {
+			gsm->state = GSM_SEARCH;
+			break;
+		}
+		gsm->good_fcs = c;
 		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
  *
@@ -2025,18 +2081,15 @@ struct gsm_mux *gsm_alloc_mux(void)
 	gsm->ftype = UIH;
 	gsm->initiator = 0;
 	gsm->adaption = 1;
-	gsm->encoding = 1;
-	gsm->mru = 64;	/* Default to encoding 1 so these should be 64 */
-	gsm->mtu = 64;
+	gsm->encoding = 0;
+	gsm->mru = GSM_DEFAULT_MTU;
+	gsm->mtu = GSM_DEFAULT_MTU;
 	gsm->dead = 1;	/* Avoid early tty opens */
 
 	return gsm;
 }
 EXPORT_SYMBOL_GPL(gsm_alloc_mux);
 
-
-
-
 /**
  *	gsmld_output		-	write to link
  *	@gsm: our mux
@@ -2053,10 +2106,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 +2161,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++;
@@ -2212,7 +2261,7 @@ static int gsmld_open(struct tty_struct *tty)
 	tty->receive_room = 65536;
 
 	/* Attach the initial passive connection */
-	gsm->encoding = 1;
+	/*gsm->encoding = 1; */
 	return gsmld_attach_gsm(tty, gsm);
 }
 
@@ -2377,6 +2426,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;
-- 
1.7.0.4

_______________________________________________
Meego-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel

Reply via email to