Add iic_is_compatible() for matching I2C devices
authorvisa <visa@openbsd.org>
Wed, 9 Feb 2022 07:58:24 +0000 (07:58 +0000)
committervisa <visa@openbsd.org>
Wed, 9 Feb 2022 07:58:24 +0000 (07:58 +0000)
When using device trees, the ia_name field of struct i2c_attach_args
points to the first string of the device node's "compatible" array.
However, in many cases it would be preferable to use the last, most
general "compatible" entry as a device matching criterion.

Enable more flexible device matching by permitting ia_name to point to
the raw "compatible" data which is a concatenation of NUL-terminated
strings. I2C bus code will supply the data and set ia_name and
ia_namelen. I2C device drivers will use iic_is_compatible() to check
matches. This method is also backwards compatible with the old, direct
use of ia_name.

Prompted by a related patch from kettenis@.

OK kettenis@

share/man/man9/iic.9
sys/dev/i2c/i2c.c
sys/dev/i2c/i2cvar.h

index 7fd3855..ce3bb00 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: iic.9,v 1.9 2015/11/23 17:53:57 jmc Exp $
+.\"    $OpenBSD: iic.9,v 1.10 2022/02/09 07:58:24 visa Exp $
 .\"
 .\" Copyright (c) 2003 Wasabi Systems, Inc.
 .\" All rights reserved.
@@ -33,7 +33,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: November 23 2015 $
+.Dd $Mdocdate: February 9 2022 $
 .Dt IIC_ACQUIRE_BUS 9
 .Os
 .Sh NAME
@@ -42,7 +42,8 @@
 .Nm iic_exec ,
 .Nm iic_smbus_write_byte ,
 .Nm iic_smbus_read_byte ,
-.Nm iic_smbus_receive_byte
+.Nm iic_smbus_receive_byte ,
+.Nm iic_is_compatible
 .Nd Inter IC (I2C) bus
 .Sh SYNOPSIS
 .In dev/i2c/i2cvar.h
 .Fa "uint8_t *datap"
 .Fa "int flags"
 .Fc
+.Ft int
+.Fo iic_is_compatible
+.Fa "const struct i2c_attach_args *ia"
+.Fa "const char *name"
+.Fc
 .Sh DESCRIPTION
 I2C is a two-wire bus developed by Philips used for connecting
 integrated circuits.
@@ -137,8 +143,11 @@ struct i2c_attach_args {
        i2c_addr_t ia_addr;     /* address of device */
        int ia_size;            /* size (for EEPROMs) */
        char *ia_name;          /* chip name */
+       size_t ia_namelen       /* length of name concatenation */
        void *ia_cookie;        /* pass extra info from
                                   bus to dev */
+       void *ia_intr           /* interrupt info */
+       int ia_poll;            /* to force polling */
 };
 .Ed
 .El
@@ -231,6 +240,9 @@ I2C_OP_READ_WITH_STOP with
 of 0 and
 .Fa len
 of 1.
+.It Fn iic_is_compatible "ia" "name"
+Test if the device is compatible with
+.Fa name .
 .El
 .Sh CONTROLLER INTERFACE
 The I2C controller driver must fill in the function pointers of
index 4b44892..48e0ec9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: i2c.c,v 1.17 2021/10/26 16:29:49 deraadt Exp $        */
+/*     $OpenBSD: i2c.c,v 1.18 2022/02/09 07:58:24 visa Exp $   */
 /*     $NetBSD: i2c.c,v 1.1 2003/09/30 00:35:31 thorpej Exp $  */
 
 /*
@@ -143,3 +143,26 @@ iic_attach(struct device *parent, struct device *self, void *aux)
        else
                iic_scan(self, aux);
 }
+
+int
+iic_is_compatible(const struct i2c_attach_args *ia, const char *name)
+{
+       const char *end, *entry;
+
+       if (ia->ia_namelen > 0) {
+               /* ia_name points to a concatenation of strings. */
+               entry = ia->ia_name;
+               end = entry + ia->ia_namelen;
+               while (entry < end) {
+                       if (strcmp(entry, name) == 0)
+                               return (1);
+                       entry += strlen(entry) + 1;
+               }
+       } else {
+               /* ia_name points to a string. */
+               if (strcmp(ia->ia_name, name) == 0)
+                       return (1);
+       }
+
+       return (0);
+}
index aaba329..7246922 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: i2cvar.h,v 1.17 2019/07/22 14:37:06 jcs Exp $ */
+/*     $OpenBSD: i2cvar.h,v 1.18 2022/02/09 07:58:24 visa Exp $        */
 /*     $NetBSD: i2cvar.h,v 1.1 2003/09/30 00:35:31 thorpej Exp $       */
 
 /*
@@ -111,6 +111,7 @@ struct i2c_attach_args {
        i2c_addr_t      ia_addr;        /* address of device */
        int             ia_size;        /* size (for EEPROMs) */
        char            *ia_name;       /* chip name */
+       size_t          ia_namelen;     /* length of name concatenation */
        void            *ia_cookie;     /* pass extra info from bus to dev */
        void            *ia_intr;       /* interrupt info */
        int             ia_poll;        /* to force polling */
@@ -164,5 +165,6 @@ int iic_smbus_receive_byte(i2c_tag_t, i2c_addr_t, uint8_t *, int);
        (*(ic)->ic_intr_string)((ic)->ic_cookie, (ih))
 
 void   iic_ignore_addr(u_int8_t addr);
+int    iic_is_compatible(const struct i2c_attach_args *, const char *);
 
 #endif /* _DEV_I2C_I2CVAR_H_ */