/*
 * Copyright 1988, 1989, 1990, 1991 Massachusetts Institute of Technology
 */

/* swtrutil.c */
#include"structs.h"
/* -------------------------------------------------------------- */

SWTR_ptr swtrutil_open( devtbl, num )
     VCONF_DEVTABLE *devtbl;
     int		num;
{
  char *calloc(), *cur_point, *strchr(), *old_point;
  SWTR_ptr	swtr;
  char devport[64];
  int res, i, outnum, switchnum, channum, default_in, (*proc)(), dummy;
  
#ifdef TRAP_BUG
  bsdsyslog(LOG_INFO, "in swtrutil_open");
#endif /* TRAP_BUG */

  if( !devtbl || num<0 || (num+1)>devtbl->ndevs )
    {
      if (DEBUG) printf("swtrutil_open: given bad devtable or number\n");
      return NULL;
    }
  if( devtbl->dev[num].type != SWTR_DEV )
    {
      if (DEBUG) printf("swtrutil_open: device is not a SWTR\n");
      return NULL;
    }
  
#ifdef TRAP_BUG
  bsdsyslog(LOG_INFO, "passed error checking");
#endif /* TRAP_BUG */

  swtr = (SWTR_ptr) calloc( 1, sizeof(SWTR) );
  if( swtr == NULL )
    return NULL;

#ifdef TRAP_BUG
  bsdsyslog(LOG_INFO, "allocated");
#endif /* TRAP_BUG */

  cur_point = devtbl->dev[num].tty;
  swtr->devnum = atoi(cur_point);
  if ((cur_point = strchr(cur_point, ':') + 1) == (char *)1) {
    swtr->devnum = -1;
    cur_point = devtbl->dev[num].tty;
  }

#ifdef TRAP_BUG
  bsdsyslog(LOG_INFO, "parsed device number");
#endif /* TRAP_BUG */

  strcpy(devport,"/dev/");
  strcat(devport,cur_point);

#ifdef TRAP_BUG
  bsdsyslog(LOG_INFO, "created port name");
#endif /* TRAP_BUG */
  
  strcpy(swtr->devname,devtbl->dev[num].name);
  strcpy(swtr->model,devtbl->dev[num].model);

#ifdef TRAP_BUG
  bsdsyslog(LOG_INFO, "created model info");
#endif /* TRAP_BUG */
  
  res = vconf_find_model( swtr->model );
  proc = vconf_find_set_func( swtr->model);

#ifdef TRAP_BUG
  bsdsyslog(LOG_INFO, "found model and set func");
#endif /* TRAP_BUG */
  swtr->devtype = res;
  switch( res )
    {
    case NETSWTR:
      strcpy(swtr->port,devtbl->dev[num].tty);
      swtr->serv = devtbl->dev[num].server;
      swtr->fd = GConnection(swtr->serv);
      break;
    case -1:
      if (DEBUG) printf("swtrutil_open: bad model <%s>\n",swtr->model);
      free( (char *) swtr );
      return NULL;
      break;
    default:
      swtr->fd = -1;
      strcpy(swtr->port,devport);
      if (swtr->devnum != -1) {
	for (i = 0; i < num_switchers; i++) {
	  if (!strcmp(devport, switchers[i]->port)) {
	    swtr->fd = switchers[i]->fd;
	  }
	}
      }
      else swtr->devnum = 0;
      if (swtr->fd == -1) {
	if( (swtr->fd = 
	     ttyutil_open( devport, devtbl->dev[num].baud,
			  devtbl->dev[num].parity) ) == -1 ) {
	  if (DEBUG) printf("swtrutil_open: unable to open SWTR device\n");
	  free( (char *) swtr );
	  return NULL;
	}
      }
      break;
    }
#ifdef TRAP_BUG
  bsdsyslog(LOG_INFO, "opened unit");
#endif /* TRAP_BUG */
  if (proc == NULL) {
    bsdsyslog(LOG_CRIT, "%s: %s: no setfuncs!", swtr->devname, swtr->port);
    free((char *)swtr);
    return NULL;
  }
  (*proc)(swtr);
#ifdef TRAP_BUG
  bsdsyslog(LOG_INFO, "execcuted set_funcs");
#endif /* TRAP_BUG */

  for (i = 0; i < MAXSERVEROUTS; i++)
    swtr->outputnum[i] = -1;
  swtr->computed = -1;
  for (i = 1; i < MAXOUTPUTS+1; i++) {
    swtr->default_input[i] = swtr->output_chans[i].switcher = -1;
    swtr->avail[i] = -1;
  }
#ifdef TRAP_BUG
  bsdsyslog(LOG_INFO, "set defaults");
#endif /* TRAP_BUG */

  old_point = cur_point = devtbl->dev[num].channel;
  do {
    default_in = -1;
    outnum = atoi(cur_point);
    old_point = cur_point;
    if ((cur_point = strchr(cur_point, ':') + 1) == (char *)1) {
      default_in = outnum;
      outnum = 1;
      cur_point = old_point;
    }
    else
      default_in = atoi(cur_point);
    if ((cur_point = strchr(cur_point, ';') + 1) == (char *)1) {
      switchnum = default_in;
      default_in = -1;
      cur_point = old_point;
    }
    else
      switchnum = atoi(cur_point);
    cur_point = strchr(cur_point, '-') + 1;
    channum = atoi(cur_point);
    if (outnum <= swtr->outputs && outnum >= 1) {
      swtr->output_chans[outnum].switcher = switchnum;
      swtr->output_chans[outnum].channel = channum;
      swtr->default_input[outnum] = default_in;
/*    if (DEBUG) printf("Output %d, switch %d, chan %d, default %d, unit %d\n",
			outnum,switchnum,channum, default_in, swtr->devnum);*/
    }
  } while ((cur_point = strchr(cur_point, ',') + 1) != (char *)1);
#ifdef TRAP_BUG
  bsdsyslog(LOG_INFO, "finished parsing");
#endif /* TRAP_BUG */

  if ((*swtr->inquire)(swtr,1,&dummy,&dummy,&dummy) < 0) {
    free( (char *) swtr );
    return(NULL);
  }
#ifdef TRAP_BUG
  bsdsyslog(LOG_INFO, "reset switcher");
#endif /* TRAP_BUG */

  return swtr;
}

