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

/* sony_driver.c: command routines for SONY LDP-1000A videodisc player */

#include "models.h"
#include "structs.h"
#include "sony.h"
typedef unsigned char byte;

#define MAXRETRYS 0		/* the number of times we try before giving up */
#define SONYDELAY 10		/* 10 millisecs between chars for sony to swallow */
#define SONY_STD_WAIT 250	/* normal time before a timeout occurs */

/* after the sony finishes a search operation, it still
   takes a significant portion of a second for its video
   output to stabilize; if you don't wait, it may be unstable
   enough to mess up a digitization */

#define SONY_SETTLE_TIME 175

int		sony_debug = 0;
static	int  	retry = 0;
static int timeouts = 0;
static	char	inchars[16];
static int	lid_open = 0;
static int	motor_off = 0;
static int      no_disc = 0;
/* ------------------------------------------------------------------------ */

sony_cmd(rpd,num)

	RPD_ptr	rpd;
	int 	num;
{
byte	cmd;
int	res;
int	loadtime = 15000;	/* 15 seconds for loading/unloading */
int     forked = 0;
/*
  all commands are sent twice, so that an unsolicited ACK
  is not mistaken for the normal response
  */

switch(num)
  {
  case INDEX_ON:
    cmd = SONY_INDEXON;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    if( res == SONY_ACK )	/* now set state */
      rpd->state.indexon = 1;
    break;
  case INDEX_OFF:
    cmd = SONY_INDEXOFF;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    if( res == SONY_ACK )	/* now set state */
      rpd->state.indexon = 0;
    break;
  case INDEX_TOGGLE:
    if (rpd->state.indexon) cmd = SONY_INDEXOFF;
    else cmd = SONY_INDEXON;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    if( res == SONY_ACK )	/* now set state */
      rpd->state.indexon = !rpd->state.indexon;
    break;
  case A1_ON:
    cmd = SONY_CH1ON;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    if( res == SONY_ACK )	/* now set state */
      rpd->state.audio1_on = 1;
    break;
  case A1_OFF:
    cmd = SONY_CH1OFF;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    if( res == SONY_ACK )	/* now set state */
      rpd->state.audio1_on = 0;
    break;
  case A2_ON:
    cmd = SONY_CH2ON;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    if( res == SONY_ACK )	/* now set state */
      rpd->state.audio2_on = 1;
    break;
  case A2_OFF:
    cmd = SONY_CH2OFF;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    if( res == SONY_ACK )	/* now set state */
      rpd->state.audio2_on = 0;
    break;
  case SQUELCH_ON:
  case SQUELCH_OFF:
    res = 1;
    break;
  case FORKLOAD:
    if (sony_getstatus(rpd) == -1) return -1;
    if (!motor_off || lid_open || no_disc) return(-1);
    forked = 1;
    if (fork()) return(0);
  case LOAD:
    cmd = SONY_MOTORON;
    sony_getstatus(rpd);
    if( !motor_off )
      {
	res = SONY_ACK;
	break;
      }
    if( lid_open || no_disc)
      {
	res = -1;
	break;
      }
    sony_ttyio(rpd->fd,&cmd,1,0);
    res = ttyutil_read(rpd->fd,inchars,1,loadtime);
    if( res > 0 && inchars[res-1] == SONY_ACK )
      {
	rpd->state.volume_loaded = 1;
	strcpy(rpd->volume,"#ffffff");	/* it's empty */
	res = SONY_ACK;
      }
#ifdef OBSOLETE
    /* PERHAPS THE SONY_LDP1000A USES 2 ACKS ALSO.  THE LDP2000 MANUAL
       SAYS THAT THE 1000A DOES!!!! CHECK INTO THIS SOON */
    if (rpd->devtype == SONY_LDP1000A)
      sleep(15);  /* 1000A needs to do more before ready */
    else {
#endif /* OBSOLETE */
      res = ttyutil_read(rpd->fd,inchars,1,loadtime);
#ifdef OBSOLETE
    }			  
#endif /* OBSOLETE */
    rpd_setframe (rpd,1);
    rpd_setspeed (rpd,0);
    break;
  case STARTLOAD:
    sony_ttyio(rpd->fd,&cmd,1,0);
    return(loadtime);  /* number of milliseconds */
  case ENDLOAD:
    res = ttyutil_read(rpd->fd,inchars,1,500);
    if( res > 0 && inchars[res-1] == SONY_ACK )
      {
	rpd->state.volume_loaded = 1;
	strcpy(rpd->volume,"#ffffff");	/* it's empty */
	res = SONY_ACK;
      }
    rpd_setframe (rpd,1);
    rpd_setspeed (rpd,0);
    return(15);  /* number of seconds */
  case EJECT:
  case UNLOAD:
    cmd = SONY_MOTOROFF;
    sony_getstatus(rpd);
    if( motor_off || lid_open )
      {
	res = SONY_ACK;
	break;
      }
    /* special processing; because of long timeout, wait for byte here */
    sony_ttyio(rpd->fd,&cmd,1,0);
    res = ttyutil_read(rpd->fd,inchars,1,loadtime);
    if( res > 0 && inchars[res-1] == SONY_ACK )	/* now set state */
      {
	rpd->state.volume_loaded = 0;
	rpd->volume[0] = 0;
	res = SONY_ACK;
      }
    rpd_setframe (rpd,-1);
    rpd_setspeed (rpd,0);
    break;
  default:
    bsdsyslog(LOG_NOTICE,"sony_cmd: illegal request %d\n",cmd);
    break;
  }
if (forked) _exit(0);
if( res != SONY_ACK ) {
  rpd_error(rpd);
  return(-1);
}
else {
  rpd_clear_error(rpd);
  return(0);
}
}

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

