
//
// Trust Design LLC : SECS/HSMS Communication library
//
// (c) Copyright Trust Design LLC.  2010-2024.  All rights reserved.
//


// =============================================================================
//
// JavaIo : Test and sample program
//
//   In a pure Java environment using only TDS.jar without using JNA (and thus
//   not using TDS.dll), use Callback function to handle incoming messages.
//
//   (Note) In this sample, when making an HSMS connection, it is assumed that
//	the HOST side executes Passive connection and the EQUIP side executes
//	Active connection.
//
//
// Starting method
//
//   java JavaIo {h|e} [option [send_wait [send_sleep]]]
//   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//   h    : Refer to [HOST]  section of Sample.ini to determine operation
//   e    : Refer to [EQUIP] section of Sample.ini to determine operation
//
//   option : Options for setting the details of operation (optional)
//	      Specify as a decimal number or as a hexadecimal number with 0x or
//	      x as a prefix.
//	      The details of the specified value for each bit are shown below.
//			   5  3210
//	      +----+----+----+----+
//			   |  |||+-- Function to use
//			   |  |||    =0: _TDSCommXxxxx()  1:_TDSUDrvXxxx()
//			   |  ||+--- SECS Header Byte order
//			   |  ||     =0: System order	  1: Network order
//			   |  |+---- Format for displaying messages in SECS
//			   |  |	     list format
//			   |  |	     =0: TDS Format	  1: SML Format
//			   |  +----- Whether to use MssgNextL() for SECS
//			   |	     message display
//			   |	     =0: Not use	  1: Use
//			   +-------- Whether to execute SECS message reception
//				     in a dedicated thread
//				     =0: No		  1: Yes
//
//   send_wait   : Transmission interval when sending continuous messages (ms).
//   send_sleep  : Time to rest for a short time after sending a given number
//                 of times (SEND_NO) when sending continuous messages (ms).
//
//   Normally, "JavaIo h" and "JavaIo e" both operate on same machine or
//   different machines to communicate with each other. The communication
//   partner may be BasicIo.exe or Callbackio.exe.
//
//   After startup, refer to the menu display, enter request code etc. and the
//   function is executed.
// 
//   When host starts up, it waits for a connection from equipment.
//   When device side is started, connection request and Select request are
//   automatically issued to host side.
//   On host side, repeat '1:Recv' processing, and confirm that display is
//   'STATUS=951: No data'. After that, exchange any message. On receiving side,
//   do not forget to reap received data until 'STATUS=951'.
//
//   The transaction ID used when sending secondary message uses that of primary
//   message received immediately before.
//
//   This sample omits some of abnormal processing.
//
//   "SECS_MODE" defined below is defined to determine whether or not connection
//   processing to Passive side in case of Active connection is performed when
//   using _TDSCommXxxx() as processing function.
//   using _TDJVSCommXxxx() as processing function.
//   (Note) Changing this value alone does not make TDS aware of the change in
//      SECS1 or HSMS.  TDS determines SECS1 or HSMS based on the setting of
//      SECSMODE in the configuration file (.ini).  To change this value, you
//      must change the setting of SECSMODE in .ini.
//
//   If the second parameter (option) at startup is not specified, the details
//   of operation are determined by the following constants.
//
//   "FUNC_TYPE" is defined to select type of processing function to be used.
//   If you use _TDSUDrvXxxx(), there is no need to perform connection
//   processing for HSMS-SS Active connection, so there is no need to set
//   "SECS_MODE" in principle.
//   Since TDS switches SECS-1 connection or HSMS-SS connection in setting file
//   (.ini), user AP does not need to know connection method (SECS-1or HSMS and
//   Passive/Active at HSMS) as long as _TDSUDrvXxxx() is used as processing
//   function.
//
//   By changing values of "MSSG_DISP_TYPE" defined below, you can change output
//   format of SECS message displayed by this AP.
//   By changing value of "MSSG_USE_NEXTL", it is possible to change whether to
//   acquire field values as data or display list format when analyzing message
//   contents.
//   If "HEADER_BO" is set to 1, Byte Order of SECS message header obtained at
//   the time of Receive and Send can be obtained as the original network Byte
//   Order of the SECS message.
//   Similarly, when "USE_RECVTHREAD" is set to =1, a thread for performing
//   receiving process is activated, and display of received message and output
//   of the secondary message are automatically performed in the thread.
//   When using the receiving thread, keep in mind that prompt message may be
//   distorted.
//
//
// =============================================================================
//
// JavaIo : テスト 及び サンプル・プログラム
//
//   JNA を使用せず（従って TDS.dll を使用せず）TDS.jar のみを使用した純 Java
//   環境ので動作で Callback 関数を使用して受信メッセージに対する応答処理を行う。
//
//   (注) 本サンプルでは HSMS 接続する場合、HOST 側が Passive 接続、EQUIP 側が
//	Active 接続を実行すると仮定している。
//
//
// 起動方法
//
//   java JavaIo {h|e} [option [send_wait [send_sleep]]]
//   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//   h    : Sample.ini の [HOST]  セクションを参照し動作を決定する
//   e    : Sample.ini の [EQUIP]      :              :
//
//   option : 動作の詳細を設定するオプション (省略可能)
//	      10進数 もしくは 接頭文字として 0x もしくは x を付与した 16進数
//	      で指定する。
//	      以下に指定値のビット毎の詳細を以下に示す。
//			   5  3210
//	      +----+----+----+----+
//			   |  |||+-- 使用する関数
//			   |  |||    =0: _TDSCommXxxxx() 1:_TDSUDrvXxxx()
//			   |  ||+--- SECS Header Byte order
//			   |  ||     =0: System order	 1: Network order
//			   |  |+---- SECS リスト形式でメッセージを表示する
//			   |  |	     場合の形式
//			   |  |	     =0: TDS 形式	 1: SML 形式
//			   |  +----- SECS メッセージ表示に MssgNextL() を使用
//			   |	     するか否か
//			   |	     =0: 使用しない	 1: 使用する
//			   +-------- SECS メッセージ受信を専用スレッドで実行
//			 	     するか否か
//				     =0: No		 1: Yes
//
//   send_wait   : 連続メッセージ送信時の送信間隔 (ms)
//   send_sleep  : 連続メッセージ送信時に所定の回数 (SEND_NO) 送信した後に少し
//                 送信をお休みする時間 (ms)
//
//   通常、JavaIo h 及び JavaIo e の両方を、同一マシン、もしくは異なるマシン上
//   で動作させて、相互通信を行う。通信相手は、BasicIo.exe、Callbackio.exe でも
//   よい。
//
//   起動後、メニュ表示を参照し、要求コード等を入力し、機能を実行する。
// 
//   ホスト側は起動すると、装置側からの接続を待つ。装置側を起動すると、自動的
//   にホスト側に接続要求、Select 要求を発行する。ホスト側では、1:Recv 処理を
//   繰り返し行い、表示が「STATUS=951 : No data」となるのを確認する。その後、
//   任意のメッセージのやりとりを行う。受信側では、受信データの刈り取りを「
//   STATUS=951」になるまで行うことを忘れぬこと。
//
//   ２次メッセージを送信する際のトランザクションＩＤは、直前に受信した１次
//   メッセージのものを使用する。
//
//   本サンプルは、異常時処理を一部省略している。
//
//   以下で定義する "SECS_MODE" は、処理関数として _TDSCommXxxx() を使用する
//   場合で Active 接続の場合の Passive 側への接続処理の実行の有無を判断する
//   ために定義する。
//   (注) この値の変更だけで TDS が SECS1 or HSMS の変更を認識するわけではない。 
//      TDS は SECS1 or HSMS を判断するのは設定ファイル (.ini) の SECSMODE の
//      設定によるので、この値を変更する場合は .ini の SECSMODE の設定変更を
//      しなければならない。
//
//   起動時の2番目のパラメータ (option) を指定しない場合は、以下の定数により
//   動作の詳細を決定する。
//
//   "FUNC_TYPE" は、使用する処理関数の種別を選択するために定義する。
//   _TDSUDrvXxxx() を使用する場合は、HSMS-SS Active 接続の場合の接続処理を
//   行う必要がないので、本来であれば "SECS_MODE" の設定も必要がない。
//   TDS は、SECS-1 接続 or HSMS-SS 接続の切替は、設定ファイル (.ini) にて行う
//   ため、処理関数として _TDSUDrvXxxx() を使用する限りは、ユーザＡＰでは、
//   接続方式（SECS-1/HSMS-SS そして HSMS-SS時の Passive/Active）を知る必要は
//   ない。
//
//   以下で定義する "MSSG_DISP_TYPE" の値を変更すると、本ＡＰにて表示する SECS
//   メッセージの出力形式を変更できる。
//   "MSSG_USE_NEXTL" の値を変更すると、メッセージ内容を解析する際に、項目値を
//   データとして取得するか、表示リスト形式で取得するかを変更できる。
//   "HEADER_BO" を 1 とすると、Receive、Send 時に取得する SECS メッセージ・
//   ヘッダのバイトオーダーを SECS メッセージ本来のネットワーク・バイトオーダー
//   として取得できる。
//   同様に "USE_RECVTHREAD" を =1 とすると、受信処理を行うスレッドを起動し、そ
//   のスレッド内で受信メッセージの表示、２次メッセージの出力を自動で行う。
//   受信スレッドを使用する場合、入力促進用メッセージに乱れが生じる事に留意
//   すること。
//
// =============================================================================

