3

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.

Petross404
  • 177
  • 1
  • 12
  • Do the shell tools from `libgpiod` work? Like `gpioget gpiochip0 0`. – 0andriy Aug 29 '20 at 21:28
  • Running ` # gpioset --mode=time --sec=5 gpiochip0 1=1 gpioset: error setting the GPIO line values: No such device ` I can't get it to work. EDIT What is happening with code tags? – Petross404 Sep 05 '20 at 19:12
  • Wha about *getting* a value as I mentioned in the comment? – 0andriy Sep 06 '20 at 18:36
  • Running `gpioget gpiochip0 0` is giving an error: `gpioget: error reading GPIO values: No such device` EDIT: I don't have any device to plug in order to read data. – Petross404 Sep 18 '20 at 13:42
  • So, what is the question then? Make sure you have */dev/gpiochip0` (or other number) is present in your system first. – 0andriy Sep 18 '20 at 14:15
  • I don't know which part isn't obvious since the question is perfectly clear. It is explained not only that the device exists in the system but other libraries _do_ access the gpio lines, it's just `gpiod` that I have trouble with. – Petross404 Sep 19 '20 at 11:35
  • It was my reaction to your *EDIT* addition. Without device you may not read values from it. Have you had the latest libgpiod and kernel? – 0andriy Sep 20 '20 at 17:54
  • What I was reffering as device was a sensor for example. I do have a device to write output and it's a led, that's why I don't bother asking about reading input. I am using kernel 5.4.49 and `dev-libs/libgpiod-1.4.1`. I suspect it's not a HW issue since libftdi and CircuitPython can give access to gpio lines for output. – Petross404 Sep 20 '20 at 19:30
  • I see. Have you tired (for sake of the possible supporting your theory) to run with latest (v5.9-rc6 and libgpiog v1.5.2)? – 0andriy Sep 21 '20 at 07:58
  • Neither of these exist in portage, so no I haven't actually. – Petross404 Sep 21 '20 at 08:17
  • Hi, iv'e tested your code on raspberry pi 3 b+ running fedora 33 and it works perfectly. libgpiod 1.6.2, kernel 5.9.16-200.fc33.aarch64; you might need an updated libgpiod version. – Sombriks Dec 30 '20 at 00:13
  • @Sombriks Thank you for the update. I am afraid using GPIO ports on raspi is easier all-together though. I will test again to see if I missed something. – Petross404 Dec 30 '20 at 10:04

1 Answers1

1

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
ubiyubix
  • 1,036
  • 9
  • 13