* [PATCH] i2c: Add parameters to sysfs-added i2c devices @ 2014-11-14 14:41 minyard-HInyCGIudOg [not found] ` <1415976117-27755-1-git-send-email-minyard-HInyCGIudOg@public.gmane.org> 0 siblings, 1 reply; 4+ messages in thread From: minyard-HInyCGIudOg @ 2014-11-14 14:41 UTC (permalink / raw) To: Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Corey Minyard From: Corey Minyard <cminyard-Igf4POYTYCDQT0dZR+AlfA@public.gmane.org> Some devices might need parameters to control their operation, add the ability to pass these parameters to the client. This also makes the parsing of sysfs-added I2C devices a little more flexible, allowing tabs and arbitrary numbers of spaces. Signed-off-by: Corey Minyard <cminyard-Igf4POYTYCDQT0dZR+AlfA@public.gmane.org> --- drivers/i2c/i2c-core.c | 46 ++++++++++++++++++++++++++++++++++------------ include/linux/i2c.h | 3 +++ 2 files changed, 37 insertions(+), 12 deletions(-) I'm adding an SMBus IPMI driver, and it needs to be able to have the IPMI bus address specified in case it's not the default. Also, this seems like it would be useful for other devices that need some sort of configuration. diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index f43b4e1..9a2ab13 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -781,7 +781,10 @@ static int i2c_device_pm_restore(struct device *dev) static void i2c_client_dev_release(struct device *dev) { - kfree(to_i2c_client(dev)); + struct i2c_client *client = to_i2c_client(dev); + + kfree(client->parms); + kfree(client); } static ssize_t @@ -1059,6 +1062,13 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) client->flags = info->flags; client->addr = info->addr; client->irq = info->irq; + if (info->parms) { + client->parms = kstrdup(info->parms, GFP_KERNEL); + if (!client->parms) { + dev_err(&adap->dev, "Out of memory allocating parms\n"); + goto out_err_silent; + } + } strlcpy(client->name, info->type, sizeof(client->name)); @@ -1207,31 +1217,43 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, struct i2c_adapter *adap = to_i2c_adapter(dev); struct i2c_board_info info; struct i2c_client *client; - char *blank, end; + char *pos, end; int res; memset(&info, 0, sizeof(struct i2c_board_info)); - blank = strchr(buf, ' '); - if (!blank) { + pos = strpbrk(buf, " \t"); + if (!pos) { dev_err(dev, "%s: Missing parameters\n", "new_device"); return -EINVAL; } - if (blank - buf > I2C_NAME_SIZE - 1) { + if (pos - buf > I2C_NAME_SIZE - 1) { dev_err(dev, "%s: Invalid device name\n", "new_device"); return -EINVAL; } - memcpy(info.type, buf, blank - buf); + memcpy(info.type, buf, pos - buf); - /* Parse remaining parameters, reject extra parameters */ - res = sscanf(++blank, "%hi%c", &info.addr, &end); - if (res < 1) { + while (isspace(*pos)) + pos++; + + /* Parse address, saving remaining parameters. */ + res = sscanf(pos, "%hi%c", &info.addr, &end); + if (res < 1 || !isspace(end)) { dev_err(dev, "%s: Can't parse I2C address\n", "new_device"); return -EINVAL; } - if (res > 1 && end != '\n') { - dev_err(dev, "%s: Extra parameters\n", "new_device"); - return -EINVAL; + if (res > 1 && end != '\n') { + if (isspace(end)) { + /* Extra parms, skip the address and space. */ + while (!isspace(*pos)) + pos++; + while (isspace(*pos)) + pos++; + info.parms = pos; + } else { + dev_err(dev, "%s: Extra parameters\n", "new_device"); + return -EINVAL; + } } client = i2c_new_device(adap, &info); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index b556e0a..e40fc56 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -222,6 +222,7 @@ struct i2c_client { char name[I2C_NAME_SIZE]; struct i2c_adapter *adapter; /* the adapter we sit on */ struct device dev; /* the device structure */ + char *parms; /* sysfs extra parms */ int irq; /* irq issued by device */ struct list_head detected; }; @@ -255,6 +256,7 @@ static inline void i2c_set_clientdata(struct i2c_client *dev, void *data) * @archdata: copied into i2c_client.dev.archdata * @of_node: pointer to OpenFirmware device node * @acpi_node: ACPI device node + * @parms: Parameters supplied on the sysfs command line * @irq: stored in i2c_client.irq * * I2C doesn't actually support hardware probing, although controllers and @@ -276,6 +278,7 @@ struct i2c_board_info { struct dev_archdata *archdata; struct device_node *of_node; struct acpi_dev_node acpi_node; + char *parms; int irq; }; -- 1.8.3.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
[parent not found: <1415976117-27755-1-git-send-email-minyard-HInyCGIudOg@public.gmane.org>]
* Re: [PATCH] i2c: Add parameters to sysfs-added i2c devices [not found] ` <1415976117-27755-1-git-send-email-minyard-HInyCGIudOg@public.gmane.org> @ 2014-11-24 13:43 ` Corey Minyard 2014-12-01 17:38 ` Wolfram Sang 0 siblings, 1 reply; 4+ messages in thread From: Corey Minyard @ 2014-11-24 13:43 UTC (permalink / raw) To: minyard-HInyCGIudOg, Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA Ping, I haven't heard anything on this. -corey On 11/14/2014 08:41 AM, minyard-HInyCGIudOg@public.gmane.org wrote: > From: Corey Minyard <cminyard-Igf4POYTYCDQT0dZR+AlfA@public.gmane.org> > > Some devices might need parameters to control their operation, > add the ability to pass these parameters to the client. > > This also makes the parsing of sysfs-added I2C devices a little > more flexible, allowing tabs and arbitrary numbers of spaces. > > Signed-off-by: Corey Minyard <cminyard-Igf4POYTYCDQT0dZR+AlfA@public.gmane.org> > --- > drivers/i2c/i2c-core.c | 46 ++++++++++++++++++++++++++++++++++------------ > include/linux/i2c.h | 3 +++ > 2 files changed, 37 insertions(+), 12 deletions(-) > > I'm adding an SMBus IPMI driver, and it needs to be able to have > the IPMI bus address specified in case it's not the default. > > Also, this seems like it would be useful for other devices that > need some sort of configuration. > > diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c > index f43b4e1..9a2ab13 100644 > --- a/drivers/i2c/i2c-core.c > +++ b/drivers/i2c/i2c-core.c > @@ -781,7 +781,10 @@ static int i2c_device_pm_restore(struct device *dev) > > static void i2c_client_dev_release(struct device *dev) > { > - kfree(to_i2c_client(dev)); > + struct i2c_client *client = to_i2c_client(dev); > + > + kfree(client->parms); > + kfree(client); > } > > static ssize_t > @@ -1059,6 +1062,13 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) > client->flags = info->flags; > client->addr = info->addr; > client->irq = info->irq; > + if (info->parms) { > + client->parms = kstrdup(info->parms, GFP_KERNEL); > + if (!client->parms) { > + dev_err(&adap->dev, "Out of memory allocating parms\n"); > + goto out_err_silent; > + } > + } > > strlcpy(client->name, info->type, sizeof(client->name)); > > @@ -1207,31 +1217,43 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, > struct i2c_adapter *adap = to_i2c_adapter(dev); > struct i2c_board_info info; > struct i2c_client *client; > - char *blank, end; > + char *pos, end; > int res; > > memset(&info, 0, sizeof(struct i2c_board_info)); > > - blank = strchr(buf, ' '); > - if (!blank) { > + pos = strpbrk(buf, " \t"); > + if (!pos) { > dev_err(dev, "%s: Missing parameters\n", "new_device"); > return -EINVAL; > } > - if (blank - buf > I2C_NAME_SIZE - 1) { > + if (pos - buf > I2C_NAME_SIZE - 1) { > dev_err(dev, "%s: Invalid device name\n", "new_device"); > return -EINVAL; > } > - memcpy(info.type, buf, blank - buf); > + memcpy(info.type, buf, pos - buf); > > - /* Parse remaining parameters, reject extra parameters */ > - res = sscanf(++blank, "%hi%c", &info.addr, &end); > - if (res < 1) { > + while (isspace(*pos)) > + pos++; > + > + /* Parse address, saving remaining parameters. */ > + res = sscanf(pos, "%hi%c", &info.addr, &end); > + if (res < 1 || !isspace(end)) { > dev_err(dev, "%s: Can't parse I2C address\n", "new_device"); > return -EINVAL; > } > - if (res > 1 && end != '\n') { > - dev_err(dev, "%s: Extra parameters\n", "new_device"); > - return -EINVAL; > + if (res > 1 && end != '\n') { > + if (isspace(end)) { > + /* Extra parms, skip the address and space. */ > + while (!isspace(*pos)) > + pos++; > + while (isspace(*pos)) > + pos++; > + info.parms = pos; > + } else { > + dev_err(dev, "%s: Extra parameters\n", "new_device"); > + return -EINVAL; > + } > } > > client = i2c_new_device(adap, &info); > diff --git a/include/linux/i2c.h b/include/linux/i2c.h > index b556e0a..e40fc56 100644 > --- a/include/linux/i2c.h > +++ b/include/linux/i2c.h > @@ -222,6 +222,7 @@ struct i2c_client { > char name[I2C_NAME_SIZE]; > struct i2c_adapter *adapter; /* the adapter we sit on */ > struct device dev; /* the device structure */ > + char *parms; /* sysfs extra parms */ > int irq; /* irq issued by device */ > struct list_head detected; > }; > @@ -255,6 +256,7 @@ static inline void i2c_set_clientdata(struct i2c_client *dev, void *data) > * @archdata: copied into i2c_client.dev.archdata > * @of_node: pointer to OpenFirmware device node > * @acpi_node: ACPI device node > + * @parms: Parameters supplied on the sysfs command line > * @irq: stored in i2c_client.irq > * > * I2C doesn't actually support hardware probing, although controllers and > @@ -276,6 +278,7 @@ struct i2c_board_info { > struct dev_archdata *archdata; > struct device_node *of_node; > struct acpi_dev_node acpi_node; > + char *parms; > int irq; > }; > ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] i2c: Add parameters to sysfs-added i2c devices 2014-11-24 13:43 ` Corey Minyard @ 2014-12-01 17:38 ` Wolfram Sang 2014-12-02 13:06 ` Corey Minyard 0 siblings, 1 reply; 4+ messages in thread From: Wolfram Sang @ 2014-12-01 17:38 UTC (permalink / raw) To: Corey Minyard; +Cc: minyard, linux-i2c, linux-kernel [-- Attachment #1: Type: text/plain, Size: 5109 bytes --] On Mon, Nov 24, 2014 at 07:43:23AM -0600, Corey Minyard wrote: > Ping, I haven't heard anything on this. Use cases please :) What client drivers would need that and what params do they need? > > -corey > > On 11/14/2014 08:41 AM, minyard@acm.org wrote: > > From: Corey Minyard <cminyard@mvista.com> > > > > Some devices might need parameters to control their operation, > > add the ability to pass these parameters to the client. > > > > This also makes the parsing of sysfs-added I2C devices a little > > more flexible, allowing tabs and arbitrary numbers of spaces. > > > > Signed-off-by: Corey Minyard <cminyard@mvista.com> > > --- > > drivers/i2c/i2c-core.c | 46 ++++++++++++++++++++++++++++++++++------------ > > include/linux/i2c.h | 3 +++ > > 2 files changed, 37 insertions(+), 12 deletions(-) > > > > I'm adding an SMBus IPMI driver, and it needs to be able to have > > the IPMI bus address specified in case it's not the default. > > > > Also, this seems like it would be useful for other devices that > > need some sort of configuration. > > > > diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c > > index f43b4e1..9a2ab13 100644 > > --- a/drivers/i2c/i2c-core.c > > +++ b/drivers/i2c/i2c-core.c > > @@ -781,7 +781,10 @@ static int i2c_device_pm_restore(struct device *dev) > > > > static void i2c_client_dev_release(struct device *dev) > > { > > - kfree(to_i2c_client(dev)); > > + struct i2c_client *client = to_i2c_client(dev); > > + > > + kfree(client->parms); > > + kfree(client); > > } > > > > static ssize_t > > @@ -1059,6 +1062,13 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) > > client->flags = info->flags; > > client->addr = info->addr; > > client->irq = info->irq; > > + if (info->parms) { > > + client->parms = kstrdup(info->parms, GFP_KERNEL); > > + if (!client->parms) { > > + dev_err(&adap->dev, "Out of memory allocating parms\n"); > > + goto out_err_silent; > > + } > > + } > > > > strlcpy(client->name, info->type, sizeof(client->name)); > > > > @@ -1207,31 +1217,43 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, > > struct i2c_adapter *adap = to_i2c_adapter(dev); > > struct i2c_board_info info; > > struct i2c_client *client; > > - char *blank, end; > > + char *pos, end; > > int res; > > > > memset(&info, 0, sizeof(struct i2c_board_info)); > > > > - blank = strchr(buf, ' '); > > - if (!blank) { > > + pos = strpbrk(buf, " \t"); > > + if (!pos) { > > dev_err(dev, "%s: Missing parameters\n", "new_device"); > > return -EINVAL; > > } > > - if (blank - buf > I2C_NAME_SIZE - 1) { > > + if (pos - buf > I2C_NAME_SIZE - 1) { > > dev_err(dev, "%s: Invalid device name\n", "new_device"); > > return -EINVAL; > > } > > - memcpy(info.type, buf, blank - buf); > > + memcpy(info.type, buf, pos - buf); > > > > - /* Parse remaining parameters, reject extra parameters */ > > - res = sscanf(++blank, "%hi%c", &info.addr, &end); > > - if (res < 1) { > > + while (isspace(*pos)) > > + pos++; > > + > > + /* Parse address, saving remaining parameters. */ > > + res = sscanf(pos, "%hi%c", &info.addr, &end); > > + if (res < 1 || !isspace(end)) { > > dev_err(dev, "%s: Can't parse I2C address\n", "new_device"); > > return -EINVAL; > > } > > - if (res > 1 && end != '\n') { > > - dev_err(dev, "%s: Extra parameters\n", "new_device"); > > - return -EINVAL; > > + if (res > 1 && end != '\n') { > > + if (isspace(end)) { > > + /* Extra parms, skip the address and space. */ > > + while (!isspace(*pos)) > > + pos++; > > + while (isspace(*pos)) > > + pos++; > > + info.parms = pos; > > + } else { > > + dev_err(dev, "%s: Extra parameters\n", "new_device"); > > + return -EINVAL; > > + } > > } > > > > client = i2c_new_device(adap, &info); > > diff --git a/include/linux/i2c.h b/include/linux/i2c.h > > index b556e0a..e40fc56 100644 > > --- a/include/linux/i2c.h > > +++ b/include/linux/i2c.h > > @@ -222,6 +222,7 @@ struct i2c_client { > > char name[I2C_NAME_SIZE]; > > struct i2c_adapter *adapter; /* the adapter we sit on */ > > struct device dev; /* the device structure */ > > + char *parms; /* sysfs extra parms */ > > int irq; /* irq issued by device */ > > struct list_head detected; > > }; > > @@ -255,6 +256,7 @@ static inline void i2c_set_clientdata(struct i2c_client *dev, void *data) > > * @archdata: copied into i2c_client.dev.archdata > > * @of_node: pointer to OpenFirmware device node > > * @acpi_node: ACPI device node > > + * @parms: Parameters supplied on the sysfs command line > > * @irq: stored in i2c_client.irq > > * > > * I2C doesn't actually support hardware probing, although controllers and > > @@ -276,6 +278,7 @@ struct i2c_board_info { > > struct dev_archdata *archdata; > > struct device_node *of_node; > > struct acpi_dev_node acpi_node; > > + char *parms; > > int irq; > > }; > > > [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] i2c: Add parameters to sysfs-added i2c devices 2014-12-01 17:38 ` Wolfram Sang @ 2014-12-02 13:06 ` Corey Minyard 0 siblings, 0 replies; 4+ messages in thread From: Corey Minyard @ 2014-12-02 13:06 UTC (permalink / raw) To: Wolfram Sang Cc: minyard-HInyCGIudOg, linux-i2c-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA On 12/01/2014 11:38 AM, Wolfram Sang wrote: > On Mon, Nov 24, 2014 at 07:43:23AM -0600, Corey Minyard wrote: >> Ping, I haven't heard anything on this. > Use cases please :) What client drivers would need that and what params > do they need? I'm adding an IPMI SMB driver, it should be going in 3.19. These devices have an IPMI bus address (not the I2C address), and it needs to be specified if it varies from the default, or certain messages won't work correctly. It seems like this would be useful for other things; it's a little surprising to me that no other devices need to have some parameters passed in. -corey >> -corey >> >> On 11/14/2014 08:41 AM, minyard-HInyCGIudOg@public.gmane.org wrote: >>> From: Corey Minyard <cminyard-Igf4POYTYCDQT0dZR+AlfA@public.gmane.org> >>> >>> Some devices might need parameters to control their operation, >>> add the ability to pass these parameters to the client. >>> >>> This also makes the parsing of sysfs-added I2C devices a little >>> more flexible, allowing tabs and arbitrary numbers of spaces. >>> >>> Signed-off-by: Corey Minyard <cminyard-Igf4POYTYCDQT0dZR+AlfA@public.gmane.org> >>> --- >>> drivers/i2c/i2c-core.c | 46 ++++++++++++++++++++++++++++++++++------------ >>> include/linux/i2c.h | 3 +++ >>> 2 files changed, 37 insertions(+), 12 deletions(-) >>> >>> I'm adding an SMBus IPMI driver, and it needs to be able to have >>> the IPMI bus address specified in case it's not the default. >>> >>> Also, this seems like it would be useful for other devices that >>> need some sort of configuration. >>> >>> diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c >>> index f43b4e1..9a2ab13 100644 >>> --- a/drivers/i2c/i2c-core.c >>> +++ b/drivers/i2c/i2c-core.c >>> @@ -781,7 +781,10 @@ static int i2c_device_pm_restore(struct device *dev) >>> >>> static void i2c_client_dev_release(struct device *dev) >>> { >>> - kfree(to_i2c_client(dev)); >>> + struct i2c_client *client = to_i2c_client(dev); >>> + >>> + kfree(client->parms); >>> + kfree(client); >>> } >>> >>> static ssize_t >>> @@ -1059,6 +1062,13 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) >>> client->flags = info->flags; >>> client->addr = info->addr; >>> client->irq = info->irq; >>> + if (info->parms) { >>> + client->parms = kstrdup(info->parms, GFP_KERNEL); >>> + if (!client->parms) { >>> + dev_err(&adap->dev, "Out of memory allocating parms\n"); >>> + goto out_err_silent; >>> + } >>> + } >>> >>> strlcpy(client->name, info->type, sizeof(client->name)); >>> >>> @@ -1207,31 +1217,43 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, >>> struct i2c_adapter *adap = to_i2c_adapter(dev); >>> struct i2c_board_info info; >>> struct i2c_client *client; >>> - char *blank, end; >>> + char *pos, end; >>> int res; >>> >>> memset(&info, 0, sizeof(struct i2c_board_info)); >>> >>> - blank = strchr(buf, ' '); >>> - if (!blank) { >>> + pos = strpbrk(buf, " \t"); >>> + if (!pos) { >>> dev_err(dev, "%s: Missing parameters\n", "new_device"); >>> return -EINVAL; >>> } >>> - if (blank - buf > I2C_NAME_SIZE - 1) { >>> + if (pos - buf > I2C_NAME_SIZE - 1) { >>> dev_err(dev, "%s: Invalid device name\n", "new_device"); >>> return -EINVAL; >>> } >>> - memcpy(info.type, buf, blank - buf); >>> + memcpy(info.type, buf, pos - buf); >>> >>> - /* Parse remaining parameters, reject extra parameters */ >>> - res = sscanf(++blank, "%hi%c", &info.addr, &end); >>> - if (res < 1) { >>> + while (isspace(*pos)) >>> + pos++; >>> + >>> + /* Parse address, saving remaining parameters. */ >>> + res = sscanf(pos, "%hi%c", &info.addr, &end); >>> + if (res < 1 || !isspace(end)) { >>> dev_err(dev, "%s: Can't parse I2C address\n", "new_device"); >>> return -EINVAL; >>> } >>> - if (res > 1 && end != '\n') { >>> - dev_err(dev, "%s: Extra parameters\n", "new_device"); >>> - return -EINVAL; >>> + if (res > 1 && end != '\n') { >>> + if (isspace(end)) { >>> + /* Extra parms, skip the address and space. */ >>> + while (!isspace(*pos)) >>> + pos++; >>> + while (isspace(*pos)) >>> + pos++; >>> + info.parms = pos; >>> + } else { >>> + dev_err(dev, "%s: Extra parameters\n", "new_device"); >>> + return -EINVAL; >>> + } >>> } >>> >>> client = i2c_new_device(adap, &info); >>> diff --git a/include/linux/i2c.h b/include/linux/i2c.h >>> index b556e0a..e40fc56 100644 >>> --- a/include/linux/i2c.h >>> +++ b/include/linux/i2c.h >>> @@ -222,6 +222,7 @@ struct i2c_client { >>> char name[I2C_NAME_SIZE]; >>> struct i2c_adapter *adapter; /* the adapter we sit on */ >>> struct device dev; /* the device structure */ >>> + char *parms; /* sysfs extra parms */ >>> int irq; /* irq issued by device */ >>> struct list_head detected; >>> }; >>> @@ -255,6 +256,7 @@ static inline void i2c_set_clientdata(struct i2c_client *dev, void *data) >>> * @archdata: copied into i2c_client.dev.archdata >>> * @of_node: pointer to OpenFirmware device node >>> * @acpi_node: ACPI device node >>> + * @parms: Parameters supplied on the sysfs command line >>> * @irq: stored in i2c_client.irq >>> * >>> * I2C doesn't actually support hardware probing, although controllers and >>> @@ -276,6 +278,7 @@ struct i2c_board_info { >>> struct dev_archdata *archdata; >>> struct device_node *of_node; >>> struct acpi_dev_node acpi_node; >>> + char *parms; >>> int irq; >>> }; >>> ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-12-02 13:06 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-11-14 14:41 [PATCH] i2c: Add parameters to sysfs-added i2c devices minyard-HInyCGIudOg [not found] ` <1415976117-27755-1-git-send-email-minyard-HInyCGIudOg@public.gmane.org> 2014-11-24 13:43 ` Corey Minyard 2014-12-01 17:38 ` Wolfram Sang 2014-12-02 13:06 ` Corey Minyard
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).