cgpioadafruitlibgpiod

Can't access gpio line with gpiod_line_request_output() on Adafruit FT232H


I am using an Adafruit Ft232H breakout to add GPIO ports to my Linux pc. Although I had some success to flash a led with libftdi and bitbang mode, I don't have the same luck with libgpiod because gpiod_line_request_output is failing.

Some gpio information of my system:

sudo gpiodetect
gpiochip0 [ftdi-cbus] (4 lines)

sudo gpioinfo
gpiochip0 - 4 lines:
        line   0:      unnamed       unused   input  active-high 
        line   1:      unnamed       unused   input  active-high 
        line   2:      unnamed       unused   input  active-high 
        line   3:      unnamed       unused   input  active-high

This is the C program which tries to access the line 0.

#include <stdio.h>
#include <stdlib.h>

#include <gpiod.h>

#define LINE_NUM 0

void gpio_fatal(struct gpiod_chip* chip, const char msg[20]);

int main(int argc, char** argv)
{
    struct gpiod_chip*  chip;
    struct gpiod_line*  line;
    const char path[] = "/dev/gpiochip0";

    chip = gpiod_chip_open(path);
    if(!chip)
    {
        fprintf(stderr, "Error opening path\n");
        return EXIT_FAILURE;
    }

    line = gpiod_chip_get_line(chip, LINE_NUM);
    if(!line)
    {
        fprintf(stderr, "error getting this line\n");
        return EXIT_FAILURE;
    }

    int ret = gpiod_line_request_output(line,
                        "ftdi-cbus",
                        1);
    if(ret != 0)
        gpio_fatal(chip, "Request output failed");

    for(;;)
    {
        gpiod_line_set_value(line, 1);
        printf("On\n");
        sleep(1);
        gpiod_line_set_value(line, 0);
        printf("Off\n");
        sleep(1);
    }

    gpiod_line_release(line);
    gpiod_chip_close(chip);

    return EXIT_SUCCESS;
}

void gpio_fatal(struct gpiod_chip* chip, const char* msg)
{
    fprintf(stderr, "%s\n", msg);
    gpiod_chip_close(chip);
    exit(EXIT_FAILURE);
}

Running the executable with sudo gives me:

sudo g_gpiod/build/g_gpiod 
Password: 
Request output failed

gpiod.h states for the failing function the following:

/**
 * @brief Reserve a single line, set the direction to output.
 * @param line GPIO line object.
 * @param consumer Name of the consumer.
 * @param default_val Initial line value.
 * @return 0 if the line was properly reserved, -1 on failure.
 */
int gpiod_line_request_output(struct gpiod_line *line,
                  const char *consumer, int default_val) GPIOD_API;

The parameters seem to be correct, for what reason could this be failing? Other examples using libftdi or CircuitPython can access the ports and work correctly.


Solution

  • You need to flash the EEPROM to set the function of pin C5, e.g. using the ftdi_eeprom command from libftdi. First, unload the ftdi_sio module and save the original EEPROM:

    $ sudo rmmod ftdi_sio
    $ sudo ftdi_eeprom --verbose --device i:0x0403:0x6014 ft232h-orig.conf
    
    FTDI eeprom generator v0.17
    (c) Intra2net AG and the libftdi developers <opensource@intra2net.com>
    FTDI read eeprom: 0
    EEPROM size: 256
    VID:     0x0403
    PID:     0x6014
    Release: 0x0900
    Bus Powered: 100 mA
    Manufacturer: ÿÿÿÿÿÿÿÿ
    Product:      ÿÿÿÿÿÿ
    Serial:       ÿÿÿÿÿÿÿÿ
    Checksum      : ffff
    PNP: 1
    Channel A has Mode UART
    FT1284 Mode Clock is idle LOW, MSB first, No Flow Control
    ACBUS has 4 mA drive
    ADBUS has 4 mA drive
    C0 Function: TRISTATE
    C1 Function: TRISTATE
    C2 Function: TRISTATE
    C3 Function: TRISTATE
    C4 Function: TRISTATE
    C5 Function: TRISTATE
    C6 Function: TRISTATE
    C7 Function: TRISTATE
    C8 Function: DRIVE_1
    C9 Function: DRIVE_0
    FTDI close: 0
    

    The file ft232h-orig.conf contains just a single line filename="ft232h-orig.bin".

    You can control 4 GPIO pins of the FT232H using the ftdi_sio module:

    | line | pin | remarks   |
    ==========================
    | 0    | C5  | -         |
    | 1    | C6  | -         | 
    | 2    | C8  | red led   |
    | 3    | C9  | green led |
    

    The Adafruit board has the cathodes of two LEDs (red and green) connected to pins C8 and C9. The default EEPROM has C9 set to DRIVE_0 so that the green LED is "on" when the board is powered up.

    Here is my config file for ftdi_eeprom:

    $ cat ft232h-libgpiod.conf
    vendor_id="0x0403"
    product_id="0x6014"
    manufacturer="Adafruit"
    product="FT232H Breakout"
    
    # whatever
    serial="20211223"
    use_serial=true
    
    max_power=100
    self_powered=false
    remote_wakeup=false
    
    cha_type=UART
    cha_vcp=false
    
    cbush5=IOMODE
    cbush6=IOMODE
    
    # red led
    cbush8=IOMODE
    
    # green led
    cbush9=DRIVE_0 # power-on indicator
    #cbush9=IOMODE
    
    $ sudo ftdi_eeprom --verbose --device i:0x0403:0x6014 --flash-eeprom ft232h-libgpiod.conf
    

    Your program now works fine with line 0 on pin C5. As a bonus, you can now control the red LED with the libgpiod commands:

    # turn red LED on (low active)
    sudo gpioset gpiochip0 2=0