[PATCHv2] gpio: add simple get/set helpers for GPIO lines
by Martin Hundebøll
The Linux kernel GPIO api operates with chips, lines, handles, and
events.
The chip and line structures represent info about gpio chips, and
gpio lines, respectively. They are used to e.g. lookup a line with a
certain name, and/or line flags.
The handle structure is used to "obtain" a handle to one or more gpio
lines on a chip. Until the file descriptor in this handle is closed, the
gpio lines cannot be used by others. The same file descriptor is used
when setting or getting the line values (one can also set the initial
value when obtaining handles for output lines).
The event structure is used to get a file descriptor that can be used
with select/poll to wait for changes in line levels.
This commit add simple support for setting and getting the value for a
single gpio line. It does so by obtaining a line handle to get/set the
value, and then release the handle immediately again.
Functionality that could be implemented, but is postponed until the need
arises includes:
* looking up a gpio line by its name
* setting/getting multiple gpio lines with a single function
* waiting for events
* holding on to handles
Some of the above probably require adding structures to represent gpio
lines and events, while handles should be private to the class.
---
Changes since v1:
* added gpiochip info and corresponding getters
* changed "line" to "line_num" a few places
Changes since RFC:
* added gpio.h to ell.h
* changed copyright to Geanix
* open gpiochip in l_gpio_chip_new()
* open gpiochip read-only
* added input checks
* clear ioctl structs with memset instead of = {0}
* reorder error-paths
Makefile.am | 6 +-
ell/ell.h | 1 +
ell/ell.sym | 7 +++
ell/gpio.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/gpio.h | 49 +++++++++++++++
5 files changed, 236 insertions(+), 2 deletions(-)
create mode 100644 ell/gpio.c
create mode 100644 ell/gpio.h
diff --git a/Makefile.am b/Makefile.am
index 8401972..0ecb9a1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,7 +51,8 @@ pkginclude_HEADERS = ell/ell.h \
ell/dhcp.h \
ell/cert.h \
ell/ecc.h \
- ell/ecdh.h
+ ell/ecdh.h \
+ ell/gpio.h
lib_LTLIBRARIES = ell/libell.la
@@ -119,7 +120,8 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/ecc.h \
ell/ecc-external.c \
ell/ecc.c \
- ell/ecdh.c
+ ell/ecdh.c \
+ ell/gpio.c
ell_libell_la_LDFLAGS = -no-undefined \
-Wl,--version-script=$(top_srcdir)/ell/ell.sym \
diff --git a/ell/ell.h b/ell/ell.h
index aab6417..fb1dd79 100644
--- a/ell/ell.h
+++ b/ell/ell.h
@@ -59,3 +59,4 @@
#include <ell/cert.h>
#include <ell/ecc.h>
#include <ell/ecdh.h>
+#include <ell/gpio.h>
diff --git a/ell/ell.sym b/ell/ell.sym
index 841bc49..793e4c3 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -463,6 +463,13 @@ global:
/* ecdh */
l_ecdh_generate_key_pair;
l_ecdh_generate_shared_secret;
+ /* gpio */
+ l_gpio_chip_new;
+ l_gpio_chip_free;
+ l_gpio_chip_get_label;
+ l_gpio_chip_get_num_lines;
+ l_gpio_chip_get_line_value;
+ l_gpio_chip_set_line_value;
local:
*;
};
diff --git a/ell/gpio.c b/ell/gpio.c
new file mode 100644
index 0000000..83032f9
--- /dev/null
+++ b/ell/gpio.c
@@ -0,0 +1,175 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2018 Geanix. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <linux/gpio.h>
+
+#include "util.h"
+#include "gpio.h"
+#include "private.h"
+
+struct l_gpio_chip {
+ int fd;
+ char *label;
+ uint32_t num_lines;
+};
+
+LIB_EXPORT struct l_gpio_chip *l_gpio_chip_new(const char *chip_name)
+{
+ struct l_gpio_chip *chip;
+ struct gpiochip_info info;
+ char *path;
+ int ret;
+
+ if (!chip_name)
+ return NULL;
+
+ chip = l_new(struct l_gpio_chip, 1);
+
+ path = l_strdup_printf("/dev/%s", chip_name);
+ chip->fd = open(path, O_RDONLY | O_CLOEXEC);
+ l_free(path);
+
+ if (chip->fd < 0) {
+ l_free(chip);
+ return NULL;
+ }
+
+ memset(&info, 0, sizeof(info));
+
+ ret = ioctl(chip->fd, GPIO_GET_CHIPINFO_IOCTL, &info);
+ if (ret < 0) {
+ l_free(chip);
+ return NULL;
+ }
+
+ if (info.label)
+ chip->label = l_strndup(info.label, sizeof(info.label));
+
+ chip->num_lines = info.lines;
+
+ return chip;
+}
+
+LIB_EXPORT void l_gpio_chip_free(struct l_gpio_chip *chip)
+{
+ if (!chip)
+ return;
+
+ if (chip->fd >= 0)
+ close(chip->fd);
+
+ l_free(chip->label);
+ l_free(chip);
+}
+
+LIB_EXPORT const char *l_gpio_chip_get_label(struct l_gpio_chip *chip)
+{
+ if (!chip)
+ return NULL;
+
+ return chip->label;
+}
+
+LIB_EXPORT uint32_t l_gpio_chip_get_num_lines(struct l_gpio_chip *chip)
+{
+ if (!chip)
+ return 0;
+
+ return chip->num_lines;
+}
+
+LIB_EXPORT bool l_gpio_chip_get_line_value(struct l_gpio_chip *chip,
+ uint32_t line_num, bool *value)
+{
+ struct gpiohandle_request req;
+ struct gpiohandle_data data;
+ int ret;
+
+ if (!chip)
+ return false;
+
+ if (line_num >= chip->num_lines)
+ return false;
+
+ if (chip->fd < 0)
+ return false;
+
+ memset(&req, 0, sizeof(req));
+ req.lineoffsets[0] = line_num;
+ req.lines = 1;
+ req.flags = GPIOHANDLE_REQUEST_INPUT;
+
+ ret = ioctl(chip->fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
+ if (ret < 0 || req.fd <= 0)
+ return false;
+
+ memset(&data, 0, sizeof(data));
+
+ ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
+
+ close(req.fd);
+
+ if (ret < 0)
+ return false;
+
+ if (value)
+ *value = !!data.values[0];
+
+ return true;
+}
+
+LIB_EXPORT bool l_gpio_chip_set_line_value(struct l_gpio_chip *chip,
+ uint32_t line_num, bool value)
+{
+ struct gpiohandle_request req;
+ int ret;
+
+ if (!chip)
+ return false;
+
+ if (line_num >= chip->num_lines)
+ return false;
+
+ if (chip->fd < 0)
+ return false;
+
+ memset(&req, 0, sizeof(req));
+ req.lineoffsets[0] = line_num;
+ req.lines = 1;
+ req.flags = GPIOHANDLE_REQUEST_OUTPUT;
+ req.default_values[0] = value;
+
+ ret = ioctl(chip->fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
+ if (ret < 0 || req.fd <= 0)
+ return false;
+
+ close(req.fd);
+
+ return true;
+}
diff --git a/ell/gpio.h b/ell/gpio.h
new file mode 100644
index 0000000..9f4ae6a
--- /dev/null
+++ b/ell/gpio.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2011-2018 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __ELL_GPIO_H
+#define __ELL_GPIO_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_gpio_chip;
+
+struct l_gpio_chip *l_gpio_chip_new(const char *chip_name);
+void l_gpio_chip_free(struct l_gpio_chip *chip);
+
+const char *l_gpio_chip_get_label(struct l_gpio_chip *chip);
+uint32_t l_gpio_chip_get_num_lines(struct l_gpio_chip *chip);
+bool l_gpio_chip_get_line_value(struct l_gpio_chip *chip, uint32_t line_num,
+ bool *value);
+bool l_gpio_chip_set_line_value(struct l_gpio_chip *chip, uint32_t line_num,
+ bool value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_GPIO_H */
--
2.20.0
1 year, 7 months
[PATCH] unit: Fix Clang 8 "-Wstring-plus-int" warning
by Ossama Othman
Declare the fixed string in unit/test-checksum.c as a static array
instead of a string literal to address a warning exhibited by Clang 8
regarding addition of an integer to a string:
unit/test-checksum.c:170:30: warning: adding 'unsigned long' to a
string does not append to the string [-Wstring-plus-int]
iov[1].iov_base = FIXED_STR + FIXED_LEN / 2;
~~~~~~~~~~^~~~~~~~~~~~~~~
unit/test-checksum.c:170:30: note: use array indexing to silence this
warning
iov[1].iov_base = FIXED_STR + FIXED_LEN / 2;
^
& [ ]
Storing the string in an array makes it obvious that pointer
arithmetic is being performed.
---
unit/test-checksum.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/unit/test-checksum.c b/unit/test-checksum.c
index 296395f..f21d0bb 100644
--- a/unit/test-checksum.c
+++ b/unit/test-checksum.c
@@ -28,10 +28,12 @@
#include <ell/ell.h>
-#define FIXED_STR "The quick brown fox jumps over the lazy dog. " \
- "Jackdaws love my big sphinx of quartz. " \
- "Pack my box with five dozen liquor jugs. " \
- "How razorback-jumping frogs can level six piqued gymnasts!"
+static char FIXED_STR[] =
+ "The quick brown fox jumps over the lazy dog. "
+ "Jackdaws love my big sphinx of quartz. "
+ "Pack my box with five dozen liquor jugs. "
+ "How razorback-jumping frogs can level six piqued gymnasts!";
+
#define FIXED_LEN (strlen (FIXED_STR))
static void test_unsupported(const void *data)
--
2.20.1
1 year, 7 months
[PATCH 0/2] Allow connection to a tcp dbus address
by Ramon Henrique
This patch came from a demand in a project with industrial IoT for
monitoring a PLC (creating supervisor apps). The infrastructure was
built from a DBus service that can be accessed by a front-end in the
same local network.
Ramon Ribeiro (2):
dbus: Add support to tcp address
unit: dbus: Add unit test to dbus tcp address
.gitignore | 1 +
Makefile.am | 3 +
ell/dbus.c | 95 ++++++++++++++++++-
unit/dbus.conf | 2 +
unit/test-dbus-tcp.c | 261 +++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 358 insertions(+), 4 deletions(-)
create mode 100644 unit/test-dbus-tcp.c
--
2.11.0
1 year, 9 months
[PATCH 1/2] cipher: add AES-CTR
by James Prestwood
The kernel already supports this with ctr(aes), so adding a new cipher
type was all that was needed.
---
ell/cipher.c | 2 ++
ell/cipher.h | 1 +
2 files changed, 3 insertions(+)
diff --git a/ell/cipher.c b/ell/cipher.c
index 977ebc8..7b909df 100644
--- a/ell/cipher.c
+++ b/ell/cipher.c
@@ -148,6 +148,8 @@ static const char *cipher_type_to_name(enum l_cipher_type type)
return "ecb(aes)";
case L_CIPHER_AES_CBC:
return "cbc(aes)";
+ case L_CIPHER_AES_CTR:
+ return "ctr(aes)";
case L_CIPHER_ARC4:
return "ecb(arc4)";
case L_CIPHER_DES:
diff --git a/ell/cipher.h b/ell/cipher.h
index 946b9ad..84f2988 100644
--- a/ell/cipher.h
+++ b/ell/cipher.h
@@ -32,6 +32,7 @@ struct l_cipher;
enum l_cipher_type {
L_CIPHER_AES = 0,
L_CIPHER_AES_CBC,
+ L_CIPHER_AES_CTR,
L_CIPHER_ARC4,
L_CIPHER_DES,
L_CIPHER_DES_CBC,
--
2.17.1
1 year, 9 months
[PATCH] ecc: add checks for zero, one and order
by James Prestwood
To mitigate potential attacks, checks were added to the two
scalar initalization APIs l_ecc_scalar{new,new_random}. After
the scalar is created we check that its not zero or one, and
less than the group order. For new_random we also keep the check
that the scalar is less than the group prime, as this is required
in several RFCs/spec for creating random values.
---
ell/ecc.c | 32 +++++++++++++++++++++++++++-----
1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/ell/ecc.c b/ell/ecc.c
index 6182155..d0c7393 100644
--- a/ell/ecc.c
+++ b/ell/ecc.c
@@ -448,6 +448,20 @@ int _vli_legendre(uint64_t *val, const uint64_t *p, unsigned int ndigits)
return -1;
}
+static bool vli_is_zero_or_one(const uint64_t *vli, unsigned int ndigits)
+{
+ unsigned int i;
+
+ if (ndigits == 0 || vli[0] > 1)
+ return false;
+
+ for (i = 1; i < ndigits; i++) {
+ if (vli[i])
+ return false;
+ }
+
+ return true;
+}
LIB_EXPORT struct l_ecc_point *l_ecc_point_new(const struct l_ecc_curve *curve)
{
@@ -584,22 +598,30 @@ LIB_EXPORT struct l_ecc_scalar *l_ecc_scalar_new(
if (!c)
return NULL;
- if (buf)
- _ecc_be2native(c->c, buf, curve->ndigits);
+ if (!buf)
+ return c;
- return c;
+ _ecc_be2native(c->c, buf, curve->ndigits);
+
+ if (!vli_is_zero_or_one(c->c, curve->ndigits) &&
+ _vli_cmp(c->c, curve->n, curve->ndigits) < 0)
+ return c;
+
+ l_ecc_scalar_free(c);
+
+ return NULL;
}
LIB_EXPORT struct l_ecc_scalar *l_ecc_scalar_new_random(
const struct l_ecc_curve *curve)
{
uint64_t r[L_ECC_MAX_DIGITS];
- uint64_t zero[L_ECC_MAX_DIGITS] = { 0 };
l_getrandom(r, curve->ndigits * 8);
while (_vli_cmp(r, curve->p, curve->ndigits) > 0 ||
- _vli_cmp(r, zero, curve->ndigits) == 0)
+ _vli_cmp(r, curve->n, curve->ndigits) > 0 ||
+ vli_is_zero_or_one(r, curve->ndigits))
l_getrandom(r, curve->ndigits * 8);
return _ecc_constant_new(curve, r, curve->ndigits * 8);
--
2.17.1
1 year, 9 months
[PATCH 0/2] Fix unit tests under Clang build.
by Ossama Othman
This patch set addresses unit test build warnings and a segmentation
fault when ELL is built with the Clang C compiler.
Ossama Othman (2):
unit: Remove unnecessary NULL pointer checks.
unit: Fixed a test-dbus-message seg fault.
unit/test-dbus-message.c | 2 +-
unit/test-dhcp.c | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
--
2.17.1
1 year, 9 months
[PATCH] genl: Be more careful with termination of genl names
by Mat Martineau
GCC 9 adds "-Werror=stringop-truncation" that warns (and therefore
triggers a compile error) when strncpy has a size limit that's the same
as the destination size, which can allow string termination
problems. Instead, reduce the limit passed to strncpy by 1 and make sure
the destination is terminated. This appears to be consistent with the
handling of GENL_NAMSIZ strings in the kernel.
The fixed-length struct genl_mcast name is also used in a string
comparison, where the known size limit is now applied.
---
ell/genl.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/ell/genl.c b/ell/genl.c
index 2905a5e..74a49e6 100644
--- a/ell/genl.c
+++ b/ell/genl.c
@@ -161,7 +161,8 @@ static struct l_genl_family *family_alloc(struct l_genl *genl,
family = l_new(struct l_genl_family, 1);
family->genl = genl;
- strncpy(family->name, name, GENL_NAMSIZ);
+ strncpy(family->name, name, GENL_NAMSIZ - 1);
+ family->name[GENL_NAMSIZ - 1] = '\0';
family->op_list = l_queue_new();
family->mcast_list = l_queue_new();
@@ -218,7 +219,7 @@ static bool match_mcast_name(const void *a, const void *b)
const struct genl_mcast *mcast = a;
const char *name = b;
- return !strcmp(mcast->name, name);
+ return !strncmp(mcast->name, name, GENL_NAMSIZ);
}
static void family_add_mcast(struct l_genl_family *family, const char *name,
@@ -237,7 +238,9 @@ static void family_add_mcast(struct l_genl_family *family, const char *name,
mcast = l_new(struct genl_mcast, 1);
- strncpy(mcast->name, name, GENL_NAMSIZ);
+ strncpy(mcast->name, name, GENL_NAMSIZ - 1);
+ mcast->name[GENL_NAMSIZ - 1] = '\0';
+
mcast->id = id;
mcast->users = 0;
@@ -1046,7 +1049,8 @@ static void get_family_callback(struct l_genl_msg *msg, void *user_data)
family->id = *((uint16_t *) data);
break;
case CTRL_ATTR_FAMILY_NAME:
- strncpy(family->name, data, GENL_NAMSIZ);
+ strncpy(family->name, data, GENL_NAMSIZ - 1);
+ family->name[GENL_NAMSIZ - 1] = '\0';
break;
case CTRL_ATTR_VERSION:
family->version = *((uint32_t *) data);
--
2.21.0
1 year, 9 months
[PATCH v2] util: Make l_container_of macro public
by Michał Lowas-Rzechonek
The macro is useful when e.g. scheduling timeouts, where l_timeout
passed to l_timeout_notify_cb_t is a member of a larger object, and we
would like to access this object while passing something else as
user_data.
---
ell/dbus.c | 8 ++++----
ell/dhcp-transport.c | 6 +++---
ell/private.h | 4 ----
ell/util.h | 5 +++++
unit/test-dbus-watch.c | 4 ++--
5 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/ell/dbus.c b/ell/dbus.c
index 92be396..3a84c90 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -579,7 +579,7 @@ static void dbus_init(struct l_dbus *dbus, int fd)
static void classic_free(struct l_dbus *dbus)
{
struct l_dbus_classic *classic =
- container_of(dbus, struct l_dbus_classic, super);
+ l_container_of(dbus, struct l_dbus_classic, super);
unsigned int i;
for (i = 0; i < classic->num_fds; i++)
@@ -658,7 +658,7 @@ static bool classic_send_message(struct l_dbus *dbus,
static struct l_dbus_message *classic_recv_message(struct l_dbus *dbus)
{
struct l_dbus_classic *classic =
- container_of(dbus, struct l_dbus_classic, super);
+ l_container_of(dbus, struct l_dbus_classic, super);
int fd = l_io_get_fd(dbus->io);
struct dbus_header hdr;
struct msghdr msg;
@@ -809,7 +809,7 @@ static bool classic_add_match(struct l_dbus *dbus, unsigned int id,
int rule_len)
{
struct l_dbus_classic *classic =
- container_of(dbus, struct l_dbus_classic, super);
+ l_container_of(dbus, struct l_dbus_classic, super);
char *match_str;
struct l_dbus_message *message;
@@ -833,7 +833,7 @@ static bool classic_add_match(struct l_dbus *dbus, unsigned int id,
static bool classic_remove_match(struct l_dbus *dbus, unsigned int id)
{
struct l_dbus_classic *classic =
- container_of(dbus, struct l_dbus_classic, super);
+ l_container_of(dbus, struct l_dbus_classic, super);
char *match_str = l_hashmap_remove(classic->match_strings,
L_UINT_TO_PTR(id));
struct l_dbus_message *message;
diff --git a/ell/dhcp-transport.c b/ell/dhcp-transport.c
index 1de190a..758af10 100644
--- a/ell/dhcp-transport.c
+++ b/ell/dhcp-transport.c
@@ -148,7 +148,7 @@ static int _dhcp_default_transport_open(struct dhcp_transport *s,
uint32_t port)
{
struct dhcp_default_transport *transport =
- container_of(s, struct dhcp_default_transport, super);
+ l_container_of(s, struct dhcp_default_transport, super);
int fd;
if (transport->io)
@@ -263,7 +263,7 @@ static int _dhcp_default_transport_send(struct dhcp_transport *s,
const void *data, size_t len)
{
struct dhcp_default_transport *transport =
- container_of(s, struct dhcp_default_transport, super);
+ l_container_of(s, struct dhcp_default_transport, super);
int fd = l_io_get_fd(transport->io);
int err;
@@ -279,7 +279,7 @@ static int _dhcp_default_transport_send(struct dhcp_transport *s,
static void _dhcp_default_transport_close(struct dhcp_transport *s)
{
struct dhcp_default_transport *transport =
- container_of(s, struct dhcp_default_transport, super);
+ l_container_of(s, struct dhcp_default_transport, super);
l_io_destroy(transport->io);
transport->io = NULL;
diff --git a/ell/private.h b/ell/private.h
index f132577..b0ae43f 100644
--- a/ell/private.h
+++ b/ell/private.h
@@ -27,10 +27,6 @@
#define uninitialized_var(x) x = x
-#define container_of(ptr, type, member) ({ \
- const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
-
#define align_len(len, boundary) (((len)+(boundary)-1) & ~((boundary)-1))
#define LIB_EXPORT __attribute__ ((visibility("default")))
diff --git a/ell/util.h b/ell/util.h
index c4ba7f8..95503de 100644
--- a/ell/util.h
+++ b/ell/util.h
@@ -35,6 +35,11 @@
extern "C" {
#endif
+#define l_container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) ); \
+ })
+
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
diff --git a/unit/test-dbus-watch.c b/unit/test-dbus-watch.c
index c6e4a92..029d71c 100644
--- a/unit/test-dbus-watch.c
+++ b/unit/test-dbus-watch.c
@@ -108,7 +108,7 @@ static bool test_add_match(struct l_dbus *dbus, unsigned int id,
int rule_len)
{
struct filter_test_state *test =
- container_of(dbus, struct filter_test_state, dbus);
+ l_container_of(dbus, struct filter_test_state, dbus);
assert(test->expected_rule);
@@ -124,7 +124,7 @@ static bool test_add_match(struct l_dbus *dbus, unsigned int id,
static bool test_remove_match(struct l_dbus *dbus, unsigned int id)
{
struct filter_test_state *test =
- container_of(dbus, struct filter_test_state, dbus);
+ l_container_of(dbus, struct filter_test_state, dbus);
assert(test->expected_id == id && id);
--
2.20.1
1 year, 9 months
[PATCH] util: Added l_container_of macro
by Michał 'Khorne' Lowas-Rzechonek
From: Michał Lowas-Rzechonek <michal.lowas-rzechonek(a)silvair.com>
The macro is useful when e.g. scheduling timeouts, where l_timeout
passed to l_timeout_notify_cb_t is a member of a larger object, and we
would like to access this object while passing something else as
user_data.
---
ell/util.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/ell/util.h b/ell/util.h
index c4ba7f8..95503de 100644
--- a/ell/util.h
+++ b/ell/util.h
@@ -35,6 +35,11 @@
extern "C" {
#endif
+#define l_container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) ); \
+ })
+
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
--
2.19.1
1 year, 9 months