aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/n_gsm.c59
1 files changed, 46 insertions, 13 deletions
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 04ef3ef0a422..5256087dd81b 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -184,6 +184,9 @@ struct gsm_mux {
184#define GSM_DATA 5 184#define GSM_DATA 5
185#define GSM_FCS 6 185#define GSM_FCS 6
186#define GSM_OVERRUN 7 186#define GSM_OVERRUN 7
187#define GSM_LEN0 8
188#define GSM_LEN1 9
189#define GSM_SSOF 10
187 unsigned int len; 190 unsigned int len;
188 unsigned int address; 191 unsigned int address;
189 unsigned int count; 192 unsigned int count;
@@ -191,6 +194,7 @@ struct gsm_mux {
191 int encoding; 194 int encoding;
192 u8 control; 195 u8 control;
193 u8 fcs; 196 u8 fcs;
197 u8 received_fcs;
194 u8 *txframe; /* TX framing buffer */ 198 u8 *txframe; /* TX framing buffer */
195 199
196 /* Methods for the receiver side */ 200 /* Methods for the receiver side */
@@ -1623,7 +1627,6 @@ static void gsm_dlci_free(struct gsm_dlci *dlci)
1623 kfree(dlci); 1627 kfree(dlci);
1624} 1628}
1625 1629
1626
1627/* 1630/*
1628 * LAPBish link layer logic 1631 * LAPBish link layer logic
1629 */ 1632 */
@@ -1648,6 +1651,8 @@ static void gsm_queue(struct gsm_mux *gsm)
1648 1651
1649 if ((gsm->control & ~PF) == UI) 1652 if ((gsm->control & ~PF) == UI)
1650 gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len); 1653 gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len);
1654 /* generate final CRC with received FCS */
1655 gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs);
1651 if (gsm->fcs != GOOD_FCS) { 1656 if (gsm->fcs != GOOD_FCS) {
1652 gsm->bad_fcs++; 1657 gsm->bad_fcs++;
1653 if (debug & 4) 1658 if (debug & 4)
@@ -1746,6 +1751,8 @@ invalid:
1746 1751
1747static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) 1752static void gsm0_receive(struct gsm_mux *gsm, unsigned char c)
1748{ 1753{
1754 unsigned int len;
1755
1749 switch (gsm->state) { 1756 switch (gsm->state) {
1750 case GSM_SEARCH: /* SOF marker */ 1757 case GSM_SEARCH: /* SOF marker */
1751 if (c == GSM0_SOF) { 1758 if (c == GSM0_SOF) {
@@ -1754,8 +1761,8 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c)
1754 gsm->len = 0; 1761 gsm->len = 0;
1755 gsm->fcs = INIT_FCS; 1762 gsm->fcs = INIT_FCS;
1756 } 1763 }
1757 break; /* Address EA */ 1764 break;
1758 case GSM_ADDRESS: 1765 case GSM_ADDRESS: /* Address EA */
1759 gsm->fcs = gsm_fcs_add(gsm->fcs, c); 1766 gsm->fcs = gsm_fcs_add(gsm->fcs, c);
1760 if (gsm_read_ea(&gsm->address, c)) 1767 if (gsm_read_ea(&gsm->address, c))
1761 gsm->state = GSM_CONTROL; 1768 gsm->state = GSM_CONTROL;
@@ -1763,9 +1770,9 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c)
1763 case GSM_CONTROL: /* Control Byte */ 1770 case GSM_CONTROL: /* Control Byte */
1764 gsm->fcs = gsm_fcs_add(gsm->fcs, c); 1771 gsm->fcs = gsm_fcs_add(gsm->fcs, c);
1765 gsm->control = c; 1772 gsm->control = c;
1766 gsm->state = GSM_LEN; 1773 gsm->state = GSM_LEN0;
1767 break; 1774 break;
1768 case GSM_LEN: /* Length EA */ 1775 case GSM_LEN0: /* Length EA */
1769 gsm->fcs = gsm_fcs_add(gsm->fcs, c); 1776 gsm->fcs = gsm_fcs_add(gsm->fcs, c);
1770 if (gsm_read_ea(&gsm->len, c)) { 1777 if (gsm_read_ea(&gsm->len, c)) {
1771 if (gsm->len > gsm->mru) { 1778 if (gsm->len > gsm->mru) {
@@ -1774,8 +1781,28 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c)
1774 break; 1781 break;
1775 } 1782 }
1776 gsm->count = 0; 1783 gsm->count = 0;
1777 gsm->state = GSM_DATA; 1784 if (!gsm->len)
1785 gsm->state = GSM_FCS;
1786 else
1787 gsm->state = GSM_DATA;
1788 break;
1778 } 1789 }
1790 gsm->state = GSM_LEN1;
1791 break;
1792 case GSM_LEN1:
1793 gsm->fcs = gsm_fcs_add(gsm->fcs, c);
1794 len = c;
1795 gsm->len |= len << 7;
1796 if (gsm->len > gsm->mru) {
1797 gsm->bad_size++;
1798 gsm->state = GSM_SEARCH;
1799 break;
1800 }
1801 gsm->count = 0;
1802 if (!gsm->len)
1803 gsm->state = GSM_FCS;
1804 else
1805 gsm->state = GSM_DATA;
1779 break; 1806 break;
1780 case GSM_DATA: /* Data */ 1807 case GSM_DATA: /* Data */
1781 gsm->buf[gsm->count++] = c; 1808 gsm->buf[gsm->count++] = c;
@@ -1783,16 +1810,25 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c)
1783 gsm->state = GSM_FCS; 1810 gsm->state = GSM_FCS;
1784 break; 1811 break;
1785 case GSM_FCS: /* FCS follows the packet */ 1812 case GSM_FCS: /* FCS follows the packet */
1786 gsm->fcs = c; 1813 gsm->received_fcs = c;
1814 if (c == GSM0_SOF) {
1815 gsm->state = GSM_SEARCH;
1816 break;
1817 }
1787 gsm_queue(gsm); 1818 gsm_queue(gsm);
1788 /* And then back for the next frame */ 1819 gsm->state = GSM_SSOF;
1789 gsm->state = GSM_SEARCH; 1820 break;
1821 case GSM_SSOF:
1822 if (c == GSM0_SOF) {
1823 gsm->state = GSM_SEARCH;
1824 break;
1825 }
1790 break; 1826 break;
1791 } 1827 }
1792} 1828}
1793 1829
1794/** 1830/**
1795 * gsm0_receive - perform processing for non-transparency 1831 * gsm1_receive - perform processing for non-transparency
1796 * @gsm: gsm data for this ldisc instance 1832 * @gsm: gsm data for this ldisc instance
1797 * @c: character 1833 * @c: character
1798 * 1834 *
@@ -2032,9 +2068,6 @@ struct gsm_mux *gsm_alloc_mux(void)
2032} 2068}
2033EXPORT_SYMBOL_GPL(gsm_alloc_mux); 2069EXPORT_SYMBOL_GPL(gsm_alloc_mux);
2034 2070
2035
2036
2037
2038/** 2071/**
2039 * gsmld_output - write to link 2072 * gsmld_output - write to link
2040 * @gsm: our mux 2073 * @gsm: our mux