Skip to content

Commit c202286

Browse files
committed
Issue 590 - Supoort both v1 and v2 of libgpiod.
1 parent 93e3ed5 commit c202286

File tree

6 files changed

+130
-16
lines changed

6 files changed

+130
-16
lines changed

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
- Include the direwolf icon in the Windows executable. Note: When building from source, environment variable RC must point to windres location.
1616

17+
- Added support for libgpiod version 2.
18+
1719
## Version 1.7 -- October 2023
1820

1921
### New Documentation:

src/audio.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,11 @@ struct audio_s {
331331

332332
int ptt_invert; /* Invert the output. */
333333
int ptt_invert2; /* Invert the secondary output. */
334-
gpio_num_t gpio_num; /* Handle from libgpiod. Valid only when ptt_method is PTT_METHOD_GPIOD. */
334+
#if USE_GPIOD
335+
#if LIBGPIOD_VERSION_MAJOR >= 2
336+
gpio_num_t gpio_num; /* Handle from libgpiod. Valid only when ptt_method is PTT_METHOD_GPIOD. */
337+
#endif
338+
#endif
335339

336340
#ifdef USE_HAMLIB
337341

src/direwolf.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ int main (int argc, char *argv[])
305305
text_color_init(t_opt);
306306
text_color_set(DW_COLOR_INFO);
307307
//dw_printf ("Dire Wolf version %d.%d (%s) BETA TEST 7\n", MAJOR_VERSION, MINOR_VERSION, __DATE__);
308-
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "D", __DATE__);
308+
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "E", __DATE__);
309309
//dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION);
310310

311311

@@ -321,7 +321,9 @@ int main (int argc, char *argv[])
321321
dw_printf (" cm108-ptt");
322322
#endif
323323
#if defined(USE_GPIOD)
324-
dw_printf (" libgpiod");
324+
#define STRINGIFY(x) STRINGIFY2(x)
325+
#define STRINGIFY2(x) #x
326+
dw_printf (" libgpiod-%s", STRINGIFY(LIBGPIOD_VERSION));
325327
#endif
326328
#if (USE_AVAHI_CLIENT|USE_MACOS_DNSSD)
327329
dw_printf (" dns-sd");

src/gpio_common.c

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,40 @@
1+
/*------------------------------------------------------------------
2+
*
3+
* Module: gpio_common.c
4+
*
5+
* Purpose: The libgpiod API changed drastically between v1 and v2, as first seen
6+
* in Debian 13 Trixie.
7+
* It is not possible to have the same application code work with both.
8+
* It is necessary to have two sets of code and conditional compilation.
9+
*
10+
* Environment: Preprocessor symbols set by build system:
11+
* USE_GPIOD to include the gpiod code
12+
* LIBGPIOD_VERSION e.g. 1.2.3
13+
* LIBGPIOD_VERSION_MAJOR e.g. 1
14+
* LIBGPIOD_VERSION_MINOR e.g. 2
15+
*
16+
* Description: Eventually we would like to put all of the version differences
17+
* in here to avoid cluttering ptt.c more than it is already.
18+
* Currently this is all version 2 code which has no hope of
19+
* building with version 1 library.
20+
*
21+
*---------------------------------------------------------------*/
22+
23+
#if USE_GPIOD // Skip all of this if no GPIOD libary present
24+
25+
#if LIBGPIOD_VERSION_MAJOR >= 2 // Someday we might have v1 and v2 sections
26+
27+
#include "direwolf.h"
28+
129
#include <gpiod.h>
230
#include <stdio.h>
331
#include <unistd.h>
432

533
#include <errno.h>
634
#include <string.h>
735

36+
#include "textcolor.h"
37+
838
#include "gpio_common.h"
939

1040
#define GPIO_MAX_LINES 32
@@ -25,7 +55,8 @@ static gpio_common_t gpio[GPIO_MAX_LINES];
2555
// Function implementations
2656

