/*
  XPortIO.c

  Copyright 12-Feb-2004 MBARI
  Written: 12-Feb-2004 Mark Sibenac
  Last mod: 12-Feb-2004 sib - creation

  Control GPIO on Lantronix XPort via TCP socket
*/

#include <stdio.h>
#include <fcntl.h>
#include <sys/termio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <ctype.h>
#ifdef _QNX
 #include <sys/select.h>
#endif

int sendMsg (char *machine, int CP, int state)
{
  int sd;
  struct hostent *hp;
  struct sockaddr_in server;
  unsigned char buff[10];
 
  printf ("machine=%s, CP=%d, state=%d\n", machine, CP, state);

  memset((char *)&server, 0, sizeof(struct sockaddr_in));
  
  server.sin_family = AF_INET;
  server.sin_port = htons((u_short)0x77F0);

  if (isdigit(machine[0])) {
    server.sin_addr.s_addr = inet_addr(machine);
  } else {
    if ((hp = gethostbyname((char *)machine)) == NULL) {
      return -1;
    }
    memcpy((char *)&server.sin_addr, (char *)hp->h_addr,  hp->h_length);
  }
  
  if ((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
    printf ("Could not create socket\n");
    return -1;
  }
  
  if (connect(sd, (struct sockaddr *)&server, sizeof(server)) < 0) {
    printf ("Could not connect to socket\n");
    return -1;
  }

  buff[0] = 0x1B;
  buff[1] = 1 << (CP-1);
  buff[2] = 0x00;
  buff[3] = 0x00;
  buff[4] = 0x00;
  buff[5] = state << (CP-1);
  buff[6] = 0x00;
  buff[7] = 0x00;
  buff[8] = 0x00;

  write (sd, buff, 9);
  close (sd);
}

void printUsage (void)
{
  printf ("Usage: XPortIO [IP,Hostname] [1,2,3] [0,1]\n");
  printf ("       where [IP,Hostname] is an IP address or hostname\n");
  printf ("       where [1,2,3] is one of the GPIO lines: CP1, CP2, CP3\n");
  printf ("       where [0,1] is OFF or ON\n");
}

int main (int argc, char **argv)
{
  int CP=0;
  int state=0;
  char *machine=argv[1];

  switch (argc) {
  case 1 : // nothing on command line
    printUsage();
    exit(-1);
    break;
  case 2 : // only one arg, so assume turn on CP1
    printf ("Turning on bit CP1 on %s\n", machine);
    sendMsg (machine, 1, 1);
    break;
  case 3 : // only two args, so assume turn on
    CP = *argv[2] - '0';
    if (CP < 1 || CP > 3) {
      printf ("Bad argument CP=%s for machine %s\n", argv[2], argv[1]);
      printUsage();
      exit(-1);
    }
    printf ("Turning on bit CP%d on %s\n", CP, machine);
    sendMsg (machine, CP, 1);
    break;
  case 4 : // got all three args
    CP = *argv[2] - '0';
    if (CP < 1 || CP > 3) {
      printf ("Bad argument CP=%s for %s\n", argv[2], argv[1]);
      printUsage();
      exit(-1);
    }
    state = *argv[3] - '0';
    if (state < 0 || state > 1) {
      printf ("Bad argument state=%s for %s\n", argv[3], argv[1]);
      printUsage();
      exit(-1);
    }
    sendMsg (machine, CP, state);
    break;
  } /* switch (argc) */

  return 0;
}
