diff options
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/n_gsm.c | 59 |
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 | ||
1747 | static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) | 1752 | static 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 | } |
2033 | EXPORT_SYMBOL_GPL(gsm_alloc_mux); | 2069 | EXPORT_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 |