aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/gigaset
diff options
context:
space:
mode:
authorTilman Schmidt <tilman@imap.cc>2010-02-22 08:09:22 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-26 04:24:23 -0500
commit63e055d1c6e3a5f6d370cc841d621d5fa4d5d834 (patch)
tree80f645c85bbc012d3b1b45ab66ee7dd8938de49b /drivers/isdn/gigaset
parent2ac2ed5f2dfc97ae9ed9f446ad6e064fa821ef6d (diff)
bas_gigaset: collapse CR/LF at end of AT response
Copy the mechanism from ser_/usb_gigaset to avoid producing spurious empty responses for CR/LF sequences from the device. Add a comment in all drivers documenting that behaviour. Correct an off by one error that might result in a one byte buffer overflow when receiving an unexpectedly long reply. Impact: minor bugfix Signed-off-by: Tilman Schmidt <tilman@imap.cc> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/isdn/gigaset')
-rw-r--r--drivers/isdn/gigaset/asyncdata.c2
-rw-r--r--drivers/isdn/gigaset/gigaset.h4
-rw-r--r--drivers/isdn/gigaset/isocdata.c44
3 files changed, 35 insertions, 15 deletions
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index ccb2a7b7c41d..e913beb63f24 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -40,6 +40,8 @@ static inline int muststuff(unsigned char c)
40 * Append received bytes to the command response buffer and forward them 40 * Append received bytes to the command response buffer and forward them
41 * line by line to the response handler. Exit whenever a mode/state change 41 * line by line to the response handler. Exit whenever a mode/state change
42 * might have occurred. 42 * might have occurred.
43 * Note: Received lines may be terminated by CR, LF, or CR LF, which will be
44 * removed before passing the line to the response handler.
43 * Return value: 45 * Return value:
44 * number of processed bytes 46 * number of processed bytes
45 */ 47 */
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index e963a6c2e86d..c9ccf7de2275 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -38,7 +38,7 @@
38#define GIG_COMPAT {0, 4, 0, 0} 38#define GIG_COMPAT {0, 4, 0, 0}
39 39
40#define MAX_REC_PARAMS 10 /* Max. number of params in response string */ 40#define MAX_REC_PARAMS 10 /* Max. number of params in response string */
41#define MAX_RESP_SIZE 512 /* Max. size of a response string */ 41#define MAX_RESP_SIZE 511 /* Max. size of a response string */
42 42
43#define MAX_EVENTS 64 /* size of event queue */ 43#define MAX_EVENTS 64 /* size of event queue */
44 44
@@ -498,7 +498,7 @@ struct cardstate {
498 spinlock_t ev_lock; 498 spinlock_t ev_lock;
499 499
500 /* current modem response */ 500 /* current modem response */
501 unsigned char respdata[MAX_RESP_SIZE]; 501 unsigned char respdata[MAX_RESP_SIZE+1];
502 unsigned cbytes; 502 unsigned cbytes;
503 503
504 /* private data of hardware drivers */ 504 /* private data of hardware drivers */
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index 85394a6ebae8..16fd3bd48883 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -905,29 +905,49 @@ void gigaset_isoc_receive(unsigned char *src, unsigned count,
905 905
906/* == data input =========================================================== */ 906/* == data input =========================================================== */
907 907
908/* process a block of received bytes in command mode (mstate != MS_LOCKED)
909 * Append received bytes to the command response buffer and forward them
910 * line by line to the response handler.
911 * Note: Received lines may be terminated by CR, LF, or CR LF, which will be
912 * removed before passing the line to the response handler.
913 */
908static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf) 914static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf)
909{ 915{
910 struct cardstate *cs = inbuf->cs; 916 struct cardstate *cs = inbuf->cs;
911 unsigned cbytes = cs->cbytes; 917 unsigned cbytes = cs->cbytes;
918 unsigned char c;
912 919
913 while (numbytes--) { 920 while (numbytes--) {
914 /* copy next character, check for end of line */ 921 c = *src++;
915 switch (cs->respdata[cbytes] = *src++) { 922 switch (c) {
916 case '\r':
917 case '\n': 923 case '\n':
918 /* end of line */ 924 if (cbytes == 0 && cs->respdata[0] == '\r') {
919 gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", 925 /* collapse LF with preceding CR */
920 __func__, cbytes); 926 cs->respdata[0] = 0;
921 if (cbytes >= MAX_RESP_SIZE - 1) 927 break;
922 dev_warn(cs->dev, "response too large\n"); 928 }
929 /* --v-- fall through --v-- */
930 case '\r':
931 /* end of message line, pass to response handler */
932 if (cbytes >= MAX_RESP_SIZE) {
933 dev_warn(cs->dev, "response too large (%d)\n",
934 cbytes);
935 cbytes = MAX_RESP_SIZE;
936 }
923 cs->cbytes = cbytes; 937 cs->cbytes = cbytes;
938 gigaset_dbg_buffer(DEBUG_TRANSCMD, "received response",
939 cbytes, cs->respdata);
924 gigaset_handle_modem_response(cs); 940 gigaset_handle_modem_response(cs);
925 cbytes = 0; 941 cbytes = 0;
942
943 /* store EOL byte for CRLF collapsing */
944 cs->respdata[0] = c;
926 break; 945 break;
927 default: 946 default:
928 /* advance in line buffer, checking for overflow */ 947 /* append to line buffer if possible */
929 if (cbytes < MAX_RESP_SIZE - 1) 948 if (cbytes < MAX_RESP_SIZE)
930 cbytes++; 949 cs->respdata[cbytes] = c;
950 cbytes++;
931 } 951 }
932 } 952 }
933 953
@@ -958,8 +978,6 @@ void gigaset_isoc_input(struct inbuf_t *inbuf)
958 numbytes, src); 978 numbytes, src);
959 gigaset_if_receive(inbuf->cs, src, numbytes); 979 gigaset_if_receive(inbuf->cs, src, numbytes);
960 } else { 980 } else {
961 gigaset_dbg_buffer(DEBUG_CMD, "received response",
962 numbytes, src);
963 cmd_loop(src, numbytes, inbuf); 981 cmd_loop(src, numbytes, inbuf);
964 } 982 }
965 983