diag: Wrap Delayed Response ID when it reaches its Maximum Value

DIAG now has new commands to wrap the delayed response ID back to
its initial value when the maximum value is reached. It now has a
command to retrieve the number of times this wrapping has
taken place and to retrieve a flag that denotes the wrap status.

Change-Id: Ia8fcf945ce0561241962d4d0841b80ff4c257324
CRs-Fixed: 397346
Signed-off-by: Ravi Aravamudhan <aravamud@codeaurora.org>
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 0b395c5..79f20a4 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -321,4 +321,8 @@
 
 extern struct diag_bridge_dev *diag_bridge;
 extern struct diagchar_dev *driver;
+
+extern int wrap_enabled;
+extern uint16_t wrap_count;
+
 #endif
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 6a7f55f..f6c26c3 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -84,11 +84,23 @@
 static int token_list[MAX_PROC] = {0, -1, -2, -3, -4, -5, -6, -7, -8, -9};
 
 #define DIAGPKT_MAX_DELAYED_RSP 0xFFFF
-/* This macro gets the next delayed respose id. Once it reaches
- DIAGPKT_MAX_DELAYED_RSP, it stays at DIAGPKT_MAX_DELAYED_RSP */
 
-#define DIAGPKT_NEXT_DELAYED_RSP_ID(x) 				\
-((x < DIAGPKT_MAX_DELAYED_RSP) ? x++ : DIAGPKT_MAX_DELAYED_RSP)
+/* returns the next delayed rsp id - rollsover the id if wrapping is
+   enabled. */
+uint16_t diagpkt_next_delayed_rsp_id(uint16_t rspid)
+{
+	if (rspid < DIAGPKT_MAX_DELAYED_RSP)
+		rspid++;
+	else {
+		if (wrap_enabled) {
+			rspid = 1;
+			wrap_count++;
+		} else
+			rspid = DIAGPKT_MAX_DELAYED_RSP;
+	}
+	delayed_rsp_id = rspid;
+	return delayed_rsp_id;
+}
 
 #define COPY_USER_SPACE_OR_EXIT(buf, data, length)		\
 do {								\
@@ -534,7 +546,7 @@
 		if ((delay_params.rsp_ptr) &&
 		 (delay_params.size == sizeof(delayed_rsp_id)) &&
 				 (delay_params.num_bytes_ptr)) {
-			interim_rsp_id = DIAGPKT_NEXT_DELAYED_RSP_ID(
+			interim_rsp_id = diagpkt_next_delayed_rsp_id(
 							delayed_rsp_id);
 			if (copy_to_user((void *)delay_params.rsp_ptr,
 					 &interim_rsp_id, sizeof(uint16_t)))
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 6b4c337..0bd26cf 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -51,6 +51,8 @@
 struct diag_master_table entry;
 struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
 struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
+int wrap_enabled;
+uint16_t wrap_count;
 
 void encode_rsp_and_send(int buf_length)
 {
@@ -896,6 +898,23 @@
 			return 0;
 		}
 	}
+	/* Return the Delayed Response Wrap Status */
+	else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
+		(*(buf+2) == 0x04) && (*(buf+3) == 0x0)) {
+		memcpy(driver->apps_rsp_buf, buf, 4);
+		driver->apps_rsp_buf[4] = wrap_enabled;
+		encode_rsp_and_send(4);
+		return 0;
+	}
+	/* Wrap the Delayed Rsp ID */
+	else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
+		(*(buf+2) == 0x05) && (*(buf+3) == 0x0)) {
+		wrap_enabled = true;
+		memcpy(driver->apps_rsp_buf, buf, 4);
+		driver->apps_rsp_buf[4] = wrap_count;
+		encode_rsp_and_send(5);
+		return 0;
+	}
 	 /* Check for ID for NO MODEM present */
 	else if (chk_polling_response()) {
 		/* respond to 0x0 command */
@@ -1449,6 +1468,8 @@
 	int success;
 	int i;
 
+	wrap_enabled = 0;
+	wrap_count = 0;
 	diag_debug_buf_idx = 0;
 	driver->read_len_legacy = 0;
 	driver->use_device_tree = has_device_tree();