sony_findspeed(num)

	int	num;
{
  int 	cmd;
  int     realspeed;
  int     dir;

  if(num < 0)
    dir = -1;
  else
    dir = 1;
  num = abs(num);
  
  if (num == 0)
    realspeed = 0;
  else if (num > 0 && num < 30 ) {
    cmd = 30/num;
    realspeed = 30/cmd;
  }  
  else if (num > 29 && num < 61 )
    realspeed = 30;
  else if (num > 60 && num < 121 )
    realspeed = 90;
  else if (num > 120)
    realspeed = 3000;
	  
  return (dir*realspeed);
}

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

sony_varspeed(rpd,num)

	RPD_ptr	rpd;
	int	num;
{
  byte 	cmd;
  int	res;
  byte    cmdstr[16];
  int     len;
  int     realspeed;

  if (sony_cancel(rpd) == -1) return -1;

  if (num < -120) {
    cmd = SONY_RSCAN;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    realspeed = -3000;
  }
  if (num < -60 && num > -121 ) {
    cmd = SONY_RFAST;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    realspeed = -90;
  }
  if (num < -29 && num > -61 ) {
    cmd = SONY_RPLAY;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    realspeed = -30;
  }
  if (num < 0 && num > -30 ) {
    cmd = SONY_RSTEP;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    if (rpd->devtype == SONY_LDP1000A) {
      cmd = SONY_STILL;
      res = sony_ttyio(rpd->fd,&cmd,1,1);
    }
    cmd = -1*30/num;
    sprintf(cmdstr,"%05d%c",cmd,SONY_ENTER);
    len = strlen(cmdstr);
    res = sony_ttyio(rpd->fd,cmdstr,len,1);
    realspeed = -30/cmd;
  }	  
  if (num == 0) {
    cmd = SONY_STILL;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    realspeed = 0;
  }
  if (num > 120) {
    cmd = SONY_FSCAN;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    realspeed = 3000;
  }
  if (num > 60 && num < 121 ) {
    cmd = SONY_FFAST;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    realspeed = 90;
  }
  if (num > 29 && num < 61 ) {
    cmd = SONY_FPLAY;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    realspeed = 30;
  }
  if (num > 0 && num < 30 ) {
    cmd = SONY_FSTEP;
    res = sony_ttyio(rpd->fd,&cmd,1,1);
    if (rpd->devtype == SONY_LDP1000A) {
      cmd = SONY_STILL;
      res = sony_ttyio(rpd->fd,&cmd,1,1);
    }
    cmd = 30/num;
    sprintf(cmdstr,"%05d%c",cmd,SONY_ENTER);
    len = strlen(cmdstr);
    res = sony_ttyio(rpd->fd,cmdstr,len,1);
    realspeed = 30/cmd;
  }	  
  
  if( res != SONY_ACK ) {
    rpd_error(rpd);
    return(COULDNT_CHANGE_SPEED);
  }
  else {
    rpd_setspeed (rpd, realspeed);
    rpd_setframe (rpd, -1);
    rpd_clear_error(rpd);
    return(realspeed);
  }
}

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

