/*
  Copyright (c) 2004,   Beijing Senselock Data Security Centre
  All rights reserved.
  
  File£ºsample_16_hw.c
  
  Briefs£ºThis code will demonstrate how to use code memory and
  		  dynamic memory in your SenseLock EL EXF.
       
  
*/
#include <string.h>
#include "..\..\inc\hardware\ses_v3.h"
#include "..\inc\sample_16.h"

#define _DEBUG

#define Pi 3.14159
/* global variable defination. */
unsigned char last_ses_error = 0; /* last SES error */
IO_PACKAGE out_pkg;  /* output package */
IO_PACKAGE *output = &out_pkg; 
IO_PACKAGE *input = (IO_PACKAGE *)pbInBuff; /* input package */

/*
	Exit upon an error.
  
	Parameters:
		errcode[in]: error code
		msg[in]: additional error message
		msglen[in]: message length
  
	Return:
		none.

	Remarks:
		none.
*/
void error_exit(unsigned char errcode, unsigned char *msg, int msglen)

{				    
	output->tag = errcode;
	output->len = 0;
	
	/* for debug purpose only */
#ifdef  _DEBUG
	if (msglen != 0 && msg != NULL)
	{
		memcpy(output->buff, msg, msglen);
		output->len = msglen;
	}
#endif

	_set_response(2+output->len, (unsigned char *)output);
	_exit();
}

float cylinder_volume(float radius, float height)
{
	return Pi*radius*radius*height;
}

float cuboid_volume(float length, float width, float height)
{
	return length*width*height;
}

void main()
{

	int length = 0;
	int ret = 0;
	float result = 0;	

	switch (input->tag)
	{
		case CMD_CYD: // calculate cylinder's volume
		{	
			/* for convenience in handling user specific data block */
			CYLINDER *dblk = (CYLINDER *)input->buff; 
			float radius = dblk->radius;
			float height = dblk->height; 
			/* from PC's Little Endian to C-Compiler's settings */
			LE32_TO_CC(&radius); 
			LE32_TO_CC(&height);
			/* call sub-function */
			result = cylinder_volume(radius, height); 
		}
		break;
		
		case CMD_CBD: // calculate cuboid's volume
		{
			CUBOID *dblk = (CUBOID *)input->buff;
			float length = dblk->length;
			float width = dblk->width;
			float height = dblk->height;
			LE32_TO_CC(&length);
			LE32_TO_CC(&width);
			LE32_TO_CC(&height);
			result = cuboid_volume(length, width, height);
		}
		break;
		
		default:
			error_exit(ERR_INVALID_PARAMETER, NULL, 0);
		
	}	
	CC_TO_LE32(&result);	
	ret = _mem_copy(&output->buff, &result, sizeof(result));
	if (ret != SES_SUCCESS) /* Almost every SES execution must be checked */
	{
		last_ses_error = ret;
		error_exit(ret, &last_ses_error, 1);
	}
	length += sizeof(result); 
	output->tag = ERR_SUCCESS;
	output->len = length;
	
	_set_response(IO_PACKAGE_HEADER_SIZE+output->len, (unsigned char *)output);
	_exit();  
}