import		java.lang.*;
import		java.util.*;
import		java.io.*;
import		java.nio.*;

import 		TDL.TDS.TDSComm;
import 		TDL.TDS.TDSUDrv;
import 		TDL.TDS.TDSMssg;


public class	JavaIo{


// -----------------------------------------------------------------------------

static final int	E_BADF		=9;
static final int	E_BUSY		=16;
static final int	E_NOMEM		=12;
static final int	E_NODEV		=19;
static final int	E_2BIG		=7;

static final int	E_NOTCONNECT	=999;
static final int	E_DESELECT	=998;
static final int	E_REJECT	=997;
static final int	E_SEPARATE	=996;
static final int	E_SELECT	=992;
static final int	E_CONNECT	=991;
static final int	E_RETRYOVER	=989;
static final int	E_T8TIMEDOUT	=988;
static final int	E_T7TIMEDOUT	=987;
static final int	E_T6TIMEDOUT	=986;
static final int	E_T5TIMEDOUT	=985;
static final int	E_T4TIMEDOUT	=984;
static final int	E_T3TIMEDOUT	=983;
static final int	E_T2TIMEDOUT	=982;
static final int	E_T1TIMEDOUT	=981;
static final int	E_ILLBLOCK	=980;
static final int	E_NODATA	=951;

static final int	XMSGSIZE	=(1024*1024);


// -----------------------------------------------------------------------------

static final int	SECS_MODE	=1;	// SECS/HSMS mode
						// 0    : SECS-1
						// 1    : HSMS
						// (Note) See comments above
						// (注) 上部コメント参照
static final int	UDRV_MASK  =0x8383ffff;	// Mask value of UDrvOpen()
						// 0          : Set =0x49
						// 0x8383ffff : All event

static final int	FUNC_TYPE	=1;	// Type of function used
						// 通信に使用する関数の種別
						// 0    : _TDSCommXxxxx
						// 1    : _TDSUDrvXxxxx
static final int	HEADER_BO	=0;	// Header byte order
						// 取得するヘッダの Byte Order
						// 0    : System  Order
						// 1    : Network Order
static final int	MSSG_DISP_TYPE	=0x20;	// SECS Message display format
						// 0x00 : TDS Format
						// 0x20 : SML Format
static final int	MSSG_USE_NEXTL	=1;	// Use MssgNextL() or not
						// 0    : Not use
						// 1    : Use

static final int	USE_RECVTHREAD	=1;	// Execute receiving process on
						// its own thread
						// 受信処理を自前スレッドで実行
						// 0    : No
						// 1    : Yes

static final int	SEND_WAIT	=200;	// Message sending interval (ms)
static final int	SEND_NO		=10;	// #of times until message
						// transmission break
static final int	SEND_SLEEP	=1000;	// Waiting time		    (ms)
static final int	ERROR_SLEEP	=1000;	// Waiting time when an  error 
						// occurs		    (ms)

static final String	PARAMFILE	="Sample.ini";


// -----------------------------------------------------------------------------

static int		FuncType	=FUNC_TYPE;		// argv[1]&0x0001
static int		HeaderBO	=HEADER_BO;		// argv[1]&0x0002
static int		MssgDispType	=MSSG_DISP_TYPE;	// argv[1]&0x0004
static int		MssgUseNextL	=MSSG_USE_NEXTL;	// argv[1]&0x0008
static int		UseRecvThrd	=USE_RECVTHREAD;	// argv[1]&0x0020

static int		SendWait	=SEND_WAIT;		// argv[2]
static int		SendSleep	=SEND_SLEEP;		// argv[3]

static TDSComm		SAcb;		// SECS Communication class
static TDSUDrv		UAcb;		// SECS Communication class
static int		OType=0;	// Operation type  (0:Host  1:Equipment)
static int		Break=0;	// End instruction to thread
					// スレッド終了指示

static int		cnt249=0;
static int		cnt250=0;
static int		cnt611=0;


// =============================================================================
// Common functions ============================================================

static private void
printf(
String		form,
Object...	arg)
{
  try{
    System.out.printf(form,arg);
  }catch(UnknownFormatConversionException	err){
    System.out.printf("Format error\n");
  }catch(Exception				err){
    System.out.printf("Printf error\n");
  }
}


// -----------------------------------------------------------------------------

static private void
Sleep(
int		msec)
{
  try{
    Thread.sleep((long)msec);
  }catch(InterruptedException	err){
  }catch(Exception		err){
  }finally{
  }
}


// -----------------------------------------------------------------------------

static private String
ReadLine(			//  o : Input string
BufferedReader	in,		// i  : Input descriptor
String		msg)		// i  : Input promotion message
{
  String	line;

  for(;;){
    printf("%s"	,msg);
    try{			line=in.readLine();
    }catch(Exception		err){			continue;
    }							break;
  }

  return(line);
}


static private int
ReadInt(			//  o : Input value
BufferedReader	in,		// i  : Input descriptor
String		msg,		// i  : Input promotion message
int		base)		// i  : Radix of integer
{
  String	line;
  int		val;

  for(;;){
    line=ReadLine(in,msg);
    try{			val=Integer.parseInt(line,base);
    }catch(Exception		err){			continue;
    }							break;
  }

  return(val);
}


// -----------------------------------------------------------------------------
// Display SECS messages on standard output ------------------------------------
// SECS メッセージを標準出力に表示する。 ---------------------------------------

static private void
DispSECSMssg(			//
int		tp,		// i  : Message type
				//	=0 : Transmission result
				//	 1 : Received message
				//	 2 : Send message
byte		hd[],		// i  : SECS Message Header
int		did,		// i  : SECS Message Device ID
int		sf,		// i  : SECS Message SF-Code
int		xid,		// i  : SECS Message Transaction ID
byte		msg[],		// i  : SECS Message strage area
				//	     (Header not included)
int		len)		// i  : SECS Message byte length
{
  String	ctp[]={"SRES","RECV","SEND"};
  String	rbit,wbit,sdid,sfcode,c;
  StringBuffer	mname=new StringBuffer(),sitem=new StringBuffer();
  ByteBuffer	pm;
  TDSMssg	mcb=new TDSMssg();
  byte		msg1[];
  long		ul;
  int		form[]=new int[1],sz[]=new int[1],noi[]=new int[1];
  int		rtn,md=0,dp=MssgDispType,fm=0,la,i,j;

  rbit=" ";	if((did&0x8000)!=0)	rbit="R";
  wbit=" ";	if((sf &0x8000)!=0)	wbit="W";
  if(did< 0)	sdid=String.format("%6d"	,did);
  else		sdid=String.format("0x%04x"	,did);
  sfcode=String.format("S%dF%d",(sf&0x7f00)/0x0100,sf&0xff);
  printf("[%s]  Dev=%-6s  %-8s  %s%s  XId=0x%04x.%04x  Len=%4d"+
	 "  Head=0x%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n"
		,ctp[tp],sdid,sfcode,rbit,wbit
		,(xid>>16)&0xffff,xid&0xffff,len
		,hd[0],hd[1],hd[2],hd[3],hd[4],hd[5],hd[6],hd[7],hd[8],hd[9]);

  if(len>0){
    if(tp==1){	dp|=0x3000;	fm|=0x3000;}	// In case of receiving
    else{	dp|=0x2000;	fm|=0x2000;}	// In case of sending
    pm=ByteBuffer.allocate(XMSGSIZE);	pm.order(ByteOrder.nativeOrder());
    msg1=pm.array();

    if(mcb._TDSMssgFind(fm,msg,len,0,hd)		>=0){
      for(la=0;;){
	if(MssgUseNextL==0){			//  Get item value
	  rtn=mcb._TDSMssgNext(0,msg,form,sz,noi,pm,XMSGSIZE);
	  form[0]&=077;
	  if(rtn						< 0)	break;
	  printf("%03o:%d*%3d:"	,form[0],sz[0],noi[0]);
	  switch(form[0]){
	    case 000: printf("L [%2d]\n"	,noi[0]);		break;
	    case 010: printf("B [%2d]"	,noi[0]);
		      for(c="=",i=0;i<noi[0];i++){
		        printf("%s0x%02x"
				,c,((int)msg1[i]&0xff));	if(i==0) c=",";
		      } printf("\n");				break; 
	    case 011: printf("T [%2d]"	,noi[0]);
		      for(c="=",i=0;i<noi[0];i++){
		        printf("%s%d"	,c,msg1[i]);		if(i==0) c=",";
		      } printf("\n");				break; 
	    case 020: c=new String(msg1,0 ,noi[0]);
		      printf("A [%2d]=%s.\n",noi[0],c);	c=null;	break;
	    case 021: c=new String(msg1,0 ,noi[0]);
		      printf("J [%2d]=%s.\n",noi[0],c);	c=null;	break;
	    case 022: c=new String(msg1,0 ,noi[0]);
		      printf("K [%2d]=%s.\n",noi[0],c);	c=null;	break;
	    case 030: printf("I8[%2d]"	,noi[0]);
		      for(c="=",i=0;i<noi[0];i++){
		        printf("%s%d"	,c,pm.getLong	(i*8));	if(i==0) c=",";
		      } printf("\n");				break;
	    case 031: printf("I1[%2d]"	,noi[0]);
		      for(c="=",i=0;i<noi[0];i++){
		        printf("%s%d"	,c,msg1[i]);		if(i==0) c=",";
		      } printf("\n");				break; 
	    case 032: printf("I2[%2d]"	,noi[0]);
		      for(c="=",i=0;i<noi[0];i++){
		        printf("%s%d"
				,c,(int)pm.getShort	(i*2));	if(i==0) c=",";
		      } printf("\n");				break; 
	    case 034: printf("I4[%2d]"	,noi[0]);
		      for(c="=",i=0;i<noi[0];i++){
		        printf("%s%d"	,c,pm.getInt	(i*4));	if(i==0) c=",";
		      } printf("\n");				break; 
	    case 040: printf("F8[%2d]"	,noi[0]);
		      for(c="=",i=0;i<noi[0];i++){
		        printf("%s%22.17e"
				,c,pm.getDouble		(i*8));	if(i==0) c=",";
		      } printf("\n");				break; 
	    case 044: printf("F4[%2d]"	,noi[0]);
		      for(c="=",i=0;i<noi[0];i++){
		        printf("%s%13.8e",c,pm.getFloat	(i*4));	if(i==0) c=",";
		      } printf("\n");				break; 
	    case 050: printf("U8[%2d]"	,noi[0]);
		      for(c="=",i=0;i<noi[0];i++){
			printf("%s%d"	,c,pm.getLong	(i*8));	if(i==0) c=",";
		      } printf("\n");				break;
	    case 051: printf("U1[%2d]"	,noi[0]);
		      for(c="=",i=0;i<noi[0];i++){
			ul=((long)msg1[i])&0xffL;
		        printf("%s%d"	,c,ul);			if(i==0) c=",";
		      } printf("\n");				break; 
	    case 052: printf("U2[%2d]"	,noi[0]);
		      for(c="=",i=0;i<noi[0];i++){
			ul=((long)pm.getShort(i*2))&0xffffL;
		        printf("%s%d"	,c,ul);			if(i==0) c=",";
		      } printf("\n");				break; 
	    case 054: printf("U4[%2d]"	,noi[0]);
		      for(c="=",i=0;i<noi[0];i++){
			ul=((long)pm.getInt  (i*4))&0xffffffffL;
		        printf("%s%d"	,c,ul);			if(i==0) c=",";
		      } printf("\n");				break; 
	    default:  printf("\n");				break;
	  }

	}else{					// Get in list format
						// リスト表示形式で取得
	  rtn=mcb._TDSMssgNextL(dp,msg,form,noi,mname);
	  form[0]&=077;
	  if(rtn						< 0)	break;
	  if((dp&0x70)>0x10){			// In case of SML
	    for(  i=la;i>rtn;i--){
	      for(j= 0;j<i  ;j++) printf("  ");
	      printf(">\n");			// Display '>'
	  } }
	  la=rtn;				// Save current hierarchy
						// 現在の階層を保存
	  printf("  %s\n",mname.toString());	// Display acquired field value
						// 取得した項目値を表示
	  if((dp&0x70)>0x10 && form[0]==000 && noi[0]==0){
	    for(  j= 0;j<=la;j++) printf("  ");	// '>' Processing for L0
	    printf(">\n");				
      } } }					// L0 の場合の '>' 処理
      if(MssgUseNextL!=0){
	if((dp&0x70)>0x10){
	  for(  i=la;i>0;i--){
	    for(j= 0;j<i;j++)	  printf("  ");	// Show remaining '>'
	    printf(">\n");			// 残りの '>' 表示
      } } }				
      mcb._TDSMssgExit(0,msg);
  } }

  mcb=null;
}



// -----------------------------------------------------------------------------
// Display sent and received data ----------------------------------------------

static private int
DispData(
int		tp,		// i  : Message type
				//	=0 : Transmission result
				//	 1 : Received message
				//	 2 : Send messag
byte		hd[],		// i  : SECS Message Header
int		did,		// i  : SECS Message Device ID
int		sf,		// i  : SECS Message SF-Code
int		xid,		// i  : SECS Message Transaction ID
byte		msg[],		// i  : SECS Message body
int		len,		// i  : Byte length of 'msg'
int		rtn)		// i  : I/O return value
{
  int		ok=0;

  if(rtn<0){							 ok=1;
    if((rtn<(-E_NOTCONNECT) || (-E_ILLBLOCK)<rtn) && rtn!=(-E_NODATA)){
      printf("ERROR  [%d]"			,rtn);
      if      (rtn==(-E_NODEV)){
	printf(" : No such device ID\n");	len=ok=0;
      }else if(rtn==(-E_2BIG )){
	printf(" : Data size to large\n");	len=ok=0;
      }else			printf("\n");
    }else{
      if(FuncType==0)	printf("STATUS = %d,%d : ",-rtn,SAcb._TDSCommStatus(0));
      else		printf("STATUS = %d,%d : ",-rtn,UAcb._TDSUDrvStatus(0));
      switch(-rtn){
	case E_NODATA:		printf("No data\n");			break;
	case E_ILLBLOCK:	printf("Illegal block#\n");		break;
	case E_T1TIMEDOUT:	printf("T1 Timeout occur\n");		break;
	case E_T2TIMEDOUT:	printf("T2 Timeout occur\n");		break;
	case E_T3TIMEDOUT:	printf("T3 Timeout occur\n");		break;
	case E_T4TIMEDOUT:	printf("T4 Timeout occur\n");		break;
	case E_T5TIMEDOUT:	printf("T5 Timeout occur\n");		break;
	case E_T6TIMEDOUT:	printf("T6 Timeout occur\n");		break;
	case E_T7TIMEDOUT:	printf("T7 Timeout occur\n");		break;
	case E_T8TIMEDOUT:	printf("T8 Timeout occur\n");		break;
	case E_RETRYOVER:	printf("Retry over\n");			break;
	case E_CONNECT:		printf("Connected\n");			break;
	case E_SELECT:		printf("Selected   (0x%04x)\n",did);	break;
	case E_REJECT:		printf("Rejected XId=0x%04x.0x%04x\n"
				,(xid>>16)&0xffff,xid&0xffff);		break;
	case E_DESELECT:	printf("Deselected (0x%04x)\n",did);	break;
	case E_SEPARATE:	printf("Separated  (0x%04x)\n",did);	break;
	case E_NOTCONNECT:	printf("Not connected\n");		break;
	default:		printf("\n");				break;
  } } }

  if(ok==0) DispSECSMssg(tp,hd,did,sf,xid,msg,len);

  return(0);
}



// =============================================================================
// S1F1 message construction and sending ---------------------------------------

static private int
SendS1F1()
{
  byte		hd[]=new byte[12],msg[]=new byte[16];
  int		rtn,sf=0x8101,cmd=0x0000,len=0;

  if(HeaderBO	!=0)	cmd=0x2000;
  if(FuncType	==0)	rtn=SAcb._TDSCommSend(cmd, -1,sf,  0,msg,len,hd);
  else			rtn=UAcb._TDSUDrvSend(cmd, -1,sf,  0,msg,len,hd);
  DispData(2,hd, -1,sf,rtn,msg,len,rtn);

  return(rtn);
}


// -----------------------------------------------------------------------------
// S1F2 message (Host) construction and sending --------------------------------

static private int
SendS1F2H(
int		did,
int		xid)
{
  TDSMssg	mcb =new TDSMssg();
  byte		hd[]=new byte[12],msg[]=new byte[256];
  int		rtn,sf=0x0102,cmd=0x0000,len;
  
  		mcb._TDSMssgInit   (0,msg, 256);		// S1F2
		mcb._TDSMssgBuild  (0,msg, 000,  0);		// L0
  len=		mcb._TDSMssgEnd    (0,msg);

  if(len<0)		rtn=len;
  else{
    if(HeaderBO	!=0)	cmd=0x2000;
    if(FuncType	==0)	rtn=SAcb._TDSCommSend(cmd,did,sf,xid,msg,len,hd);
    else		rtn=UAcb._TDSUDrvSend(cmd,did,sf,xid,msg,len,hd);
  }
  DispData(2,hd,did,sf,rtn,msg,len,rtn);
  mcb=null;

  return(rtn);
}


// -----------------------------------------------------------------------------
// S1F2 message (Equipment) construction and sending ---------------------------

static private int
SendS1F2E(
int		did,
int		xid)
{
  TDSMssg	mcb =new TDSMssg();
  byte		hd[]=new byte[12],msg[]=new byte[256];
  int		rtn,sf=0x0102,cmd=0x0000,len;
  
    		mcb._TDSMssgInit   (0,msg, 256);		// S1F2
		mcb._TDSMssgBuild  (0,msg, 000, 2);		// L2
		mcb._TDSMssgBuild  (0,msg, 020, 6,"EQUIP1");	//  MDLN
		mcb._TDSMssgBuild  (0,msg, 020, 6,"01.000");	//  SOFTREV
  len=		mcb._TDSMssgEnd    (0,msg);

  if(len<0)		rtn=len;
  else{
    if(HeaderBO	!=0)	cmd=0x2000;
    if(FuncType	==0)	rtn=SAcb._TDSCommSend(cmd,did,sf,xid,msg,len,hd);
    else		rtn=UAcb._TDSUDrvSend(cmd,did,sf,xid,msg,len,hd);
  }
  DispData(2,hd,did,sf,rtn,msg,len,rtn);
  mcb=null;

  return(rtn);
}


// =============================================================================
// S1F21 message construction and sending --------------------------------------

static private int
SendS1F21()
{
  TDSMssg	mcb =new TDSMssg();
  byte		hd []=new byte [12],msg[]=new byte[XMSGSIZE];
  byte		vb []={                      1,            (byte)0xff};
  byte		vt []={                      0,                     1};
  String 	vs0  = "MSG41";
  String 	vs1  = "ｿﾌﾄ 41";
  String 	vs2  = "これは ｺﾒﾝﾄ (JavaIo) です";
  byte		vi1[]={                      2,                  -128};
  short		vi2[]={                  32767,                -32768};
  int		vi4[]={             0x7ffffffe,            0xfffffffe};
  long		vi8[]={    0x7fffffffffffffffL,   0x800080008000800bL};
  byte		vu1[]={                   0x7f,            (byte)0xff};
  short		vu2[]={                 0x7ffe,         (short)0xfffe};
  int		vu4[]={             0x7ffffffd,            0xfffffffd};
  long		vu8[]={    0x7fffffffffffffffL,   0x800080008000800bL};
  long		au8[]={  7, -6,  5, -4,  3, -2,  1,  0};
  float		vf4[]={  (float)9.87654321e-21,(float)-8.642097531e13};
  double	vf8[]={-1.9283746574839201e123,9.1827364546372819208e-213};
  int		rtn,sf=0x8100+21,cmd=0x0000,len=0;

		mcb._TDSMssgInit   (0,msg,XMSGSIZE);		// S1F21
  		mcb._TDSMssgBuild  (0,msg, 000,  4);		// L4
  		mcb._TDSMssgBuild  (0,msg, 000,  2);		//  L2
		mcb._TDSMssgBuild  (0,msg, 010,  2,vb);		//   VB
		mcb._TDSMssgBuild  (0,msg, 011,  2,vt);		//   VT
  		mcb._TDSMssgBuild  (0,msg, 000,  3);		//  L3
  		mcb._TDSMssgBuild  (0,msg, 020,  6,vs0);	//   MDLN
  		mcb._TDSMssgBuild  (0,msg, 021,  0,vs1);	//   SOFTREV
  		mcb._TDSMssgBuild  (0,msg, 022,  0,vs2);	//   COMMENT
  		mcb._TDSMssgBuild  (0,msg, 000,  9);		//  L9
		mcb._TDSMssgBuild  (0,msg, 031,  2,vi1);	//   VI1
		mcb._TDSMssgBuild  (0,msg, 032,  2,vi2);	//   VI2
		mcb._TDSMssgBuild  (0,msg, 034,  2,vi4);	//   VI4
		mcb._TDSMssgBuild  (0,msg, 030,  2,vi8);	//   VI8
		mcb._TDSMssgBuild  (0,msg, 051,  2,vu1);	//   VU1
		mcb._TDSMssgBuild  (0,msg, 052,  2,vu2);	//   VU2
		mcb._TDSMssgBuild  (0,msg, 054,  2,vu4);	//   VU4
		mcb._TDSMssgBuild  (0,msg, 050,  2,vu8);	//   VU8
		mcb._TDSMssgBuild  (0,msg, 050,  8,au8);	//   AU8
  		mcb._TDSMssgBuild  (0,msg, 000,  2);		//  L2
		mcb._TDSMssgBuild  (0,msg, 044,  2,vf4);	//   VF4
		mcb._TDSMssgBuild  (0,msg, 040,  2,vf8);	//   VF8
  len=		mcb._TDSMssgEnd    (0,msg);

  if(len<0)		rtn=len;
  else{
    if(HeaderBO	!=0)	cmd=0x2000;
    if(FuncType ==0)	rtn=SAcb._TDSCommSend(cmd, -1,sf,  0,msg,len,hd);
    else		rtn=UAcb._TDSUDrvSend(cmd, -1,sf,  0,msg,len,hd);
  }
  DispData(2,hd, -1,sf,rtn,msg,len,rtn);
  mcb=null;

  return(rtn);
}


// -----------------------------------------------------------------------------
// S1F22 message (Host) construction and sending -------------------------------

static private int
SendS1F22(
int		did,
int		xid)
{
  TDSMssg	mcb =new TDSMssg();
  byte		hd []=new byte [12],msg[]=new byte[XMSGSIZE];
  byte		vb []={                     2,              (byte)0xfe};
  byte		vt []={                     1,                       0};
  String 	vs0  = "MSG42";
  String 	vs1  = "ﾚﾋﾞｼﾞｮﾝ";
  String	vs2  = "This is コメント (JavaIo)";
  byte		vi1[]={                   127,                      -2};
  short		vi2[]={                 32766,                  -32768};
  int		vi4[]={            2147483646,             -2147483648};
  long		vi8[]={   0x8000000000000000L,     0x7ffffffffffffffeL};
  byte		vu1[]={              (byte)254,             (byte)0xff};
  short		vu2[]={           (short)65534,          (short)0xffff};
  int		vu4[]={       (int)4294967294L,        (int)0xffffffff};
//long		vu8[]={  18446744073709551614L,    0xffffffffffffffffL};
  long		vu8[]={    0xffffffffffffffffL,    0xffffffffffffffffL};
  long		au8[]={ -1,  2, -3,  4, -5,  6, -7,  0};
  float		vf4[]={  (float)7.89012345e-12,(float)-4.321098765e31};
  double	vf8[]={ 5.6473829101928374e189,-3.2109876543210987654e-179};
  int		rtn,sf=0x0100+22,cmd=0x0000,len=0;
  
		mcb._TDSMssgInit   (0,msg,XMSGSIZE);		// S1F22
  		mcb._TDSMssgBuild  (0,msg, 000,  4);		// L4
  		mcb._TDSMssgBuild  (0,msg, 000,  2);		//  L2
		mcb._TDSMssgBuild  (0,msg, 010,  2,vb);		//   VB
		mcb._TDSMssgBuild  (0,msg, 011,  2,vt);		//   VT
  		mcb._TDSMssgBuild  (0,msg, 000,  3);		//  L3
  		mcb._TDSMssgBuild  (0,msg, 020,  6,vs0);	//   MDLN
  		mcb._TDSMssgBuild  (0,msg, 021,  0,vs1);	//   SOFTREV
  		mcb._TDSMssgBuild  (0,msg, 022,  0,vs2);	//   COMMENT
  		mcb._TDSMssgBuild  (0,msg, 000,  9);		//  L9
		mcb._TDSMssgBuild  (0,msg, 031,  2,vi1);	//   VI1
		mcb._TDSMssgBuild  (0,msg, 032,  2,vi2);	//   VI2
		mcb._TDSMssgBuild  (0,msg, 034,  2,vi4);	//   VI4
		mcb._TDSMssgBuild  (0,msg, 030,  2,vi8);	//   VI8
		mcb._TDSMssgBuild  (0,msg, 051,  2,vu1);	//   VU1
		mcb._TDSMssgBuild  (0,msg, 052,  2,vu2);	//   VU2
		mcb._TDSMssgBuild  (0,msg, 054,  2,vu4);	//   VU4
		mcb._TDSMssgBuild  (0,msg, 050,  2,vu8);	//   VU8
		mcb._TDSMssgBuild  (0,msg, 050,  8,au8);	//   AU8
  		mcb._TDSMssgBuild  (0,msg, 000,  2);		//  L2
		mcb._TDSMssgBuild  (0,msg, 044,  2,vf4);	//   VF4
		mcb._TDSMssgBuild  (0,msg, 040,  2,vf8);	//   VF8
  len=		mcb._TDSMssgEnd    (0,msg);

  if(len<0)		rtn=len;
  else{
    if(HeaderBO	!=0)	cmd=0x2000;
    if(FuncType ==0)	rtn=SAcb._TDSCommSend(cmd,did,sf,xid,msg,len,hd);
    else		rtn=UAcb._TDSUDrvSend(cmd,did,sf,xid,msg,len,hd);
  }
  DispData(2,hd,did,sf,rtn,msg,len,rtn);
  mcb=null;

  return(rtn);
}


// =============================================================================
// S2F49 message construction and sending --------------------------------------

static private int
SendS2F49()
{
  TDSMssg	mcb =new TDSMssg();
  byte		hd[]=new byte[12],msg[]=new byte[XMSGSIZE];
  byte		vb[]=new byte[32];
  int		vi[]=new int[4];
  String	str,itm;
  int		rtn,sf=0x8200+49,cmd=0x0000,no1,no2,len,i,j;

  cnt249++;	no1=(cnt249%2)+1;	no2=(cnt249%10)+1;
  str=String.format("LOTID (%04d)"	,cnt249);
  
		mcb._TDSMssgInit   (0,msg,XMSGSIZE);		// S2F49
  		mcb._TDSMssgBuild  (0,msg, 000,  3);		// L3
  vb[0]=0;	mcb._TDSMssgBuild  (0,msg, 010,  1,vb);		//  DATAIDB
  		mcb._TDSMssgBuild  (0,msg, 020,  0,"LOAD");	//  RCMD
  		mcb._TDSMssgBuild  (0,msg, 000,  4);		//  L4
  vb[0]=1;	mcb._TDSMssgBuild  (0,msg, 010,  1,vb);		//   STID
  vb[0]=0;	mcb._TDSMssgBuild  (0,msg, 010,  1,vb);		//   MTKD
  		mcb._TDSMssgBuild  (0,msg, 020, 20,str);	//   LOTID
		mcb._TDSMssgBuild  (0,msg, 000,no1);		//   L[no1]
  for(i=0;i<no1;i++){
		mcb._TDSMssgBuild  (0,msg, 000,no2);		//    L[no2]
    for(j=0;j<no2;j++){
		mcb._TDSMssgBuild  (0,msg, 000,  2);		//     L[2]
      str=String.format("WAFER(%04d-%d-%02d)",cnt249,i+1,i+2);
  		mcb._TDSMssgBuild  (0,msg, 020, 20,str);	//      WAFERID
      str=String.format("PPID (%04d-%d-%02d)",cnt249,i+1,i+2);
  		mcb._TDSMssgBuild  (0,msg, 020, 16,str);	//      PPID
  } }
  len=		mcb._TDSMssgEnd    (0,msg);

  if(len<0)		rtn=len;
  else{
    if(HeaderBO	!=0)	cmd=0x2000;
    if(FuncType ==0)	rtn=SAcb._TDSCommSend(cmd, -1,sf,  0,msg,len,hd);
    else		rtn=UAcb._TDSUDrvSend(cmd, -1,sf,  0,msg,len,hd);
  }
  DispData(2,hd, -1,sf,rtn,msg,len,rtn);
  mcb=null;

  return(rtn);
}


// -----------------------------------------------------------------------------
// S2F50 message construction and sending --------------------------------------

static private int
SendS2F50(
int		did,
int		xid)
{
  TDSMssg	mcb =new TDSMssg();
  byte		hd[]=new byte[12],msg[]=new byte[256];
  byte		vb[]=new byte[32];
  String	str;
  int		rtn,sf=0x0200+50,cmd=0x0000,len;
  
  str=String.format("LOTID (%04d)"		,++cnt250);

		mcb._TDSMssgInit   (0,msg, 256);		// S2F50
		mcb._TDSMssgBuild  (0,msg, 000,  2);		// L2
  vb[0]=0;	mcb._TDSMssgBuild  (0,msg, 010,  1,vb);		//  HCACK
		mcb._TDSMssgBuild  (0,msg, 000,  2);		//  L2
  		mcb._TDSMssgBuild  (0,msg, 020, 16,"PPID");	//   PPID
  		mcb._TDSMssgBuild  (0,msg, 020, 20,str);	//   LOTID
  len=		mcb._TDSMssgEnd    (0,msg);

  if(len<0)		rtn=len;
  else{
    if(HeaderBO	!=0)	cmd=0x2000;
    if(FuncType ==0)	rtn=SAcb._TDSCommSend(cmd,did,sf,xid,msg,len,hd);
    else		rtn=UAcb._TDSUDrvSend(cmd,did,sf,xid,msg,len,hd);
  }
  DispData(2,hd,did,sf,rtn,msg,len,rtn);
  mcb=null;

  return(rtn);
}


// =============================================================================
// S6F11 message construction and sending --------------------------------------

static private int
SendS6F11()
{
  TDSMssg	mcb =new TDSMssg();
  byte		hd[]=new byte[12],msg[]=new byte[256];
  short		vs[]=new short[4];
  int		rtn,sf=0x8600+11,cmd=0x0000,len;

  if((++cnt611)==32768) cnt611=0;

		mcb._TDSMssgInit   (0,msg, 256);		// S6F11
  		mcb._TDSMssgBuild  (0,msg, 000,  3);		// L3
  vs[0]=(short)cnt611;
		mcb._TDSMssgBuild  (0,msg, 052,  1,vs);		//  DATAID
  vs[0]=8;	mcb._TDSMssgBuild  (0,msg, 052,  1,vs);		//  CEID
  		mcb._TDSMssgBuild  (0,msg, 000,  3);		//  L3
  		mcb._TDSMssgBuild  (0,msg, 020, 16,"DATA1");	//   DATA1
  		mcb._TDSMssgBuild  (0,msg, 020, 16,"DATA2");	//   DATA2
  		mcb._TDSMssgBuild  (0,msg, 020, 14,"YYYYMMDDhhmmss");
			// @TIME Actually I set current time, but omitted.
			// @TIME 本当は現在時刻を設定するのだが、省略。
  len=		mcb._TDSMssgEnd    (0,msg);

  if(len<0)		rtn=len;
  else{
    if(HeaderBO	!=0)	cmd=0x2000;
    if(FuncType ==0)	rtn=SAcb._TDSCommSend(cmd, -1,sf,  0,msg,len,hd);
    else		rtn=UAcb._TDSUDrvSend(cmd, -1,sf,  0,msg,len,hd);
  }
  DispData(2,hd, -1,sf,rtn,msg,len,rtn);
  mcb=null;

  return(rtn);
}



// -----------------------------------------------------------------------------
// S6F12 message construction and sending --------------------------------------

static private int
SendS6F12(
int		did,
int		xid)
{
  TDSMssg	mcb =new TDSMssg();
  byte		hd[]=new byte[12],msg[]=new byte[256];
  byte		vb[]=new byte[32];
  int		rtn,sf=0x0600+12,cmd=0x0000,len;

		mcb._TDSMssgInit (0,msg, 256);			// S6F12
  vb[0]=0;	mcb._TDSMssgBuild(0,msg, 010,  1);		// ACKC
  len=		mcb._TDSMssgEnd  (0,msg);

  if(len<0)		rtn=len;
  else{
    if(HeaderBO	!=0)	cmd=0x2000;
    if(FuncType ==0)	rtn=SAcb._TDSCommSend(cmd,did,sf,xid,msg,len,hd);
    else		rtn=UAcb._TDSUDrvSend(cmd,did,sf,xid,msg,len,hd);
  }
  DispData(2,hd,did,sf,rtn,msg,len,rtn);
  mcb=null;

  return(rtn);
}



// =============================================================================
// Callback function ===========================================================

static private int
CBRecvProc(
int		req,		// i  : Request code to library
int		rtn,		// i  : Return code from library
int		did,		// i  : SECS Message Device ID
int		xsf,		// i  : SECS Message SF-Code
int		xid,		// i  : SECS Message Transaction ID
byte		xhd[],		// i  : SECS Message Header
byte		xmsg[])		// i  : SECS Message Body
{
  // ヘッダ情報の Network Byte order での取得が指示されている場合 xhd は動作
  // システムの BO で格納されているので、Network Byte Order に変換する
  if(HeaderBO	!=0){
    if(FuncType	==0)	SAcb._TDSCommHeaderBO(0x00,xhd);
    else		UAcb._TDSUDrvHeaderBO(0x00,xhd);
  }

  DispData(1,xhd,did,xsf,xid,xmsg,rtn,rtn);
  if(req== 0 && rtn>=0){
    if     (xsf==(0x8100+ 1)&&OType==0)	SendS1F2H (did,xid);
    else if(xsf==(0x8100+ 1)&&OType==1)	SendS1F2E (did,xid);
    else if(xsf==(0x8100+21))		SendS1F22 (did,xid);
    else if(xsf==(0x8200+49))		SendS2F50 (did,xid);
    else if(xsf==(0x8600+11))		SendS6F12 (did,xid);
  }

  return(0);
}



// -----------------------------------------------------------------------------

static class RecvProcThread extends Thread{
public void
run()
{
  byte		msg[]=new byte[XMSGSIZE],hd[]=new byte[12];
  int		xid[]=new int[ 1],did[]=new int[1],sf[]=new int[1];
  int		rtn,cmd,req;

  for(;Break==0;){
    req=0;		cmd=0;
  // ヘッダ・バイトオーダー変換は、CBRecvProc() で行うので、それと同様の扱いと
  // なるよう、ここではヘッダ・バイトオーダー変換を指示しない。
  //if(HeaderBO	!=0)	cmd=0x2000;
  //else		cmd=0x0000;
    if(FuncType	==0)	rtn=SAcb._TDSCommRecv(cmd,did,sf,xid,msg,XMSGSIZE,hd);
    else		rtn=UAcb._TDSUDrvRecv(cmd,did,sf,xid,msg,XMSGSIZE,hd);
    if(rtn==(-E_NODATA)){
      Sleep(100);
    }else{
      if((-1000)<rtn && rtn<(-959))	req=(-rtn)-900;
      CBRecvProc(req,rtn,did[0],sf[0],xid[0],hd,msg);
  } }
}
}



// =============================================================================
// Main process ----------------------------------------------------------------

public static void
main(
String[]		argv)
{
  int			opt=0;

						// Initialize startup parameters
  if(FuncType		!=0)			opt|=0x0001;
  if(HeaderBO		!=0)			opt|=0x0002;
  if(MssgDispType	!=0x00)			opt|=0x0004;
  if(MssgUseNextL	!=0)			opt|=0x0008;
  if(UseRecvThrd	!=0)			opt|=0x0020;

  if     (argv.length>1){			// Analyze startup parameters
    if      (argv[1].length()	>1			   &&
	    (argv[1].substring(0,1).equalsIgnoreCase("x"))){
      opt=Integer.parseInt(argv[1].substring(1),16);
    }else if(argv[1].length()	>2			   &&
	    (argv[1].substring(0,1).equals	    ("0")) &&
	    (argv[1].substring(1,2).equalsIgnoreCase("x"))){
      opt=Integer.parseInt(argv[1].substring(2),16);
    }else{
      opt=Integer.parseInt(argv[1]);
    }
    if((opt&0x0001)!=0) FuncType    =1;		else FuncType    =0;
    if((opt&0x0002)!=0) HeaderBO    =1;		else HeaderBO	 =0;
    if((opt&0x0004)!=0) MssgDispType=0x20;	else MssgDispType=0x00;
    if((opt&0x0008)!=0) MssgUseNextL=1;		else MssgUseNextL=0;
    if((opt&0x0020)!=0) UseRecvThrd =1;		else UseRecvThrd =0;
  }
  if(argv.length>2)	SendWait    =Integer.parseInt(argv[2]);
  if(argv.length>3)	SendSleep   =Integer.parseInt(argv[3]);

						// Display startup parameters
  printf("option      =0x%02x,%d\n"		,opt,opt);
  printf("FuncType    =%d\n"			,FuncType);
  printf("HeaderBO    =%d\n"			,HeaderBO);
  printf("MssgDispType=0x%02x\n"		,MssgDispType);
  printf("MssgUseNextL=%d\n"			,MssgUseNextL);
  printf("UseRecvThrd =%d\n"			,UseRecvThrd);
  printf("SendWait    =%d\n"			,SendWait);
  printf("SendSleep   =%d\n"			,SendSleep);

						// Start processing function
  if     (argv.length<1)			Usage();
  else if(argv[0].equals("h")==false &&
	  argv[0].equals("e")==false)		Usage();
  else{
    if(argv[0].equals("h")==true)		Host ();
    else					Equip();
  }
}


// -----------------------------------------------------------------------------

static private void
Usage()
{
  printf("\nUsage: java JavaIo {h|e} [option [send_wait [send_sleep]]]\n");
  printf("\n  option\n");
  printf(  "               5  3210\n");
  printf(  "  +----+----+----+----+\n");
  printf(  "               |  |||+-- Function to use\n");
  printf(  "               |  |||    =0: _TDSCommXxxxx() 1:_TDSUDrvXxxx()\n");
  printf(  "               |  ||+--- SECS Header Byte order\n");
  printf(  "               |  ||     =0: System order    1: Network order\n");
  printf(  "               |  |+---- Format for displaying messages in SECS list format\n");
  printf(  "               |  |      =0: TDS Format      1: SML Format\n");
  printf(  "               |  +----- Whether to use MssgNextL() for SECS message display\n");
  printf(  "               |         =0: Not use         1: Use\n");
  printf(  "               +-------- Whether to execute SECS message reception in a dedicated thread\n");
  printf(  "                         =0: No              1: Yes\n");
  printf(  "  send_wait   : Message sending interval     (%5dms)\n",SendWait);
  printf(  "  send_sleep  : Wait time                    (%5dms)\n",SendSleep);
  printf("\n");
}



// =============================================================================
// Host side process -----------------------------------------------------------

static private void
Host()
{
  BufferedReader	in;
  RecvProcThread	th;
  String		str;
  byte			hd[]=new byte[12],msg[]=new byte[XMSGSIZE];
  int			xid[]=new int[1],did[]=new int[1],sf[]=new int[1];
  int			req,rtn,omd=0,cmd,mno,dsd=0,xsd=0,stat,i;

  OType=0;	Break=0;
  in=new BufferedReader(new InputStreamReader(System.in));

L0:{
  if(FuncType	==0)	SAcb=new TDSComm();
  else			UAcb=new TDSUDrv();
  if(FuncType	==0)	rtn=SAcb._TDSCommOpen(omd,PARAMFILE,"HOST");
  else			rtn=UAcb._TDSUDrvOpen(omd,PARAMFILE,"HOST",UDRV_MASK);
  if(rtn						< 0)	break L0;
  printf("(H) Opened\n");

  if(UseRecvThrd!=0){
    th=new RecvProcThread();
    th.start();
  }

  for(;;){		// In case of HSMS, wait for Select state.
			// HSMS 接続の場合、Select 状態になるのを待つ。
    if(FuncType==0)	rtn=SAcb._TDSCommStatus(0x0000);
    else		rtn=UAcb._TDSUDrvStatus(0x0000);
    if(rtn							< 0) break L0;
    if(rtn							==3) break;
    Sleep(100);
  }
  printf("(H) Selected\n");

  for(;;){		rtn=0;
    if(UseRecvThrd==0)	str="Req (0:Exit 1:Recv 2:Send) : ";
    else		str="Req (0:Exit 2:Send 3:Continuous) : ";
    req=ReadInt(in,str,10);
    if      (req==0){						break;

    }else if(req==1){	cmd=0x0000;
    //if(HeaderBO!=0)	cmd=0x2000;
    //else		cmd=0x0000;
      if(FuncType==0)	rtn=SAcb._TDSCommRecv(cmd,did,sf,xid,msg,XMSGSIZE,hd);
      else		rtn=UAcb._TDSUDrvRecv(cmd,did,sf,xid,msg,XMSGSIZE,hd);
      if(HeaderBO!=0){	// The mode setting of CommRecv() is sufficient, but
			// for testing purposes, CommHeaderBO() is used here.
      			// CommRecv() の mode 設定でことは足りるが、ここでは
			// 試験のため、敢えて CommHeaderBO() を使用する。
	if(FuncType==0)	SAcb._TDSCommHeaderBO(0x00,hd);
	else		UAcb._TDSUDrvHeaderBO(0x00,hd);
      }
      if(rtn	>=0){	dsd=did[0];	xsd=xid[0];}
      DispData(1,hd,did[0],sf[0],xid[0],msg,rtn,rtn);

    }else if(req==2){
      if(UseRecvThrd==0){
	str="Message(1:S1F1 2:S1F21 3:S2F49   6:S1F2 7:S1F22 8:S6F12) : ";
      }else{
	str="Message(1:S1F1 2:S1F21 3:S2F49) : ";
      }
      mno=ReadInt(in,str,10);
      switch(mno){
	case 1: rtn=SendS1F1 ();		break;
	case 2: rtn=SendS1F21();		break;
	case 3: rtn=SendS2F49();		break;
	case 6: rtn=SendS1F2H(dsd,xsd);		break;
	case 7: rtn=SendS1F22(dsd,xsd);		break;
	case 8: rtn=SendS6F12(dsd,xsd);		break;
      }

    }else if(req==3){
      for(Break=i=0;Break==0;i++){
	Sleep(SendWait);
	if(FuncType==0)	stat=SAcb._TDSCommStatus(0);
	else		stat=UAcb._TDSUDrvStatus(0);
	if(stat==3){
	  if((rtn=SendS2F49())	< 0){
	    printf("(H) Send error (%d)\n",rtn);	Sleep(ERROR_SLEEP);
	  }
	  if((i%SEND_NO)			==0)	Sleep(SendSleep);
      } }
      rtn=0;
    }

    if(rtn<(-999) || ((-900)<rtn && rtn<0)){
      printf("(H) I/O Error (%d)\n"			,rtn);
  } }
  }	// L0:

  Break  = 1;
  if(SAcb!=null)	SAcb._TDSCommClose(0);		SAcb=null;
  if(UAcb!=null)	UAcb._TDSUDrvClose(0);		UAcb=null;
  if(rtn < 0)		printf("(H) Error (%d)\n"	,rtn);
}



// =============================================================================
// Equipment side process ------------------------------------------------------

static private void
Equip()
{
  BufferedReader	in;
  RecvProcThread	th;
  String		str;
  byte			hd[]=new byte[12],msg[]=new byte[XMSGSIZE];
  int			xid[]=new int[1],did[]=new int[1],sf[]=new int[1];
  int			req,rtn,omd=0,cmd,mno,dsd=0,xsd=0,stat,i;

  OType=1;	Break=0;
  in=new BufferedReader(new InputStreamReader(System.in));

L0:{
  if(FuncType	==0)	SAcb=new TDSComm();
  else			UAcb=new TDSUDrv();
  if(FuncType	==0)	rtn=SAcb._TDSCommOpen(omd,PARAMFILE,"EQUIP");
  else			rtn=UAcb._TDSUDrvOpen(omd,PARAMFILE,"EQUIP",UDRV_MASK);
  if(rtn							< 0) break L0;
  printf("(E) Opened\n");

  if(UseRecvThrd!=0){
    th=new RecvProcThread();
    th.start();
  }

  if(SECS_MODE!=0 && FuncType==0){   // In case of and use _TDSCommXxxxx()
				     // HSMS で _TDSCommXxxxx() 使用の場合
    if(SAcb._TDSCommSend(0x0100,0,0,0,msg,0,hd)			< 0) break L0;
    printf("(E) Connect\n");
    if(SAcb._TDSCommSend(0x0200,0,0,0,msg,0,hd)			< 0) break L0;
    printf("(E) Select request\n");

    for(;;){		// In case of HSMS, wait for Select state.
			// HSMS 接続の場合、Select 状態になるのを待つ。
      if(FuncType==0)	rtn=SAcb._TDSCommStatus(0x0000);
      else		rtn=UAcb._TDSUDrvStatus(0x0000);
      if(rtn							< 0) break L0;
      if(rtn							==3) break;
      Sleep(100);
    }
    printf("(E) Selected\n");
  }

  for(;;){		rtn=0;
    if(UseRecvThrd==0)	str="Req (0:Exit 1:Recv 2:Send) : ";
    else		str="Req (0:Exit 2:Send 3:Continuous) : ";
    req=ReadInt(in,str,10);
    if      (req==0){						     break;

    }else if(req==1){	cmd=0x0000;
    //if(HeaderBO!=0)	cmd=0x2000;
    //else		cmd=0x0000;
      if(FuncType==0)	rtn=SAcb._TDSCommRecv(cmd,did,sf,xid,msg,XMSGSIZE,hd);
      else		rtn=UAcb._TDSUDrvRecv(cmd,did,sf,xid,msg,XMSGSIZE,hd);
      if(HeaderBO!=0){	// The mode setting of CommRecv() is sufficient, but
			// for testing purposes, CommHeaderBO() is used here.
      			// CommRecv() の mode 設定でことは足りるが、ここでは
			// 試験のため、敢えて CommHeaderBO() を使用する。
	if(FuncType==0)	SAcb._TDSCommHeaderBO(0x00,hd);
	else		UAcb._TDSUDrvHeaderBO(0x00,hd);
      }
      if(rtn	>=0){	dsd=did[0];	xsd=xid[0];}
      DispData(1,hd,did[0],sf[0],xid[0],msg,rtn,rtn);

    }else if(req==2){
      if(UseRecvThrd==0){
	str="Message(1:S1F1 2:S1F21 3:S6F11   6:S1F2 7:S1F22 8:S2F50) : ";
      }else{
	str="Message(1:S1F1 2:S1F21 3:S6F11) : ";
      }
      mno=ReadInt(in,str,10);
      switch(mno){
	case 1: rtn=SendS1F1 ();		break;
	case 2: rtn=SendS1F21();		break;
	case 3: rtn=SendS6F11();		break;
	case 6: rtn=SendS1F2E(dsd,xsd);		break;
	case 7: rtn=SendS1F22(dsd,xsd);		break;
	case 8: rtn=SendS2F50(dsd,xsd);		break;
      }

    }else if(req==3){
      for(Break=i=0;Break==0;i++){
	Sleep(SendWait);
	if(FuncType==0)	stat=SAcb._TDSCommStatus(0);
	else		stat=UAcb._TDSUDrvStatus(0);
	if(stat==3){
	  if((rtn=SendS6F11())	< 0){
	    printf("(E) Send error (%d)\n",rtn);	Sleep(ERROR_SLEEP);
	  }
	  if((i%SEND_NO)			==0)	Sleep(SendSleep);
      } }
      rtn=0;
    }

    if(rtn<(-999) || ((-900)<rtn && rtn<0)){
      printf("(E) I/O Error (%d)\n"			,rtn);
  } }

  if(SECS_MODE	!=0){			// In case of HSMS, Shutdown process
					// HSMS 接続の場合、切断処理
    if(FuncType	==0)	rtn=SAcb._TDSCommStatus(0);
    else		rtn=UAcb._TDSUDrvStatus(0);
    if(rtn	==3){
    // Deselect request is not performed. (Of course you may go. However SEMI
    // claims that HSMS-SS does not perform Deselect request.)
    // Deselect request は行わない。 (もちろん行ってもよい。SEMI では HSMS-SS
    // において、Deselect request は行わない、としている。)
    //if(FuncType==0)	rtn=SAcb._TDSCommSend(0x0800,0,0,0,msg,0,hd);
    //else		rtn=UAcb._TDSUDrvSend(0x0800,0,0,0,msg,0,hd);
    //if(rtn							< 0) break L0;
    //printf("(E) Deselected\n");
      if(FuncType==0)	rtn=SAcb._TDSCommSend(0x0900,0,0,0,msg,0,hd);
      else		rtn=UAcb._TDSUDrvSend(0x0900,0,0,0,msg,0,hd);
      if(rtn							< 0) break L0;
      printf("(E) Separated\n");
  } }
  }	// L0:

  Break  = 1;
  if(SAcb!=null)	SAcb._TDSCommClose(0);		SAcb=null;
  if(UAcb!=null)	UAcb._TDSUDrvClose(0);		UAcb=null;
  if(rtn < 0)		printf("(H) Error (%d)\n"	,rtn);
}

}