sony_jog(rpd,num)
     RPD_ptr	rpd;
     int	num;
{
  int	i;
  byte	cmd;
  byte	dir;
  
  if (sony_cancel(rpd) == -1) return -1;

  if(rpd->speed)
    sony_varspeed(rpd, 0);

  (num > 0) ? (dir=SONY_FSTEP) : (dir=SONY_RSTEP);
  if( num<0 ) num = (-num);
  
  for( i=0; i<num; i++ )
    {
      if( sony_ttyio(rpd->fd,&dir,1,0) ) {
	rpd_error(rpd);
	return (-1);
      }
      mpause(33);	/* 33 millisecs */
      cmd = SONY_STILL;
      if( sony_ttyio(rpd->fd,&cmd,1,0) ) {
	rpd_error(rpd);
	return (-1);
      }
    }
  rpd_setspeed (rpd,0);
  if (rpd_getframe(rpd) < 0) sony_getframe(rpd);
  if (dir == SONY_FSTEP) rpd_setframe (rpd, rpd_getframe(rpd)+1);
  else rpd_setframe (rpd, rpd_getframe(rpd)-1);
  rpd_clear_error(rpd);
  return (0);
}


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

sony_getframe(rpd)

	RPD_ptr	rpd;
{
  int  frame;
  byte cmd;
  
  if (rpd_getframe(rpd) > 0) return (rpd_getframe(rpd));
  /* can't SONY_CL or stops playing */
  cmd = SONY_ADDRINQ;
  if( sony_ttyio(rpd->fd,&cmd,1,5) == -1 ) {
    rpd_error(rpd);
    return (-1);
  }
  inchars[5] = '\0';
  frame = atoi(inchars);
  rpd_setframe (rpd, frame);
  rpd_clear_error(rpd);
  return (frame);
}

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

sony_getstatus(rpd)
	RPD_ptr	rpd;
{
  byte	cmd;

  cmd = SONY_STATUSINQ;
  if( sony_ttyio(rpd->fd,&cmd,1,5) == -1 )
    {
      rpd_error(rpd);
/*      if (++timeouts > SONY_MAX_TIMEOUTS) need_to_rebuild_list = 1; */
      bsdsyslog(LOG_NOTICE,
		"sony_getstatus: unable to get status %s",rpd->port);
      return (-1);
    }
  
  if (rpd->devtype == SONY_LDP1000A) {
    lid_open = ( inchars[0] & 8 );
    motor_off = ( inchars[0] & 32 );
    no_disc = lid_open;
  }
  else {
    lid_open = 0;  /* Lid will close automatically anyway */
    motor_off = (inchars[0] & 32) | (inchars[0] & 8);
    no_disc = (inchars[0] & 4);
  }
  rpd_clear_error(rpd);
  return 0;
}	

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

sony_proddev(rpd)
     RPD_ptr rpd;
{
  if (sony_getstatus(rpd) == -1) return -1;
  if (lid_open || no_disc) {
    bsdsyslog(LOG_NOTICE,"%s, %s: lid open\n",
	      rpd->devname,rpd->port);
    return -1;
  }
  return 0;
}

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