2757
void gpio_common_init(void) {
28-
fprintf(stderr, "Initializing GPIO common structure\n");
58+
text_color_set(DW_COLOR_DEBUG);
59+
dw_printf("Initializing GPIO common structure\n");
2960
for (gpio_num_t i = 0; i < GPIO_MAX_LINES; i++) {
3061
gpio[i].used = false;
3162
}
@@ -44,11 +75,13 @@ gpio_num_t gpio_common_open_line(const char *chip_name, unsigned int line, bool
4475
gpio_num = GPIO_COMMON_UNKNOWN;
4576

4677
if (chip_name == NULL) {
47-
fprintf(stderr, "No chip name supplied.\n");
78+
text_color_set(DW_COLOR_ERROR);
79+
dw_printf("No chip name supplied.\n");
4880
goto out;
4981
}
5082

51-
fprintf(stderr, "Opening GPIO line %d on chip %s\n", line, chip_name);
83+
text_color_set(DW_COLOR_DEBUG);
84+
dw_printf("Opening GPIO line %d on chip %s\n", line, chip_name);
5285

5386
// Get a free slot
5487
for (gpio_num_t i = 0; i < GPIO_MAX_LINES; i++) {
@@ -59,22 +92,25 @@ gpio_num_t gpio_common_open_line(const char *chip_name, unsigned int line, bool
5992
}
6093

6194
if (gpio_num == GPIO_COMMON_UNKNOWN) {
62-
fprintf(stderr, "Too many GPIOs open.\n");
95+
text_color_set(DW_COLOR_ERROR);
96+
dw_printf("Too many GPIOs open.\n");
6397
goto out;
6498
}
6599

66100
chip = gpiod_chip_open(chip_name);
67101

68102
if (chip == NULL) {
69-
fprintf(stderr, "Failed to open GPIO chip %s\n", chip_name);
103+
text_color_set(DW_COLOR_ERROR);
104+
dw_printf("Failed to open GPIO chip %s\n", chip_name);
70105
gpio_num = GPIO_COMMON_UNKNOWN;
71106
goto out;
72107
}
73108

74109
settings = gpiod_line_settings_new();
75110

76111
if (settings == NULL) {
77-
fprintf(stderr, "Unable to allocate memory for line settings \n");
112+
text_color_set(DW_COLOR_ERROR);
113+
dw_printf("Unable to allocate memory for line settings \n");
78114
gpio_num = GPIO_COMMON_UNKNOWN;
79115
goto close_chip;
80116
}
@@ -93,8 +129,9 @@ gpio_num_t gpio_common_open_line(const char *chip_name, unsigned int line, bool
93129

94130
ret = gpiod_line_config_add_line_settings(line_cfg, &line, 1,
95131
settings);
96-
if (ret < 0) {
97-
fprintf(stderr, "Failed to add line settings\n");
132+
if (ret < 0) {
133+
text_color_set(DW_COLOR_ERROR);
134+
dw_printf("Failed to add line settings\n");
98135
gpio_num = GPIO_COMMON_UNKNOWN;
99136
goto free_line_config;
100137
}
@@ -104,12 +141,13 @@ gpio_num_t gpio_common_open_line(const char *chip_name, unsigned int line, bool
104141
goto free_line_config;
105142
}
106143

107-
gpiod_request_config_set_consumer(req_cfg, "FLDIGI");
144+
gpiod_request_config_set_consumer(req_cfg, GPIO_CONSUMER);
108145

109146
gpio[gpio_num].request = gpiod_chip_request_lines(chip, req_cfg, line_cfg);
110147

111148
if (gpio[gpio_num].request == NULL) {
112-
fprintf(stderr, "Failed to request GPIO line %d\n", gpio_num);
149+
text_color_set(DW_COLOR_ERROR);
150+
dw_printf("Failed to request GPIO line %d\n", gpio_num);
113151
gpio_num = GPIO_COMMON_UNKNOWN;
114152
goto free_line_config;
115153
} else {
@@ -162,7 +200,8 @@ int gpio_common_set(gpio_num_t gpio_num, bool val) {
162200

163201
int ret = gpiod_line_request_set_value(gpio[gpio_num].request, gpio[gpio_num].offset, gpiod_val);
164202
if (ret < 0) {
165-
fprintf(stderr, "Error setting line\n");
203+
text_color_set(DW_COLOR_ERROR);
204+
dw_printf("Error setting line\n");
166205
return GPIO_COMMON_ERR;
167206
}
168207
return 0;
@@ -177,3 +216,9 @@ int gpio_common_close(void) {
177216

178217
return 0;
179218
}
219+
220+
#endif // LIBGPIOD_VERSION_MAJOR >= 2
221+
222+
#endif // USE_GPIOD
223+
224+
// end gpio_common.c

src/gpio_common.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#ifndef GPIO_COMMON_H
22
#define GPIO_COMMON_H
33

4+
#if USE_GPIOD // Skip all if no libgpiod available
5+
6+
#if LIBGPIOD_VERSION_MAJOR >= 2 // Someday we might have v1 and v2 sections
47

58
#ifdef __cplusplus
69
extern "C" {
@@ -29,4 +32,8 @@ int gpio_common_set(gpio_num_t gpio_num, bool val);
2932
}
3033
#endif
3134

35+
#endif // LIBGPIOD_VERSION_MAJOR >= 2
36+
37+
#endif // USE_GPIOD
38+
3239
#endif // GPIO_COMMON_H

src/ptt.c

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,11 @@
163163
#endif
164164

165165
#ifdef USE_GPIOD
166+
#if LIBGPIOD_VERSION_MAJOR >= 2
166167
#include "gpio_common.h"
168+
#else
169+
#include <gpiod.h>
170+
#endif
167171
#endif
168172

169173
/* So we can have more common code for fd. */
@@ -652,6 +656,42 @@ void export_gpio(int ch, int ot, int invert, int direction)
652656
get_access_to_gpio (gpio_value_path);
653657
}
654658

659+
#if defined(USE_GPIOD)
660+
661+
// TODO: Maybe move to gpio_common.c or rewrite.
662+
663+
#if LIBGPIOD_VERSION_MAJOR == 1
664+
665+
int gpiod_probe(const char *chip_dev_path, int line_number)
666+
{
667+
// chip_dev_path must be complete device path such as /dev/gpiochip3
668+
669+
struct gpiod_chip *chip;
670+
chip = gpiod_chip_open(chip_dev_path);
671+
if (chip == NULL) {
672+
text_color_set(DW_COLOR_ERROR);
673+
dw_printf ("Can't open GPIOD chip %s.\n", chip_dev_path);
674+
return -1;
675+
}
676+
677+
struct gpiod_line *line;
678+
line = gpiod_chip_get_line(chip, line_number);
679+
if (line == NULL) {
680+
text_color_set(DW_COLOR_ERROR);
681+
dw_printf ("Can't get GPIOD line %d.\n", line_number);
682+
return -1;
683+
}
684+
if (ptt_debug_level >= 2) {
685+
text_color_set(DW_COLOR_DEBUG);
686+
dw_printf("GPIOD probe OK. Chip: %s line: %d\n", chip_dev_path, line_number);
687+
}
688+
return 0;
689+
}
690+
691+
#endif // LIBGPIOD_VERSION_MAJOR == 1
692+
693+
#endif /* USE_GPIOD */
694+
655695
#endif /* not __WIN32__ */
656696

657697

@@ -725,8 +765,10 @@ void ptt_init (struct audio_s *audio_config_p)
725765
#endif
726766

727767
#if USE_GPIOD
768+
#if LIBGPIOD_VERSION_MAJOR >= 2
728769
gpio_common_init();
729770
#endif
771+
#endif
730772

731773
#if DEBUG
732774
text_color_set(DW_COLOR_DEBUG);
@@ -912,9 +954,15 @@ void ptt_init (struct audio_s *audio_config_p)
912954
if (audio_config_p->achan[ch].octrl[ot].ptt_method == PTT_METHOD_GPIOD) {
913955
const char *chip_name = audio_config_p->achan[ch].octrl[ot].out_gpio_name;
914956
int line_number = audio_config_p->achan[ch].octrl[ot].out_gpio_num;
915-
audio_config_p->achan[ch].octrl[ot].gpio_num = gpio_common_open_line(chip_name, line_number, false);
957+
958+
#if LIBGPIOD_VERSION_MAJOR >= 2
959+
audio_config_p->achan[ch].octrl[ot].gpio_num = gpio_common_open_line(chip_name, line_number, false);
916960
if (audio_config_p->achan[ch].octrl[ot].gpio_num == GPIO_COMMON_UNKNOWN) {
917-
text_color_set(DW_COLOR_ERROR);
961+
#else
962+
int rc = gpiod_probe(chip_name, line_number);
963+
if (rc < 0) {
964+
#endif
965+
text_color_set(DW_COLOR_ERROR);
918966
//No, people won't notice the error message and be confused. Just terminate.
919967
//dw_printf ("Disable PTT for channel %d\n", ch);
920968
//audio_config_p->achan[ch].octrl[ot].ptt_method = PTT_METHOD_NONE;
@@ -1371,7 +1419,13 @@ void ptt_set (int ot, int chan, int ptt_signal)
13711419
if (save_audio_config_p->achan[chan].octrl[ot].ptt_method == PTT_METHOD_GPIOD) {
13721420
const char *chip = save_audio_config_p->achan[chan].octrl[ot].out_gpio_name;
13731421
int line = save_audio_config_p->achan[chan].octrl[ot].out_gpio_num;
1422+
1423+
1424+
#if LIBGPIOD_VERSION_MAJOR >= 2
13741425
int rc = gpio_common_set(save_audio_config_p->achan[chan].octrl[ot].gpio_num, ptt);
1426+
#else
1427+
int rc = gpiod_ctxless_set_value(chip, line, ptt, false, "direwolf", NULL, NULL);
1428+
#endif
13751429
if (ptt_debug_level >= 1) {
13761430
text_color_set(DW_COLOR_DEBUG);
13771431
dw_printf("PTT_METHOD_GPIOD chip: %s line: %d ptt: %d rc: %d\n", chip, line, ptt, rc);

0 commit comments

Comments
 (0)