#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
-#include <ctype.h>
#include "options.h"
/**
/**
* Unexport a GPIO pin and close its' file descriptors
+ * @param pin The GPIO number to be unexported
*/
void GPIO_Unexport(int pin)
{
}
GPIO_Pin *gpio = &g_gpio[g_pin_gpio_to_index[pin]];
+ if (!gpio->initialised)
+ {
+ AbortBool("GPIO %d is not initialised.", pin);
+ }
if (pwrite(gpio->fd_direction, "in", 2, 0) != 2)
- AbortBool("Couldn't set GPIO %d direction - %s", pin, strerror(errno));
+ {
+ AbortBool("Couldn't set GPIO %d direction - %s", pin, strerror(errno));
+ }
char c = '0';
if (pread(gpio->fd_value, &c, 1, 0) != 1)
+ {
AbortBool("Couldn't read GPIO %d value - %s", pin, strerror(errno));
+ }
*result = (c == '1');
return true;
// Have to stop PWM before changing it
if (pwrite(pwm->fd_run, "0", 1, 0) != 1)
{
- AbortBool("Couldn't stop PWM%d - %s", pin, strerror(errno));
+ AbortBool("Couldn't stop PWM %d - %s", pin, strerror(errno));
}
char c = polarity ? '1' : '0';
if (pwrite(pwm->fd_polarity, &c, 1, 0) != 1)
{
- AbortBool("Couldn't set PWM%d polarity - %s", pin, strerror(errno));
+ AbortBool("Couldn't set PWM %d polarity - %s", pin, strerror(errno));
}
//This must be done first, otherwise period/duty settings can conflict
if (fwrite("0", 1, 1, pwm->file_duty) < 1)
{
- AbortBool("Couldn't zero the duty for PWM%d - %s", pin, strerror(errno));
+ AbortBool("Couldn't zero the duty for PWM %d - %s", pin, strerror(errno));
}
if (fprintf(pwm->file_period, "%lu", period) < 0)
{
- AbortBool("Couldn't set period for PWM%d - %s", pin, strerror(errno));
+ AbortBool("Couldn't set period for PWM %d - %s", pin, strerror(errno));
}
if (fprintf(pwm->file_duty, "%lu", duty) < 0)
{
- AbortBool("Couldn't set duty cycle for PWM%d - %s", pin, strerror(errno));
+ AbortBool("Couldn't set duty cycle for PWM %d - %s", pin, strerror(errno));
}
if (pwrite(pwm->fd_run, "1", 1, 0) != 1)
{
- AbortBool("Couldn't start PWM%d - %s", pin, strerror(errno));
+ AbortBool("Couldn't start PWM %d - %s", pin, strerror(errno));
}
return true;
/**
* Deactivate a PWM pin
* @param pin - The syfs pin number
+ * @return true on success, false otherwise
*/
-void PWM_Stop(int pin)
+bool PWM_Stop(int pin)
{
if (pin < 0 || pin >= PWM_NUM_PINS)
{
- Abort("Invalid PWM pin number %d specified.", pin);
+ AbortBool("Invalid PWM pin number %d specified.", pin);
+ }
+ else if (!g_pwm[pin].initialised)
+ {
+ AbortBool("PWM %d is not initialised.", pin);
}
if (pwrite(g_pwm[pin].fd_run, "0", 1, 0) != 1)
{
- Abort("Couldn't stop PWM %d - %s", pin, strerror(errno));
+ AbortBool("Couldn't stop PWM %d - %s", pin, strerror(errno));
}
+
+ return true;
}
/**
{
AbortBool("ADC %d read failed: %s", id, strerror(errno));
}
+
*value = strtol(adc_str, NULL, 10);
return true;
}
\ No newline at end of file
*/
void Pin_Init()
{
- //Don't export anything; make the user do it.
- /*for (int i = 0; i < GPIO_NUM_PINS; ++i)
- GPIO_Export(g_index_to_gpio[i]);
-
- for (int i = 0; i < ADC_NUM_PINS; ++i)
- ADC_Export(i);
-
- //Only export 'safe' PWM pins that don't interfere with one another
- for (int i = 0; i < PWM_NUM_SAFE_PINS; ++i)
- PWM_Export(g_pin_safe_pwm[i]);*/
+
}
/**
PWM_Unexport(g_pin_safe_pwm[i]);
}
+bool Pin_Configure(const char *type, int pin_export, int num)
+{
+ bool ret = true;
+
+ if (strcmp(type, "gpo") == 0 || strcmp(type, "gpi") == 0)
+ {
+ if (pin_export < 0)
+ GPIO_Unexport(num);
+ else
+ ret = GPIO_Export(num);
+ }
+ else if (strcmp(type, "pwm") == 0)
+ {
+ if (pin_export < 0)
+ PWM_Unexport(num);
+ else
+ ret = PWM_Export(num);
+ }
+ else if (strcmp(type, "adc") == 0)
+ {
+ if (pin_export < 0)
+ ADC_Unexport(num);
+ else
+ ret = ADC_Export(num);
+ }
+ return ret;
+}
+
/**
* Handle a request to the Pin test module
* @param context - The FastCGI context
void Pin_Handler(FCGIContext *context, char * params)
{
- char * type = NULL;
+ const char * type = NULL;
int num = 0;
- bool set = true;
+ int pin_export = 0;
+ bool set = false;
bool pol = false;
double freq = 50;
double duty = 0.5;
FCGIValue values[] = {
{"type", &type, FCGI_REQUIRED(FCGI_STRING_T)},
{"num", &num, FCGI_REQUIRED(FCGI_INT_T)},
+ {"export", &pin_export, FCGI_INT_T},
{"set", &set, FCGI_BOOL_T},
{"pol", &pol, FCGI_BOOL_T},
{"freq", &freq, FCGI_DOUBLE_T},
typedef enum {
TYPE,
NUM,
+ EXPORT,
SET,
POL,
FREQ,
return;
}
- Log(LOGDEBUG, "Params: type = %s, num = %d, set = %d, pol = %d, freq = %f, duty = %f", type, num, set, pol, freq, duty);
+ Log(LOGDEBUG, "Params: type = %s, num = %d, export = %d, set = %d, pol = %d, freq = %f, duty = %f", type, num, pin_export, set, pol, freq, duty);
+ if (pin_export != 0)
+ {
+ if (!Pin_Configure(type, pin_export, num))
+ {
+ FCGI_RejectJSON(context, "Failed to (un)export the pin. Check that a valid number has been specified.");
+ return;
+ }
+ FCGI_BeginJSON(context, STATUS_OK);
+ FCGI_JSONPair("description", "Pin (un)export OK!");
+ FCGI_EndJSON();
+ return;
+ }
if (strcmp(type, "gpo") == 0)
{
}
Log(LOGDEBUG, "Setting GPIO%d to %d", num, set);
- GPIO_Set(num, set);
-
- FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
- FCGI_PrintRaw("GPIO%d set to %d\n", num, set);
+ if (!GPIO_Set(num, set))
+ {
+ FCGI_RejectJSON(context, "Failed to set the GPIO pin. Check that it's exported.");
+ }
+ else
+ {
+ FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
+ FCGI_PrintRaw("GPIO%d set to %d\n", num, set);
+ }
}
else if (strcmp(type, "gpi") == 0)
{
return;
}
Log(LOGDEBUG, "Reading GPIO%d", num);
- FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
- bool ret;
- if (!GPIO_Read(num, &ret))
- FCGI_PrintRaw("GPIO%d read failed. Is it exported?", num);
+ bool val;
+ if (!GPIO_Read(num, &val))
+ {
+ FCGI_RejectJSON(context, "Failed to read from the GPIO pin. Check that it's exported.");
+ }
else
- FCGI_PrintRaw("GPIO%d reads %d\n", num, ret);
-
+ {
+ FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
+ FCGI_PrintRaw("GPIO%d reads %d\n", num, val);
+ }
}
else if (strcmp(type, "adc") == 0)
{
return;
}
Log(LOGDEBUG, "Reading ADC%d", num, set);
- FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
int raw_adc;
if (!ADC_Read(num, &raw_adc))
{
- FCGI_PrintRaw("ADC%d read failed. Is it initialised?", num);
+ FCGI_RejectJSON(context, "ADC read failed. Check that it's exported.");
}
else
{
+ FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
FCGI_PrintRaw("ADC%d reads %d\n", num, raw_adc);
}
}
FCGI_RejectJSON(context, "Invalid PWM pin");
return;
}
-
- FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
if (set)
{
duty = duty < 0 ? 0 : duty > 1 ? 1 : duty;
long period_ns = (long)(1e9 / freq);
long duty_ns = (long)(duty * period_ns);
- PWM_Set(g_pin_safe_pwm[num], pol, period_ns, duty_ns);
- FCGI_PrintRaw("PWM%d set to period_ns = %lu (%f Hz), duty_ns = %lu (%f), polarity = %d",
- num, period_ns, freq, duty_ns, duty*100, (int)pol);
+ if (!PWM_Set(num, pol, period_ns, duty_ns))
+ {
+ FCGI_RejectJSON(context, "PWM set failed. Check if it's exported, and that there's no channel conflict.");
+ }
+ else
+ {
+ FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
+ FCGI_PrintRaw("PWM%d set to period_ns = %lu (%f Hz), duty_ns = %lu (%f), polarity = %d",
+ num, period_ns, freq, duty_ns, duty*100, (int)pol);
+ }
}
else
{
Log(LOGDEBUG, "Stopping PWM%d",num);
PWM_Stop(g_pin_safe_pwm[num]);
+ FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
FCGI_PrintRaw("PWM%d stopped",num);
}
}