sony_search(rpd,frame,wait)

	RPD_ptr	rpd;
	int	frame;
	int	wait;		/* if true, hangs until it gets there 
					or times out */
{
  byte	cmdstr[16];
  byte	reply[16];
  int	res;
  int	len;
  
  
  if (frame < 1) frame = 1;
  res = sony_getframe(rpd);
  if (res == -1) return -1;
  if (frame == res) return(frame);  /* we're already there */
  if (frame-res == -1) {
    if (sony_jog(rpd, -1) == -1) {
      return -1;
    }
    else {
      rpd_clear_error(rpd);
      return(frame);
    }
  }
  if (frame-res == 1) {
    if (sony_jog(rpd, 1) == -1) {
      return -1;
    }
    else {
      rpd_clear_error(rpd);
      return(frame);
    }
  }
  
  if (sony_cancel(rpd) == -1) return -1;
/*  sprintf(cmdstr,"%c%c%c",SONY_CL,SONY_CE,0);
  sony_ttyio(rpd->fd,cmdstr,strlen(cmdstr),1);*/

  sprintf(cmdstr,"%c%05d%c%c",
	  SONY_SEARCH,frame,SONY_ENTER,0);
  len = strlen(cmdstr);
  
  ttyutil_clear(rpd->fd);
  
  if( (res = ttyutil_write(rpd->fd,cmdstr,len,10)) < 0 )
    {
      bsdsyslog(LOG_NOTICE, 
		"sony_search: write failed: %s",rpd->port);
      rpd_error(rpd);
/*      if (++timeouts > SONY_MAX_TIMEOUTS) need_to_rebuild_list = 1;*/
      return(-1);
    }
  
  if( !wait )		/* don't wait for reply */
    {
      return(0);
    }
  else if( (res = ttyutil_read(rpd->fd,reply,len+1,6000)) < 0 )
    {
      if( res == -1 ) {
	rpd_error(rpd);
/*	if (++timeouts > SONY_MAX_TIMEOUTS) need_to_rebuild_list = 1;*/
	bsdsyslog(LOG_NOTICE,
		  "sony_search: read failed: %s",rpd->port);
      }
      if( res == -2 ) {
	rpd_error(rpd);
/*	if (++timeouts > SONY_MAX_TIMEOUTS) need_to_rebuild_list = 1;*/
	bsdsyslog(LOG_NOTICE,
		  "sony_search: timeout: %s",rpd->port);
      }
      (*rpd->reset)(rpd);
      return(-1);
    }
  
  if( reply[len] != SONY_COMPLETION )
    {
      rpd_error(rpd);
/*      if (++timeouts > SONY_MAX_TIMEOUTS) need_to_rebuild_list = 1;*/
      bsdsyslog(LOG_NOTICE,
		"sony_search: error %d: %s",reply[len],
		rpd->port);
      (*rpd->reset)(rpd);
      return(-1);
    }
  mpause(SONY_SETTLE_TIME);
  rpd_setspeed (rpd,0);
  rpd_setframe (rpd,-1);
  sony_getframe (rpd);
  rpd_clear_error(rpd);
  return(0);
}

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

sony_reset(rpd)
     
     RPD_ptr	rpd;
{
  int	ret = 0;
  
#ifdef OBSOLETE  
  sprintf(cmdstr,"%c%c%c",SONY_CL,SONY_CE,0);
  if( sony_ttyio(rpd->fd,cmdstr,strlen(cmdstr),1) < 0)
    {
      bsdsyslog(LOG_NOTICE,"sony_reset: sony_ttyio failed: %s\n",
	      rpd->port);
      rpd->state.volume_loaded = 0;
      rpd->state.not_responding = 1;
      return -1;
    }
#endif /* OBSOLETE */
  if (sony_cancel(rpd) == -1) {
    bsdsyslog(LOG_NOTICE,"sony_reset: sony_cancel failed: %s\n",
	      rpd->port);
    rpd->state.volume_loaded = 0;
    rpd->state.not_responding = 1;
    return -1;		
  }

  if( sony_getstatus(rpd) )	/* couldn't even get status */
    {
      bsdsyslog(LOG_NOTICE,"sony_reset: sony_getstatus failed: %s\n",
	      rpd->port);
      rpd->state.volume_loaded = 0;
      rpd->state.not_responding = 1;
      return -1;		
    }
  
  if( lid_open )
    {
      bsdsyslog(LOG_NOTICE,"%s: lid is open\n",rpd->port);
      rpd->state.not_responding = 1;
      rpd->state.volume_loaded = 0;
      ret = -1;
    }
  
  if (no_disc)
    {
      bsdsyslog(LOG_NOTICE,
		"%s: %s: No disc in player",rpd->devname, rpd->port);
      rpd->state.not_responding = 1;
      rpd->state.volume_loaded = 0;
      ret = -1;
    }
  
  if (!motor_off) {
    ret += sony_cmd(rpd,INDEX_OFF);
    ret += sony_cmd(rpd,A1_ON);
    ret += sony_cmd(rpd,A2_ON);
  }
  if( ret < 0 )
    {
      rpd->state.volume_loaded = 0;
      rpd->state.not_responding = 1;
      bsdsyslog(LOG_NOTICE,
		"sony_reset: not responding: %s", rpd->port);
      ret = -1;
    }
  else
    {
      rpd->state.not_responding = 0;
      ret = 0;
      timeouts = 0;
    }
  return ret;
}

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

