--- a/ifcico/emsi.c
+++ b/ifcico/emsi.c
@@ -225,6 +225,380 @@ char* data;
 	else return txwazoo();
 }
 
+#ifdef EXPERIMENTAL_EMSI
+
+SM_DECL(rxemsi,"rxemsi")
+SM_STATES
+	sendnak, resettimer, waitpkt, waitchar, getdat, getdatchar, checkdat
+SM_NAMES
+	"sendnak", "resettimer", "waitpkt", "waitchar", "getdat", "getdatchar",
+	"checkdat"
+SM_EDECL
+
+	int c=0;
+	unsigned short lcrc,rcrc;
+	int len = 0;
+	int standby=0,tries=0;
+	char buf[13], *p = buf;
+	char *databuf=NULL;
+
+	tries = 0;
+	SETTIMER(0, 20);
+	SETTIMER(1, 60);
+
+SM_START(sendnak)
+
+SM_STATE(sendnak)
+
+	++tries;
+	if (tries > 6)
+	{
+		loginf("too many tries waiting for EMSI handshake");
+		SM_ERROR;
+	}
+	if (!caller)
+	{
+		PUTSTR("**EMSI_REQA77E\r\021");
+		SM_PROCEED(resettimer);
+	}
+	if (tries > 1)
+	{
+		PUTSTR("**EMSI_NAKEEC3\r\021");
+		SM_PROCEED(resettimer);
+	}
+
+	SM_PROCEED(waitpkt);
+
+
+SM_STATE(resettimer)
+
+	SETTIMER(0, 20);
+	SM_PROCEED(waitpkt);
+
+
+SM_STATE(waitpkt)
+
+	len = 0;
+	standby = 0;
+	p = buf;
+	SM_PROCEED(waitchar);
+
+
+SM_STATE(waitchar)
+
+	c = GETCHAR(-1);
+
+	if (c == TIMEOUT)
+	{
+		if (EXPIRED(1))
+		{
+			loginf("timeout waiting for EMSI handshake");
+			SM_ERROR;
+		}
+		if (EXPIRED(0))
+		{
+			SM_PROCEED(sendnak);
+		}
+	}
+	else if (c < 0)
+	{
+		SM_ERROR;
+	}
+	else if ((c >= ' ') && (c <= '~'))
+	{
+		if (c == '*')
+		{
+			if (len)
+			{
+				standby = 1;
+				len = 0;
+			}
+			else
+			{
+				++standby;
+				debug(DBG_HANDSHAKE, "set standby=%d",
+				      standby);
+			}
+		}
+		else if (standby >= 2)
+		{
+			*p++ = c;
+			len++;
+			debug(DBG_HANDSHAKE, "set len=%d", len);
+
+			if (len == 12)
+			{
+				*p = 0;
+				standby = 0;
+				p = buf;
+				len = 0;
+
+				if (!strncasecmp(buf, "EMSI_DAT", 8))
+				{
+					SM_PROCEED(getdat);
+				}
+				else if (!strncasecmp(buf, "EMSI_HBT", 8))
+				{
+					lcrc=crc16(buf,8);
+					sscanf(buf+8,"%04hx",&rcrc);
+
+					if (lcrc == rcrc)
+					{
+						SM_PROCEED(resettimer);
+					}
+					else
+					{
+						debug(DBG_HANDSHAKE,
+						      "ignoring 'EMSI_HBT' with invalid CRC");
+					}
+				}
+				else if (!strncasecmp(buf, "EMSI_", 5))
+				{
+					debug(DBG_HANDSHAKE,
+					      "ignoring packet '%s'", buf);
+				}
+			}
+
+		}
+	}
+	else
+	{
+		debug(DBG_HANDSHAKE, "ignoring '%c'", printablec(c));
+	}
+
+	/* SM_PROCEED(waitchar); */
+
+
+SM_STATE(getdat)
+
+	debug(DBG_HANDSHAKE,"try get emsi_dat packet starting with \"%s\"",
+	      buf);
+
+	if (sscanf(buf+8,"%04x",&len) != 1)
+	{
+		SM_PROCEED(sendnak);
+	}
+
+	len += 16; /* strlen("EMSI_DATxxxxyyyy"), include CRC */
+	if (databuf) free(databuf);
+	databuf=xmalloc(len+1);
+	strcpy(databuf,buf);
+	p=databuf+strlen(databuf);
+
+	SM_PROCEED(getdatchar);
+
+SM_STATE(getdatchar)
+
+	c = GETCHAR(-1);
+
+	if (c == TIMEOUT)
+	{
+		if (EXPIRED(1))
+		{
+			loginf("timeout waiting for EMSI handshake");
+			SM_ERROR;
+		}
+
+		SM_PROCEED(sendnak);
+	}
+	else if (c < 0)
+	{
+		loginf("error while reading EMSI_DAT packet");
+		SM_ERROR;
+	}
+
+	*p++ = c;
+
+	if ((p - databuf) == len)
+	{
+		SM_PROCEED(checkdat);
+	}
+
+	/* SM_PROCEED(getdatchar); */
+
+
+SM_STATE(checkdat)
+
+	databuf[len] = '\0';
+	sscanf(databuf + len - 4, "%04hx", &rcrc);
+	lcrc = crc16(databuf, len - 4);
+	if (lcrc != rcrc)
+	{
+		loginf("got EMSI_DAT packet \"%s\" with bad crc: %04x/%04x",
+		       printable(databuf,0),lcrc,rcrc);
+		SM_PROCEED(sendnak);
+	}
+
+	PUTSTR("**EMSI_ACKA490\r\021");
+	PUTSTR("**EMSI_ACKA490\r\021");
+
+	if (scanemsidat(databuf + 12) == 0)
+	{
+		SM_SUCCESS;
+	}
+	else
+	{
+		SM_ERROR;
+	}
+
+SM_END
+
+
+	if (databuf)
+	{
+		free(databuf);
+	}
+
+	RESETTIMERS();
+
+SM_RETURN
+
+
+SM_DECL(txemsi,"txemsi")
+SM_STATES
+	senddata, resettimer, waitpkt, waitchar
+SM_NAMES
+	"senddata", "resettimer", "waitpkt", "waitchar"
+SM_EDECL
+
+	int c;
+	unsigned short lcrc,rcrc;
+	int len = 0;
+	int standby=0,tries=0;
+	char buf[13], *p = buf;
+	char trailer[8];
+
+	SETTIMER(0, 60);
+
+
+SM_START(senddata)
+
+SM_STATE(senddata)
+
+	p=mkemsidat(caller);
+	PUTCHAR('*');
+	PUTCHAR('*');
+	PUTSTR(p);
+	sprintf(trailer,"%04X\r\021",crc16(p,strlen(p)));
+	PUTSTR(trailer);
+	free(p);
+
+	++tries;
+	if (tries > 6)
+	{
+		loginf("too many tries sending EMSI");
+		SM_ERROR;
+	}
+
+	SM_PROCEED(resettimer);
+
+
+SM_STATE(resettimer)
+
+	SETTIMER(1, 20);
+	SM_PROCEED(waitpkt);
+
+
+SM_STATE(waitpkt)
+
+	len = 0;
+	standby = 0;
+	p = buf;
+	SM_PROCEED(waitchar);
+
+
+SM_STATE(waitchar)
+
+	c = GETCHAR(-1);
+
+	if (c == TIMEOUT)
+	{
+		if (EXPIRED(0))
+		{
+			loginf("timeout waiting for EMSI handshake");
+			SM_ERROR;
+		}
+		if (EXPIRED(1))
+		{
+			SM_PROCEED(senddata);
+		}
+	}
+	else if (c < 0)
+	{
+		SM_ERROR;
+	}
+	else if ((c >= ' ') && (c <= '~'))
+	{
+		if (c == '*')
+		{
+			if (len)
+			{
+				standby = 1;
+				len = 0;
+			}
+			else
+			{
+				++standby;
+				debug(DBG_HANDSHAKE, "set standby=%d",
+				      standby);
+			}
+		}
+		else if (standby >= 2)
+		{
+			*p++ = c;
+			len++;
+			debug(DBG_HANDSHAKE, "set len=%d", len);
+
+			if (len == 12)
+			{
+				*p = 0;
+				standby = 0;
+				p = buf;
+				len = 0;
+
+				if (!strncasecmp(buf, "EMSI_REQ", 8))
+				{
+					SM_PROCEED(waitpkt);
+				}
+				else if (!strncasecmp(buf, "EMSI_ACK", 8))
+				{
+					lcrc=crc16(buf,8);
+					sscanf(buf+8,"%04hx",&rcrc);
+
+					if (lcrc == rcrc)
+					{
+						SM_SUCCESS;
+					}
+					else
+					{
+						debug(DBG_HANDSHAKE,
+						      "ignoring 'EMSI_ACK' with invalid CRC");
+					}
+				}
+				else
+				{
+					SM_PROCEED(senddata);
+				}
+			}
+
+		}
+	}
+	else
+	{
+		debug(DBG_HANDSHAKE, "ignoring '%c'", printablec(c));
+	}
+
+	/* SM_PROCEED(waitchar); */
+
+
+SM_END
+
+	RESETTIMERS();
+
+SM_RETURN
+
+#else  /* EXPERIMENTAL_EMSI */
+
 SM_DECL(rxemsi,"rxemsi")
 SM_STATES
 	waitpkt,waitchar,checkemsi,getdat,checkpkt,checkdat,
@@ -576,3 +950,5 @@ SM_STATE(sendack)
 
 SM_END
 SM_RETURN
+
+#endif /* EXPERIMENTAL_EMSI */
