Description: fix SOL disconnects due to 0x29 message
 amtterm disconnects with the following error.
 amtterm: RUN_SOL -> ERROR (failure)
 amtterm: ERROR: redir_data: unknown r->buf 0x29
 This has already been resolved upstream via 6d5a429a and 0ece513 
 which provide support for 0x29 message, to avoid errant disconnects.

Author: Dave Chiluk <chiluk@canonical.com>

---
Origin: upstream, https://www.kraxel.org/cgit/amtterm/commit/?h=0ece5135fef56dbd0d94957c334655a57adb7212
Origin: upstream, https://www.kraxel.org/cgit/amtterm/commit/?h=6d5a429ab96363aeeb9a91a5ab8fddddf14e2aaa
Bug-Debian: http://bugs.debian.org/681210
Bug-Ubuntu: https://launchpad.net/bugs/1301692

--- amtterm-1.3.orig/RedirectionConstants.h
+++ amtterm-1.3/RedirectionConstants.h
@@ -24,6 +24,8 @@
 #define SOL_KEEP_ALIVE_PING                 0x24  //Console to Host
 #define SOL_KEEP_ALIVE_PONG                 0x25  //Host to Console
 #define SOL_DATA_TO_HOST                    0x28  //Console to host
+#define SOL_CONTROLS_FROM_HOST              0x29  //Host to Console
+
 #define SOL_DATA_FROM_HOST                  0x2A  //Host to Console
 #define SOL_HEARTBEAT                       0x2B
 
@@ -33,6 +35,19 @@
 #define END_SOL_REDIRECTION_LENGTH             8
 #define END_SOL_REDIRECTION_REPLY_LENGTH       8
 
+// Control message control bits (message 0x29)
+#define RTS_CONTROL                            1
+#define DTR_CONTROL                            2 
+#define BREAK_CONTROL                          4
+
+// Control message status bits (message 0x29)
+#define TX_OVERFLOW                            1
+#define LOOPBACK_ACTIVE                        2
+#define SYSTEM_POWER_STATE                     4
+#define RX_FLUSH_TIMEOUT                       8
+#define TESTMODE_ACTIVE                       16
+
+
 //IDER Messages Formats
 #define START_IDER_REDIRECTION              0x40
 #define START_IDER_REDIRECTION_REPLY        0x41
--- amtterm-1.3.orig/redir.c
+++ amtterm-1.3/redir.c
@@ -298,6 +298,9 @@ int redir_sol_recv(struct redir *r)
     return bshift;
 }
 
+static int in_loopback_mode = 0;
+static int powered_off = 0;
+
 int redir_data(struct redir *r)
 {
     int rc, bshift;
@@ -382,6 +385,55 @@ int redir_data(struct redir *r)
 		goto again;
 	    redir_stop(r);
 	    break;
+	case SOL_CONTROLS_FROM_HOST: {
+	  bshift = r->blen; /* FIXME */
+	  if (r->blen < bshift)
+	    goto again;
+	  
+	  /* Host sends this message to the Management Console when
+	   * the host has changed its COM port control lines. This
+	   * message is likely to be one of the first messages that
+	   * the Host sends to the Console after it starts SOL
+	   * redirection.
+	   */
+	  struct controls_from_host_message *msg = (struct controls_from_host_message *) r->buf;
+	  //printf("Type %x, control %d, status %d\n", msg->type, msg->control, msg->status);
+	  if (msg->status & LOOPBACK_ACTIVE) {
+	    if (r->verbose)
+	      fprintf (stderr, "Warning, SOL device is running in loopback mode.  Text input may not be accepted\n");
+	    in_loopback_mode = 1;
+	  } else if (in_loopback_mode) {
+	    if (r->verbose)
+	      fprintf (stderr, "SOL device is no longer running in loopback mode\n");
+	    in_loopback_mode = 0;
+	  }
+
+	  if (0 == (msg->status & SYSTEM_POWER_STATE))  {
+	    if (r->verbose)
+	      fprintf (stderr, "The system is powered off.\n");
+	    powered_off = 1;
+	  } else if (powered_off) {
+	    if (r->verbose)
+	      fprintf (stderr, "The system is powered on.\n");
+	    powered_off = 0;
+	  }
+	  
+	  if (r->verbose) {
+	    if (msg->status & (TX_OVERFLOW|RX_FLUSH_TIMEOUT|TESTMODE_ACTIVE))
+	      fprintf (stderr, "Other unhandled status condition\n");
+	    
+	    if (msg->control & RTS_CONTROL) 
+	      fprintf (stderr, "RTS is asserted on the COM Port\n");
+	    
+	    if (msg->control & DTR_CONTROL) 
+	      fprintf (stderr, "DTR is asserted on the COM Port\n");
+	    
+	    if (msg->control & BREAK_CONTROL) 
+	      fprintf (stderr, "BREAK is asserted on the COM Port\n");
+	  }
+
+	  break;
+	}
 	default:
 	    snprintf(r->err, sizeof(r->err), "%s: unknown r->buf 0x%02x",
 		     __FUNCTION__, r->buf[0]);
--- amtterm-1.3.orig/redir.h
+++ amtterm-1.3/redir.h
@@ -1,4 +1,5 @@
 #include "RedirectionConstants.h"
+#include <stdint.h>
 
 enum redir_state {
     REDIR_NONE      =  0,
@@ -38,6 +39,14 @@ struct redir {
     int (*cb_recv)(void *cb_data, unsigned char *buf, int len);
 };
 
+struct __attribute__ ((__packed__)) controls_from_host_message {
+    unsigned char type; // 0x29
+    unsigned char reserved[3];
+    uint32_t      host_sequence_number;
+    unsigned char control; 
+    unsigned char status;
+};
+
 const char *redir_state_name(enum redir_state state);
 const char *redir_state_desc(enum redir_state state);
 
