/*
 * sc88drv.c -- Machine/OS dependent serial I/O code for Roland Corp. SC-88 Pro
 *
 *  Copyright 1998  John Stone   (j.stone@acm.org)
 *
 *  $Id: sc88drv.c,v 1.3 1998/02/25 01:25:43 johns Exp $
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "rawserial.h" /* protos for raw serial I/O code */
#include "seq.h"       /* protos for MidiIOEvent */
#include "devices.h"   /* protos for device installation code */

#define SC88DRV_INTERNAL
#include "sc88drv.h"   /* protos and types for this file */

static char sc88drv_drivername[] = "SC88";
static char sc88drv_version[] = "$Revision: 1.3 $";

/*
 * Roland SC-88 Programming information:
 *   The SC-88 connects at 38400 baud via RS-232 serial to the host machine.
 *   Unlike the predecessor models such as the SC-7, the SC-88 serial protocol
 *   includes a special extension to allow it to appear as two virtual MIDI
 *   ports to software.  Port selection is done by sending a special sequence
 *   of bytes, which are 0xF5 (undefined MIDI status code) followed by the
 *   a byte for the port number (0x00 or 0x01).  Running status may or may
 *   not be preserved across these port selection messages, this remains
 *   to be determined.  It is likely that if running status is preserved,
 *   it is done on a per-port basis (my guess) which would make the most sense
 *   for typical MIDI sequencing usages.  So, in order to present both 
 *   virtual MIDI ports to the user, this driver must install two "ports"
 *   For each configured SC-88 on the system, and it must handle sending
 *   the port selection bytes when necessary.  
 */


int sc88drv_drvinst(AddMIDIDriverFunc adddriver, MidiSystem * midisystem) {
  MidiDriver drvinfo;

  drvinfo.typename  = sc88drv_drivername;
  drvinfo.version   = sc88drv_version;
  drvinfo.flags     = DEVICE_NO_FLAGS;
  drvinfo.openfunc  = sc88drv_open;
  drvinfo.writefunc = sc88drv_write;   
  drvinfo.readfunc  = sc88drv_read;
  drvinfo.closefunc = sc88drv_close;

  adddriver(midisystem, drvinfo);

  return 0;
}

int sc88drv_open(MidiDeviceSetupParms name, MidiDeviceHandle * handleptr, int *iofd) {
  *iofd = -1;
  return comm_open(name, 38400, handleptr, iofd);
}

int sc88drv_write(MidiDeviceHandle handle, MidiIOEvent * ev) {
  /* 
   * This is where we should determine if we need to send a port selection
   * sequencer or not, and if so, do it before sending the MIDI event data.
   */
  return comm_write(handle, (char *) ev->msg, ev->msglen);
}

int sc88drv_read(MidiDeviceHandle handle, MidiIOEvent * ev) {
  return comm_read(handle, (char *) ev->msg, ev->msglen);
}

int sc88drv_close(MidiDeviceHandle * handleptr) {
  return comm_close(handleptr);
}



