test.c/src/gpio.c
2019-07-14 09:18:42 +02:00

160 lines
3.5 KiB
C

#include <stdlib.h>
#include <syslog.h>
#include <stdbool.h>
#include <ftdi.h>
#include <gpio.h>
struct ftdi_obj {
struct ftdi_context *ftdi;
bool is_open;
unsigned int vendor_id;
unsigned int product_id;
unsigned char bit_mask;
};
static struct ftdi_obj ftdi_obj = {
.ftdi = NULL,
.is_open = false,
.vendor_id = 0x0403,
.product_id = 0x6001,
.bit_mask = 0,
};
static int ftdi_open(void)
{
int res;
if((ftdi_obj.ftdi = ftdi_new()) == 0) {
syslog(LOG_ERR, "ftdi_new failed\n");
return EXIT_FAILURE;
}
res = ftdi_usb_open(ftdi_obj.ftdi, ftdi_obj.vendor_id, ftdi_obj.product_id);
if (res < 0 && res != -5) {
syslog(LOG_ERR, "unable to open ftdi device: %d (%s)\n", res,
ftdi_get_error_string(ftdi_obj.ftdi));
ftdi_free(ftdi_obj.ftdi);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int gpio_open(const struct gpio *gpio)
{
int res;
unsigned char init_value = 0;
bool init_write = false;
if(NULL == gpio) {
syslog(LOG_ERR, "No valid gpio object given.\n");
return EXIT_FAILURE;
}
if(!ftdi_obj.is_open) {
res = ftdi_open();
if(res != EXIT_SUCCESS) {
return EXIT_FAILURE;
}
init_write = true;
}
ftdi_obj.bit_mask |= (unsigned char)gpio->pin;
res = ftdi_set_bitmode(ftdi_obj.ftdi, ftdi_obj.bit_mask, BITMODE_BITBANG);
if(res < 0) {
syslog(LOG_ERR, "unable to set bit bang mode: %d (%s)\n", res,
ftdi_get_error_string(ftdi_obj.ftdi));
ftdi_free(ftdi_obj.ftdi);
return EXIT_FAILURE;
}
ftdi_obj.is_open = true;
if(init_write) {
ftdi_write_data(ftdi_obj.ftdi, &init_value, 1);
}
return EXIT_SUCCESS;
}
int gpio_close(const struct gpio *gpio)
{
if(NULL == gpio) {
return EXIT_FAILURE;
}
unsigned char pin = (unsigned char)gpio->pin;
ftdi_obj.bit_mask &= ~pin;
if(ftdi_obj.bit_mask == 0) {
ftdi_usb_close(ftdi_obj.ftdi);
ftdi_free(ftdi_obj.ftdi);
}
return EXIT_SUCCESS;
}
int gpio_read(const struct gpio *gpio, unsigned int *value)
{
int res;
unsigned char buf;
if(NULL == gpio || NULL == value) {
return EXIT_FAILURE;
}
res = ftdi_read_data(ftdi_obj.ftdi, &buf, 1);
if(res < 0) {
syslog(LOG_ERR, "unable to readfrom ftdi device: %d (%s)\n", res,
ftdi_get_error_string(ftdi_obj.ftdi));
return EXIT_FAILURE;
}
if(buf & (unsigned char)(gpio->pin)) {
*value = 1;
} else {
*value = 0;
}
return EXIT_SUCCESS;
}
int gpio_write(const struct gpio *gpio, unsigned int value)
{
int res;
unsigned int current_state;
unsigned char buf;
if(NULL == gpio) {
return EXIT_FAILURE;
}
res = gpio_read(gpio, &current_state);
if(res != EXIT_SUCCESS) {
syslog(LOG_ERR, "write failed for 0x%x, error %d (%s)\n", value, res,
ftdi_get_error_string(ftdi_obj.ftdi));
return EXIT_FAILURE;
}
buf = (unsigned char)current_state;
if(value == 0) {
buf &= ~(unsigned char)(gpio->pin);
}
else {
buf |= (unsigned char)(gpio->pin);
}
res = ftdi_write_data(ftdi_obj.ftdi, &buf, 1);
if(res < 0) {
syslog(LOG_ERR, "write failed for 0x%x, error %d (%s)\n", value, res,
ftdi_get_error_string(ftdi_obj.ftdi));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
void gpio_toggle(const struct gpio *gpio)
{
}