/* Automatically generated from Squeak on #(21 October 2001 9:18:03 pm) */

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

/* Default EXPORT macro that does nothing (see comment in sq.h): */
#define EXPORT(returnType) returnType

/* Do not include the entire sq.h file but just those parts needed. */
/*  The virtual machine proxy definition */
#include "sqVirtualMachine.h"
/* Configuration options */
#include "sqConfig.h"
/* Platform specific definitions */
#include "sqPlatformSpecific.h"

#define true 1
#define false 0
#define null 0  /* using 'null' because nil is predefined in Think C */
#include "SerialPlugin.h"

/* memory access macros */
#define byteAt(i) (*((unsigned char *) (i)))
#define byteAtput(i, val) (*((unsigned char *) (i)) = val)
#define longAt(i) (*((int *) (i)))
#define longAtput(i, val) (*((int *) (i)) = val)

/*** Variables ***/
static struct VirtualMachine* interpreterProxy;
static const char *moduleName = "SerialPlugin 21 October 2001 (i)";

/*** Function Prototypes ***/
#pragma export on
EXPORT(const char*) SerialPlugin_getModuleName(void);
EXPORT(int) SerialPlugin_initialiseModule(void);
EXPORT(int) SerialPlugin_primitiveSerialPortClose(void);
EXPORT(int) SerialPlugin_primitiveSerialPortOpen(void);
EXPORT(int) SerialPlugin_primitiveSerialPortRead(void);
EXPORT(int) SerialPlugin_primitiveSerialPortWrite(void);
EXPORT(int) SerialPlugin_setInterpreter(struct VirtualMachine* anInterpreter);
EXPORT(int) SerialPlugin_shutdownModule(void);
#pragma export off


/*	Note: This is hardcoded so it can be run from Squeak.
	The module name is used for validating a module *after*
	it is loaded to check if it does really contain the module
	we're thinking it contains. This is important! */

EXPORT(const char*) SerialPlugin_getModuleName(void) {
	return moduleName;
}

EXPORT(int) SerialPlugin_initialiseModule(void) {
	return serialPortInit();
}

EXPORT(int) SerialPlugin_primitiveSerialPortClose(void) {
	int portNum;

	portNum = interpreterProxy->stackIntegerValue(0);
	if (interpreterProxy->failed()) {
		return null;
	}
	serialPortClose(portNum);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->pop(1);
	return null;
}

EXPORT(int) SerialPlugin_primitiveSerialPortOpen(void) {
	int portNum;
	int baudRate;
	int stopBitsType;
	int parityType;
	int dataBits;
	int inFlowControl;
	int outFlowControl;
	int xOnChar;
	int xOffChar;

	portNum = interpreterProxy->stackIntegerValue(8);
	baudRate = interpreterProxy->stackIntegerValue(7);
	stopBitsType = interpreterProxy->stackIntegerValue(6);
	parityType = interpreterProxy->stackIntegerValue(5);
	dataBits = interpreterProxy->stackIntegerValue(4);
	inFlowControl = interpreterProxy->stackIntegerValue(3);
	outFlowControl = interpreterProxy->stackIntegerValue(2);
	xOnChar = interpreterProxy->stackIntegerValue(1);
	xOffChar = interpreterProxy->stackIntegerValue(0);
	if (interpreterProxy->failed()) {
		return null;
	}
	serialPortOpen(
			portNum, baudRate, stopBitsType, parityType, dataBits,
			inFlowControl, outFlowControl, xOnChar, xOffChar);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->pop(9);
	return null;
}

EXPORT(int) SerialPlugin_primitiveSerialPortRead(void) {
	int bytesRead;
	int arrayPtr;
	int portNum;
	char *array;
	int startIndex;
	int count;
	int _return_value;

	portNum = interpreterProxy->stackIntegerValue(3);
	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(2)));
	array = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(2))));
	startIndex = interpreterProxy->stackIntegerValue(1);
	count = interpreterProxy->stackIntegerValue(0);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->success((startIndex >= 1) && (((startIndex + count) - 1) <= (interpreterProxy->byteSizeOf(((int) (array) -4)))));
	arrayPtr = ((((int) array )) + startIndex) - 1;

	/* adjust for zero-origin indexing */

	bytesRead = serialPortReadInto( portNum, count, arrayPtr);
	_return_value = interpreterProxy->integerObjectOf(bytesRead);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->popthenPush(5, _return_value);
	return null;
}

EXPORT(int) SerialPlugin_primitiveSerialPortWrite(void) {
	int bytesWritten;
	int arrayPtr;
	int portNum;
	char *array;
	int startIndex;
	int count;
	int _return_value;

	portNum = interpreterProxy->stackIntegerValue(3);
	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(2)));
	array = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(2))));
	startIndex = interpreterProxy->stackIntegerValue(1);
	count = interpreterProxy->stackIntegerValue(0);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->success((startIndex >= 1) && (((startIndex + count) - 1) <= (interpreterProxy->byteSizeOf(((int) (array) -4)))));
	if (!(interpreterProxy->failed())) {
		arrayPtr = ((((int) array )) + startIndex) - 1;
		bytesWritten = serialPortWriteFrom(portNum, count, arrayPtr);
	}
	_return_value = interpreterProxy->integerObjectOf(bytesWritten);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->popthenPush(5, _return_value);
	return null;
}


/*	Note: This is coded so that is can be run from Squeak. */

EXPORT(int) SerialPlugin_setInterpreter(struct VirtualMachine* anInterpreter) {
	int ok;

	interpreterProxy = anInterpreter;
	ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR;
	if (ok == 0) {
		return 0;
	}
	ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR;
	return ok;
}

EXPORT(int) SerialPlugin_shutdownModule(void) {
	return serialPortShutdown();
}
