netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Tilman Schmidt <tilman@imap.cc>
To: Karsten Keil <isdn@linux-pingi.de>, David Miller <davem@davemloft.net>
Cc: Hansjoerg Lipp <hjlipp@web.de>, Karsten Keil <keil@b1-systems.de>,
	isdn4linux@listserv.isdn4linux.de,
	i4ldeveloper@listserv.isdn4linux.de, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH 2/4] bas_gigaset: collapse CR/LF at end of AT response
Date: Tue, 23 Feb 2010 00:09:22 +0100 (CET)	[thread overview]
Message-ID: <20100221-patch-gigaset-02.tilman@imap.cc> (raw)
In-Reply-To: <20100221-patch-gigaset-00.tilman@imap.cc>

From: Tilman Schmidt <tilman@imap.cc>
Subject: [PATCH 2/4] 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>
---
 drivers/isdn/gigaset/asyncdata.c |    2 +
 drivers/isdn/gigaset/gigaset.h   |    4 +-
 drivers/isdn/gigaset/isocdata.c  |   44 ++++++++++++++++++++++++++-----------
 3 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index ccb2a7b..e913beb 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -40,6 +40,8 @@ static inline int muststuff(unsigned char c)
  * Append received bytes to the command response buffer and forward them
  * line by line to the response handler. Exit whenever a mode/state change
  * might have occurred.
+ * Note: Received lines may be terminated by CR, LF, or CR LF, which will be
+ * removed before passing the line to the response handler.
  * Return value:
  *	number of processed bytes
  */
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index e963a6c..c9ccf7d 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -38,7 +38,7 @@
 #define GIG_COMPAT  {0, 4, 0, 0}
 
 #define MAX_REC_PARAMS 10	/* Max. number of params in response string */
-#define MAX_RESP_SIZE 512	/* Max. size of a response string */
+#define MAX_RESP_SIZE 511	/* Max. size of a response string */
 
 #define MAX_EVENTS 64		/* size of event queue */
 
@@ -498,7 +498,7 @@ struct cardstate {
 	spinlock_t ev_lock;
 
 	/* current modem response */
-	unsigned char respdata[MAX_RESP_SIZE];
+	unsigned char respdata[MAX_RESP_SIZE+1];
 	unsigned cbytes;
 
 	/* private data of hardware drivers */
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index 85394a6..16fd3bd 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,
 
 /* == data input =========================================================== */
 
+/* process a block of received bytes in command mode (mstate != MS_LOCKED)
+ * Append received bytes to the command response buffer and forward them
+ * line by line to the response handler.
+ * Note: Received lines may be terminated by CR, LF, or CR LF, which will be
+ * removed before passing the line to the response handler.
+ */
 static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf)
 {
 	struct cardstate *cs = inbuf->cs;
 	unsigned cbytes      = cs->cbytes;
+	unsigned char c;
 
 	while (numbytes--) {
-		/* copy next character, check for end of line */
-		switch (cs->respdata[cbytes] = *src++) {
-		case '\r':
+		c = *src++;
+		switch (c) {
 		case '\n':
-			/* end of line */
-			gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
-				__func__, cbytes);
-			if (cbytes >= MAX_RESP_SIZE - 1)
-				dev_warn(cs->dev, "response too large\n");
+			if (cbytes == 0 && cs->respdata[0] == '\r') {
+				/* collapse LF with preceding CR */
+				cs->respdata[0] = 0;
+				break;
+			}
+			/* --v-- fall through --v-- */
+		case '\r':
+			/* end of message line, pass to response handler */
+			if (cbytes >= MAX_RESP_SIZE) {
+				dev_warn(cs->dev, "response too large (%d)\n",
+					 cbytes);
+				cbytes = MAX_RESP_SIZE;
+			}
 			cs->cbytes = cbytes;
+			gigaset_dbg_buffer(DEBUG_TRANSCMD, "received response",
+					   cbytes, cs->respdata);
 			gigaset_handle_modem_response(cs);
 			cbytes = 0;
+
+			/* store EOL byte for CRLF collapsing */
+			cs->respdata[0] = c;
 			break;
 		default:
-			/* advance in line buffer, checking for overflow */
-			if (cbytes < MAX_RESP_SIZE - 1)
-				cbytes++;
+			/* append to line buffer if possible */
+			if (cbytes < MAX_RESP_SIZE)
+				cs->respdata[cbytes] = c;
+			cbytes++;
 		}
 	}
 
@@ -958,8 +978,6 @@ void gigaset_isoc_input(struct inbuf_t *inbuf)
 					   numbytes, src);
 			gigaset_if_receive(inbuf->cs, src, numbytes);
 		} else {
-			gigaset_dbg_buffer(DEBUG_CMD, "received response",
-					   numbytes, src);
 			cmd_loop(src, numbytes, inbuf);
 		}
 
-- 
1.6.5.3.298.g39add

  parent reply	other threads:[~2010-02-22 23:09 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-22 23:08 [PATCH 0/4] gigaset: patches for 2.6.34 Tilman Schmidt
2010-02-22 23:08 ` [PATCH 1/4] gigaset: small documentation improvement Tilman Schmidt
2010-02-22 23:09 ` Tilman Schmidt [this message]
2010-02-23  6:34   ` [PATCH 2/4] bas_gigaset: collapse CR/LF at end of AT response Simon Horman
2010-02-23 13:19     ` Tilman Schmidt
2010-02-23 21:43       ` Simon Horman
2010-02-22 23:09 ` [PATCH 3/4] gigaset: reduce syslog clutter Tilman Schmidt
2010-02-22 23:10 ` [PATCH 4/4] isdn: remove ishexdigit() in regard to isxdigit() Tilman Schmidt
2010-02-26  9:24 ` [PATCH 0/4] gigaset: patches for 2.6.34 David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100221-patch-gigaset-02.tilman@imap.cc \
    --to=tilman@imap.cc \
    --cc=davem@davemloft.net \
    --cc=hjlipp@web.de \
    --cc=i4ldeveloper@listserv.isdn4linux.de \
    --cc=isdn4linux@listserv.isdn4linux.de \
    --cc=isdn@linux-pingi.de \
    --cc=keil@b1-systems.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).