Skip to content

Commit df832c0

Browse files
authored
Merge pull request #38 from superna9999/local-gpio
Add local gpio control
2 parents fbdc677 + 87fbc38 commit df832c0

File tree

14 files changed

+558
-23
lines changed

14 files changed

+558
-23
lines changed

README

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,26 @@ devices:
6161
fastboot: 91671140
6262
fastboot_set_active: true
6363
fastboot_key_timeout: 2
64+
65+
- board: testboard
66+
console: /dev/serial/by-id/usb-1234-if00-port0
67+
name: GPIO controller board
68+
local_gpio:
69+
- power:
70+
chip: gpiochip0
71+
line: 7
72+
active_low: true
73+
- fastboot_key:
74+
chip: gpiochip0
75+
line: 8
76+
active_low: true
77+
- power_key:
78+
chip: gpiochip0
79+
line: 14
80+
active_low: true
81+
- usb_disconnect:
82+
chip: gpiochip1
83+
line: 4
84+
fastboot: cacafada
85+
fastboot_set_active: true
86+
fastboot_key_timeout: 2

ci/archlinux.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pacman -Syu --noconfirm \
2020
libftdi-compat \
2121
libyaml \
2222
systemd-libs \
23+
libgpiod \
2324
pkgconf \
2425
meson \
2526
$PKGS_CC

ci/debian.cross-compile.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ apt install -y --no-install-recommends \
2222
libftdi-dev:${ARCH} \
2323
libudev-dev:${ARCH} \
2424
libyaml-dev:${ARCH} \
25+
libgpiod-dev:${ARCH} \
2526
gcc-`dpkg-architecture -a ${ARCH} -q DEB_TARGET_GNU_TYPE`
2627

2728
echo "Install finished: $0"

ci/debian.i386.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ apt install -y --no-install-recommends \
2323
libftdi-dev:i386 \
2424
libudev-dev:i386 \
2525
libyaml-dev:i386 \
26+
libgpiod-dev:i386 \
2627
$PKGS_CC
2728

2829
echo "Install finished: $0"

ci/debian.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ apt install -y --no-install-recommends \
3232
libftdi-dev \
3333
libudev-dev \
3434
libyaml-dev \
35+
libgpiod-dev \
3536
meson \
3637
$PKGS_CC
3738

ci/fedora.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ dnf -y install \
2020
libftdi-devel \
2121
libudev-devel \
2222
libyaml-devel \
23+
libgpiod-devel \
2324
meson \
2425
$PKGS_CC
2526

device.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ struct cdb_assist;
88
struct fastboot;
99
struct fastboot_ops;
1010
struct device;
11+
struct device_parser;
1112