sony_segplay(rpd,f1,f2,speed,wait)
     RPD_ptr	rpd;
     int	f1,f2;
     int     speed;
     int	wait;		/* if true, hangs until done */
{
  byte cmdstr[100];
  byte reply[16];
  int  res;
  int  len;
  int realspeed, abspeed, dir;

#ifdef OBSOLETE  
  if( (f1 > f2) && rpd->devtype == SONY_LDP1000A) 
    {
      bsdsyslog(LOG_NOTICE,"%s: segplay: can only play forward yet\n",
	      rpd->port);
      return(-1);
    }
#endif

  realspeed = sony_findspeed(speed);
  if(realspeed > 90)
    realspeed = 90;
  else if(realspeed < -90)
    realspeed = -90;

  abspeed = abs(realspeed);

  if (f1) {
    res = sony_search( rpd, f1, 1 );	/* wait for the reply */
    if (res == -1) return(-1);
    len = abs(f2 - f1);
    if(!len || !realspeed)
      return 0;
  }
  else {
    res = sony_getframe(rpd);
    if(res == -1) return(-1);
    len = abs(f2 - res);
    if(!len && !rpd->speed)
      return 0;
    if(len < 3)
      {
	/* on sony, repeat is unreliable when len is 1 or 2 */

        if(realspeed < 0)
	  dir = -1;
	else dir = 1;
	if(realspeed == 0)
	  {
	    sony_varspeed(rpd,0);
	    return 0;
	  }
	else
	  {
	    sony_jog(rpd, dir * len);
	    return 0;
	  }
      }
  }

  if (realspeed == 0) {
    sony_varspeed(rpd, 0);
    return(0);
  }

  if (sony_cancel(rpd) == -1) return -1;

  /* if disc is in motion, and CURRENT_FRAME is specified, 
     may have to stop it momentarily to determine the
     proper direction to go in (by getting an exact current frame);
     actually, it turns out the sony is a (semi-)intelligent life form,
     and figures out all by itself what direction to go in; but
     we have to maintain the correct speed (direction) in the
     rpd cache, so we still have to go through this stuff
     */

  if(f1 == CURRENT_FRAME && rpd->speed)
    {      
      /* disc is already moving; see if we're inside the 'danger zone'; 
	 if so, stop disc and get current frame before changing rate;
	 otherwise, we might have passed the target and be going in
	 the wrong direction; note that rpd->frame has just been set
	 by DoPlaySeg() in dofuncs.c, if CURRENT_FRAME is specified */

      if( abs(f2 - rpd->frame) <= MAX_GETFRAME_ERROR(abs(rpd->speed)) )
	{
	  sony_varspeed(rpd, 0);
	  rpd_setframe(rpd, rpd_getframe(rpd));
	  /* reverse direction if need to */
	  if(f2 < rpd->frame && realspeed > 0)
	    realspeed = -1 * realspeed;
	  else if(f2 > rpd->frame && realspeed < 0)
	    realspeed = abs(realspeed);
	  else if(f2 == rpd->frame)
	    return (0);
	}
    }
  else if(f1 == CURRENT_FRAME && !rpd->speed && f2 == rpd->frame)
    {
      /* we're not moving and the target is where we already are */
      return 0;
    }

  if (abspeed > 29 && abspeed < 61)
    sprintf(cmdstr,"%c%d%c%c%c%c",
	    SONY_REPEAT,f2,SONY_ENTER,'1',SONY_ENTER,0);
  else {
    if (abspeed > 0 && abspeed < 30) {
      if(rpd->devtype != SONY_LDP1000A)
	sprintf(cmdstr,"%c%c%d%c%d%c%c%c%c",
		SONY_REPEAT,SONY_FSTEP,f2,SONY_ENTER, 
		30/abspeed,SONY_ENTER,
		'1',SONY_ENTER,0);
      else /* LDP1000A */
	{
	  if(realspeed < 0)
	    sony_jog(rpd, -1);
	  if(f2 == rpd->frame)
	    return 0;
	  sprintf(cmdstr,"%c%c%d%c%c%c%d%c%c",
		  SONY_REPEAT,SONY_FSTEP,f2,SONY_ENTER, 
		  '1',SONY_ENTER,
		  30/abspeed,SONY_ENTER,0);
	}
    }
    if (abspeed > 60) {
      sprintf(cmdstr,"%c%c%d%c%c%c%c",
	      SONY_REPEAT,SONY_FFAST,f2,SONY_ENTER,'1',SONY_ENTER,0);
    }
  }
  ttyutil_clear(rpd->fd);
  if( (res = ttyutil_write(rpd->fd,cmdstr,strlen(cmdstr),10)) == -1 )
    {
      rpd_error(rpd);
/*      if (++timeouts > SONY_MAX_TIMEOUTS) need_to_rebuild_list = 1;*/
      bsdsyslog(LOG_NOTICE,
		"sony_segplay: write error: %s", rpd->port);
      return(-1);
    }
  
  if( !wait )
    {
      rpd_setspeed(rpd, realspeed);
      rpd_setframe(rpd, -1);
      return(0);
    }
  else if( (res = ttyutil_read(rpd->fd,reply,strlen(cmdstr)+1,
			       (len*33)+1000)) < 0 )
    {
      if( res==-1 ) {
	rpd_error(rpd);
/*	if (++timeouts > SONY_MAX_TIMEOUTS) need_to_rebuild_list = 1; */
	bsdsyslog(LOG_NOTICE,
		  "sony_segplay: read error: %s",rpd->port);
      }
      else if (res==-2) {
	rpd_error(rpd);
/*	if (++timeouts > SONY_MAX_TIMEOUTS) need_to_rebuild_list=1;*/
	bsdsyslog(LOG_NOTICE,
		  "sony_segplay: time out on play: %s",
		  rpd->port);
      }
      return(-1);	
    }
  rpd_setframe(rpd, f2);
  rpd_setspeed(rpd, 0);
  rpd_clear_error(rpd);
  return(0);
}

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