/* -------------------------------------------------------------- */

SWTR_ptr
swtrutil_close( swtr )

	SWTR_ptr swtr;
{
  int res;
	res = vconf_find_model( swtr->model );
	if (res != NETSWTR) ttyutil_close( swtr->fd );
	free( (char *) swtr );
	return NULL;
}

/* -------------------------------------------------------------- */

	/*
	 	the following utilities encode/decode the 3
		input channel settings for a given output 
		channel to/from an integer; the 3 lowest nibbles
		are used, thus:

		0 0 0 0 | 0 0 0 0 | 0 0 0 0 | 0 0 0 0
	     	    	   left      right    video

		where each nibble is 0-15 (1-4 in case of a4x1)
	*/

int
swtrutil_encode_settings( video, left, right )

	int	video,left,right;
{
int	temp = 0;

	/* assume the numbers are okay */

	temp |= (video & 0xf);
	temp |= ( (right & 0xf) << 4 );
	temp |= ( (left & 0xf) << 8 );
	return temp;
}

/* -------------------------------------------------------------- */

int
swtrutil_decode_settings( code, vptr, lptr, rptr )

	int	code;
	int *	vptr;
	int *	lptr;
	int *	rptr;
{

	if( !vptr || !lptr || !rptr )
		return -1;

	/* assume the numbers are okay */

	*vptr = ( code & 0xf );
	*lptr = ( (code & 0xf0) >> 4 );
	*rptr = ( (code & 0xf00) >> 8 );
	return 0;
}