1213
struct control_ops {
14+
void *(*parse_options)(struct device_parser *dp);
1315
void *(*open)(struct device *dev);
1416
void (*close)(struct device *dev);
1517
int (*power)(struct device *dev, bool on);
@@ -28,6 +30,7 @@ struct console_ops {
2830
struct device {
2931
char *board;
3032
char *control_dev;
33+
void *control_options;
3134
char *console_dev;
3235
char *name;
3336
char *serial;
@@ -90,6 +93,7 @@ extern const struct control_ops alpaca_ops;
9093
extern const struct control_ops cdb_assist_ops;
9194
extern const struct control_ops conmux_ops;
9295
extern const struct control_ops ftdi_gpio_ops;
96+
extern const struct control_ops local_gpio_ops;
9397
extern const struct control_ops external_ops;
9498
extern const struct control_ops qcomlt_dbg_ops;
9599

device_parser.c

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <yaml.h>
3434

3535
#include "device.h"
36+
#include "device_parser.h"
3637

3738
#define TOKEN_LENGTH 16384
3839

@@ -49,12 +50,13 @@ static void nextsym(struct device_parser *dp)
4950
}
5051
}
5152

52-
static int accept(struct device_parser *dp, int type, char *scalar)
53+
int device_parser_accept(struct device_parser *dp, int type,
54+
char *scalar, size_t scalar_len)
5355
{
5456
if (dp->event.type == type) {
55-
if (scalar) {
56-
strncpy(scalar, (char *)dp->event.data.scalar.value, TOKEN_LENGTH - 1);
57-
scalar[TOKEN_LENGTH - 1] = '\0';
57+
if (scalar && scalar_len > 0) {
58+
strncpy(scalar, (char *)dp->event.data.scalar.value, scalar_len - 1);
59+
scalar[scalar_len - 1] = '\0';
5860
}
5961

6062
yaml_event_delete(&dp->event);
@@ -65,9 +67,10 @@ static int accept(struct device_parser *dp, int type, char *scalar)
6567
}
6668
}
6769

68-
static bool expect(struct device_parser *dp, int type, char *scalar)
70+
bool device_parser_expect(struct device_parser *dp, int type,
71+
char *scalar, size_t scalar_len)
6972
{
70-
if (accept(dp, type, scalar)) {
73+
if (device_parser_accept(dp, type, scalar, scalar_len)) {
7174
return true;
7275
}
7376

@@ -103,30 +106,37 @@ static void parse_board(struct device_parser *dp)
103106

104107
dev = calloc(1, sizeof(*dev));
105108

106-
while (accept(dp, YAML_SCALAR_EVENT, key)) {
109+
while (device_parser_accept(dp, YAML_SCALAR_EVENT, key, TOKEN_LENGTH)) {
107110
if (!strcmp(key, "users")) {
108111
dev->users = calloc(1, sizeof(*dev->users));
109112
list_init(dev->users);
110113

111-
if (accept(dp, YAML_SCALAR_EVENT, value))
114+
if (device_parser_accept(dp, YAML_SCALAR_EVENT, value, 0))
112115
continue;
113116

114-
expect(dp, YAML_SEQUENCE_START_EVENT, NULL);
117+
device_parser_expect(dp, YAML_SEQUENCE_START_EVENT, NULL, 0);
115118

116-
while (accept(dp, YAML_SCALAR_EVENT, key)) {
119+
while (device_parser_accept(dp, YAML_SCALAR_EVENT, key, TOKEN_LENGTH)) {
117120
struct device_user *user = calloc(1, sizeof(*user));
118121

119122
user->username = strdup(key);
120123

121124
list_add(dev->users, &user->node);
122125
}
123126

124-
expect(dp, YAML_SEQUENCE_END_EVENT, NULL);
127+
device_parser_expect(dp, YAML_SEQUENCE_END_EVENT, NULL, 0);
125128

126129
continue;
127130
}
128131

129-
expect(dp, YAML_SCALAR_EVENT, value);
132+
if (!strcmp(key, "local_gpio")) {
133+
dev->control_options = local_gpio_ops.parse_options(dp);
134+
if (dev->control_options)
135+
set_control_ops(dev, &local_gpio_ops);
136+
continue;
137+
}
138+
139+
device_parser_expect(dp, YAML_SCALAR_EVENT, value, TOKEN_LENGTH);
130140

131141
if (!strcmp(key, "board")) {
132142
dev->board = strdup(value);
@@ -212,25 +222,25 @@ int device_parser(const char *path)
212222

213223
nextsym(&dp);
214224

215-
expect(&dp, YAML_STREAM_START_EVENT, NULL);
225+
device_parser_expect(&dp, YAML_STREAM_START_EVENT, NULL, 0);
216226

217-
expect(&dp, YAML_DOCUMENT_START_EVENT, NULL);
218-
expect(&dp, YAML_MAPPING_START_EVENT, NULL);
227+
device_parser_expect(&dp, YAML_DOCUMENT_START_EVENT, NULL, 0);
228+
device_parser_expect(&dp, YAML_MAPPING_START_EVENT, NULL, 0);
219229

220-
if (accept(&dp, YAML_SCALAR_EVENT, key)) {
221-
expect(&dp, YAML_SEQUENCE_START_EVENT, NULL);
230+
if (device_parser_accept(&dp, YAML_SCALAR_EVENT, key, TOKEN_LENGTH)) {
231+
device_parser_expect(&dp, YAML_SEQUENCE_START_EVENT, NULL, 0);
222232

223-
while (accept(&dp, YAML_MAPPING_START_EVENT, NULL)) {
233+
while (device_parser_accept(&dp, YAML_MAPPING_START_EVENT, NULL, 0)) {
224234
parse_board(&dp);
225-
expect(&dp, YAML_MAPPING_END_EVENT, NULL);
235+
device_parser_expect(&dp, YAML_MAPPING_END_EVENT, NULL, 0);
226236
}
227237

228-
expect(&dp, YAML_SEQUENCE_END_EVENT, NULL);
238+
device_parser_expect(&dp, YAML_SEQUENCE_END_EVENT, NULL, 0);
229239
}
230240

231-
expect(&dp, YAML_MAPPING_END_EVENT, NULL);
232-
expect(&dp, YAML_DOCUMENT_END_EVENT, NULL);
233-
expect(&dp, YAML_STREAM_END_EVENT, NULL);
241+
device_parser_expect(&dp, YAML_MAPPING_END_EVENT, NULL, 0);
242+
device_parser_expect(&dp, YAML_DOCUMENT_END_EVENT, NULL, 0);
243+
device_parser_expect(&dp, YAML_STREAM_END_EVENT, NULL, 0);
234244

235245
yaml_event_delete(&dp.event);
236246
yaml_parser_delete(&dp.parser);

device_parser.h

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

4+
struct device_parser;
5+
6+
int device_parser_accept(struct device_parser *dp, int type,
7+
char *scalar, size_t scalar_len);
8+
bool device_parser_expect(struct device_parser *dp, int type,
9+
char *scalar, size_t scalar_len);
10+
411
int device_parser(const char *path);
512

613
#endif

local-gpio-v1.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright (c) 2023, Linaro Ltd.
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright notice,
9+
* this list of conditions and the following disclaimer.
10+
*
11+
* 2. Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
*
15+
* 3. Neither the name of the copyright holder nor the names of its contributors
16+
* may be used to endorse or promote products derived from this software without
17+
* specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29+
* POSSIBILITY OF SUCH DAMAGE.
30+
*/
31+
#include <ctype.h>
32+
#include <err.h>
33+
#include <errno.h>
34+
#include <fcntl.h>
35+
#include <stdio.h>
36+
#include <string.h>
37+
#include <stdlib.h>
38+
#include <unistd.h>
39+
#include <stdbool.h>
40+
41+
/* local-gpio implementation for libgpiod major version 1 */
42+
43+
#include "local-gpio.h"
44+
45+
#include <gpiod.h>
46+
47+
int local_gpio_init(struct local_gpio *local_gpio)
48+
{
49+
int i;
50+
51+
for (i = 0; i < GPIO_COUNT; ++i) {
52+
struct gpiod_line_request_config cfg;
53+
54+
if (!local_gpio->options->gpios[i].present)
55+
continue;
56+
57+
local_gpio->gpios[i].chip =
58+
gpiod_chip_open_lookup(local_gpio->options->gpios[i].chip);
59+
if (!local_gpio->gpios[i].chip) {
60+
err(1, "Unable to open gpiochip '%s'",
61+
local_gpio->options->gpios[i].chip);
62+
return -1;
63+
}
64+
65+
cfg.consumer = "cdba";
66+
cfg.request_type = GPIOD_LINE_REQUEST_DIRECTION_OUTPUT;
67+
cfg.flags = 0;
68+
69+
if (local_gpio->options->gpios[i].active_low)
70+
cfg.flags = GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW;
71+
72+
local_gpio->gpios[i].line = gpiod_chip_get_line(local_gpio->gpios[i].chip,
73+
local_gpio->options->gpios[i].offset);
74+
75+
if (!local_gpio->gpios[i].line) {
76+
err(1, "Unable to find gpio %d offset %u",
77+
i, local_gpio->options->gpios[i].offset);
78+
return -1;
79+
}
80+
81+
if (gpiod_line_request(local_gpio->gpios[i].line, &cfg, 0)) {
82+
err(1, "Unable to request gpio %d offset %u",
83+
i, local_gpio->options->gpios[i].offset);
84+
return -1;
85+
}
86+
}
87+
88+
return 0;
89+
}
90+
91+
int local_gpio_set_value(struct local_gpio *local_gpio, unsigned int gpio, bool on)
92+
{
93+
return gpiod_line_set_value(local_gpio->gpios[gpio].line, on);
94+
}

0 commit comments

Comments
 (0)