diff options
Diffstat (limited to 'drivers/tty/n_gsm.c')
-rw-r--r-- | drivers/tty/n_gsm.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 09e8c7d53af3..19b4ae052af8 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c | |||
@@ -875,7 +875,8 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, | |||
875 | *dp++ = last << 7 | first << 6 | 1; /* EA */ | 875 | *dp++ = last << 7 | first << 6 | 1; /* EA */ |
876 | len--; | 876 | len--; |
877 | } | 877 | } |
878 | memcpy(dp, skb_pull(dlci->skb, len), len); | 878 | memcpy(dp, dlci->skb->data, len); |
879 | skb_pull(dlci->skb, len); | ||
879 | __gsm_data_queue(dlci, msg); | 880 | __gsm_data_queue(dlci, msg); |
880 | if (last) | 881 | if (last) |
881 | dlci->skb = NULL; | 882 | dlci->skb = NULL; |
@@ -984,10 +985,22 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, u8 *data, | |||
984 | */ | 985 | */ |
985 | 986 | ||
986 | static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, | 987 | static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, |
987 | u32 modem) | 988 | u32 modem, int clen) |
988 | { | 989 | { |
989 | int mlines = 0; | 990 | int mlines = 0; |
990 | u8 brk = modem >> 6; | 991 | u8 brk = 0; |
992 | |||
993 | /* The modem status command can either contain one octet (v.24 signals) | ||
994 | or two octets (v.24 signals + break signals). The length field will | ||
995 | either be 2 or 3 respectively. This is specified in section | ||
996 | 5.4.6.3.7 of the 27.010 mux spec. */ | ||
997 | |||
998 | if (clen == 2) | ||
999 | modem = modem & 0x7f; | ||
1000 | else { | ||
1001 | brk = modem & 0x7f; | ||
1002 | modem = (modem >> 7) & 0x7f; | ||
1003 | }; | ||
991 | 1004 | ||
992 | /* Flow control/ready to communicate */ | 1005 | /* Flow control/ready to communicate */ |
993 | if (modem & MDM_FC) { | 1006 | if (modem & MDM_FC) { |
@@ -1061,7 +1074,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen) | |||
1061 | return; | 1074 | return; |
1062 | } | 1075 | } |
1063 | tty = tty_port_tty_get(&dlci->port); | 1076 | tty = tty_port_tty_get(&dlci->port); |
1064 | gsm_process_modem(tty, dlci, modem); | 1077 | gsm_process_modem(tty, dlci, modem, clen); |
1065 | if (tty) { | 1078 | if (tty) { |
1066 | tty_wakeup(tty); | 1079 | tty_wakeup(tty); |
1067 | tty_kref_put(tty); | 1080 | tty_kref_put(tty); |
@@ -1482,12 +1495,13 @@ static void gsm_dlci_begin_close(struct gsm_dlci *dlci) | |||
1482 | * open we shovel the bits down it, if not we drop them. | 1495 | * open we shovel the bits down it, if not we drop them. |
1483 | */ | 1496 | */ |
1484 | 1497 | ||
1485 | static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int len) | 1498 | static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int clen) |
1486 | { | 1499 | { |
1487 | /* krefs .. */ | 1500 | /* krefs .. */ |
1488 | struct tty_port *port = &dlci->port; | 1501 | struct tty_port *port = &dlci->port; |
1489 | struct tty_struct *tty = tty_port_tty_get(port); | 1502 | struct tty_struct *tty = tty_port_tty_get(port); |
1490 | unsigned int modem = 0; | 1503 | unsigned int modem = 0; |
1504 | int len = clen; | ||
1491 | 1505 | ||
1492 | if (debug & 16) | 1506 | if (debug & 16) |
1493 | pr_debug("%d bytes for tty %p\n", len, tty); | 1507 | pr_debug("%d bytes for tty %p\n", len, tty); |
@@ -1507,7 +1521,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int len) | |||
1507 | if (len == 0) | 1521 | if (len == 0) |
1508 | return; | 1522 | return; |
1509 | } | 1523 | } |
1510 | gsm_process_modem(tty, dlci, modem); | 1524 | gsm_process_modem(tty, dlci, modem, clen); |
1511 | /* Line state will go via DLCI 0 controls only */ | 1525 | /* Line state will go via DLCI 0 controls only */ |
1512 | case 1: | 1526 | case 1: |
1513 | default: | 1527 | default: |