/*
 * driver.c
 *
 *  Created on: Jul 27, 2016
 *      Author: tkl
 */

#include <stddef.h>

#include "driver.h"
#include "adc.h"
#include "gpio.h"
#include "i2c.h"
#include "pwm.h"
#include "rng.h"
#include "spi.h"
#include "uart.h"

int drv_open(const struct driver *driver)
{
	int ret = -1;
	if(NULL == driver)
		return ret;
	switch(driver->driver_type) {
	case DRIVER_TYPE_ADC:
		ret = adc_open((const struct adc *)(driver->device_driver));
		break;
	case DRIVER_TYPE_GPIO:
		ret = gpio_open((const struct gpio *)(driver->device_driver));
		break;
	case DRIVER_TYPE_I2C:
		ret = i2c_open((struct i2c *)(driver->device_driver));
		break;
	case DRIVER_TYPE_PWM:
		ret = pwm_open((const struct pwm *)(driver->device_driver));
		break;
	case DRIVER_TYPE_RNG:
		ret = rng_open((const struct rng *)(driver->device_driver));
		break;
	case DRIVER_TYPE_RTC:
		break;
	case DRIVER_TYPE_SPI:
		ret = spi_open((const struct spi *)(driver->device_driver));
		break;
	case DRIVER_TYPE_UART:
		ret = uart_open((const struct uart *)(driver->device_driver));
		break;
	}
	return ret;
}

int drv_close(const struct driver *driver)
{
	int ret = -1;
	if(NULL == driver)
		return ret;
	switch(driver->driver_type) {
	case DRIVER_TYPE_ADC:
		ret = adc_close((const struct adc *)(driver->device_driver));
		break;
	case DRIVER_TYPE_GPIO:
		ret = gpio_close((const struct gpio *)(driver->device_driver));
		break;
	case DRIVER_TYPE_I2C:
		ret = i2c_close((struct i2c *)(driver->device_driver));
		break;
	case DRIVER_TYPE_PWM:
		ret = pwm_close((const struct pwm *)(driver->device_driver));
		break;
	case DRIVER_TYPE_RNG:
		ret = rng_close((const struct rng *)(driver->device_driver));
		break;
	case DRIVER_TYPE_RTC:
		break;
	case DRIVER_TYPE_SPI:
		ret = spi_close((const struct spi *)(driver->device_driver));
		break;
	case DRIVER_TYPE_UART:
		ret = uart_close((const struct uart *)(driver->device_driver));
		break;
	}
	return ret;
}

int drv_read(const struct driver *driver, char *buffer, int len)
{
	int ret = -1;
	if(NULL == driver)
		return ret;
	switch(driver->driver_type) {
	case DRIVER_TYPE_ADC:
		break;
	case DRIVER_TYPE_GPIO:
		ret = gpio_read((const struct gpio *)(driver->device_driver));
		if(len > 0) {
			buffer[0] = ret + 0x30;
			ret = 1;
		}
		break;
	case DRIVER_TYPE_I2C:
		break;
	case DRIVER_TYPE_PWM:
		break;
	case DRIVER_TYPE_RNG:
		ret = rng_read((const struct rng *)(driver->device_driver));
		break;
	case DRIVER_TYPE_RTC:
		break;
	case DRIVER_TYPE_SPI:
		break;
	case DRIVER_TYPE_UART:
		ret = uart_read((const struct uart *)(driver->device_driver), buffer, len);
		break;
	}
	return ret;
}

int drv_write(const struct driver *driver, const char *buffer, int len)
{
	int ret = -1;
	if(NULL == driver)
		return ret;
	switch(driver->driver_type) {
	case DRIVER_TYPE_ADC:
		break;
	case DRIVER_TYPE_GPIO:
		if(len > 0) {
			char send = 0;
			if((buffer[0] - 0x30) > 0)
				send = 1;
			gpio_write((const struct gpio *)(driver->device_driver), send);
			ret = 1;
		}
		break;
	case DRIVER_TYPE_I2C:
		break;
	case DRIVER_TYPE_PWM:
		break;
	case DRIVER_TYPE_RNG:
		break;
	case DRIVER_TYPE_RTC:
		break;
	case DRIVER_TYPE_SPI:
		break;
	case DRIVER_TYPE_UART:
		ret = uart_write((const struct uart *)(driver->device_driver), buffer, len);
		break;
	}
	return ret;
}

int drv_ioctl(const struct driver *driver, unsigned int cmd, const void *data)
{
	int ret = -1;
	if(NULL == driver)
		return ret;
	switch(driver->driver_type) {
	case DRIVER_TYPE_ADC:
		break;
	case DRIVER_TYPE_GPIO:
		break;
	case DRIVER_TYPE_I2C:
		break;
	case DRIVER_TYPE_PWM:
		if(cmd == IOCTL_PWM_SET_DUTY_CYCLE) {
			unsigned int *duty = (unsigned int *)data;
			return pwm_set_duty_cycle((const struct pwm *)(driver->device_driver), *duty);
		}
		else if(cmd == IOCTL_PWM_GET_PERIOD_NS) {
			return pwm_get_period_ns((const struct pwm *)(driver->device_driver));
		}
		else if(cmd == IOCTL_PWM_GET_PULSE_WIDTH_NS) {
			return pwm_get_pulse_width_ns((const struct pwm *)(driver->device_driver));
		}
		break;
	case DRIVER_TYPE_RNG:
		break;
	case DRIVER_TYPE_RTC:
		break;
	case DRIVER_TYPE_SPI:
		break;
	case DRIVER_TYPE_UART:
		break;
	}
	return ret;
}
