#include #include #include #include #include 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, ¤t_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) { }