sony_cancel(rpd)
     RPD_ptr rpd;
{
  byte cmdstr[5];
  sprintf(cmdstr,"%c%c%c",SONY_CL,SONY_CE,0);
  ttyutil_clear(rpd->fd);
  if( sony_ttyio(rpd->fd,cmdstr,strlen(cmdstr),1) < 0)
    {
      bsdsyslog(LOG_NOTICE,"sony_cancel: sony_ttyio failed: %s\n",
	      rpd->port);
#ifdef OBSOLETE
      rpd->state.volume_loaded = 0;
      rpd->state.not_responding = 1;
#endif OBSOLETE
      rpd_error(rpd);
      return -1;
    }
  rpd_clear_error(rpd);
  ttyutil_clear(rpd->fd);
  return(0);
}  

sony_ttyio( fd, cmdstr, writenum, readnum )

	int	fd;
	char 	*cmdstr;
	int	writenum;
	int	readnum;
{
int	num = 0;

/*	ttyutil_debug = sony_debug;*/
	ttyutil_clear(fd);

	if( ttyutil_write( fd,cmdstr,writenum,SONYDELAY ) == -1 )
		return (-1);

	if( readnum == 0 )
		return (0);
	
	if( (num=ttyutil_read(fd,inchars,readnum,SONY_STD_WAIT)) < 0 ) {
/*	   if (++timeouts > SONY_MAX_TIMEOUTS) need_to_rebuild_list = 1;*/
	   bsdsyslog(LOG_NOTICE,"sony_ttyio: i/o timeout");
	   return (-1);	/* timeout after .5 seconds */
	 }

	if( num==-2 || (readnum==1 && inchars[0] == SONY_ERROR) )
	{
		if( sony_debug )
		{
			if( num == -2 )
			bsdsyslog(LOG_NOTICE,"sony_ttyio: NO RESPONSE, try %d\n",retry+1);
			else
			bsdsyslog(LOG_NOTICE,"sony_ttyio: ERROR RESPONSE, try %d\n",retry+1);
		}
		if( retry++ < MAXRETRYS )
		{
		int rv;
			rv = sony_ttyio(fd,cmdstr,writenum,readnum);
			retry = 0;
			return (rv);
		}
		else
		{
/*		  need_to_rebuild_list = 1; */
			bsdsyslog(LOG_NOTICE, 
			       "sony_ttyio: i/o timeout");
			return (-1);
		}
	}

	if( readnum==1 )	/* search - completion, nottarget, error */
		return ((int)inchars[0]);
	return(0);
}

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

sony_setfuncs( disc )

	RPD_ptr	disc;
{
  disc->proddev = sony_proddev;
  disc->reset = sony_reset;
  disc->cmd = sony_cmd;
  disc->search = sony_search;
  disc->segplay = sony_segplay;
  disc->getspeed = rpd_getspeed_f;
  disc->getframe = sony_getframe;
  disc->varspeed = sony_varspeed;
  disc->jog = sony_jog;
  disc->record = NULL;
  disc->buildfreelist = NULL;
  disc->lastframe = 54000;
}
