From 3a3c99f7eefc6def3f78d30844cc4899fad2b831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=BCsch?= Date: Fri, 4 Mar 2011 15:40:32 +0000 Subject: [PATCH] n810: More retu-wdt cleanups SVN-Revision: 25863 --- ...us-retu-wdt-remove-unused-interfaces.patch | 182 +++++++++++++++++ .../535-cbus-retu-wdt-cleanup.patch | 184 +---------------- ...bus-retu-wdt-remove-static-variables.patch | 191 ++++++++++++++++++ ...5-cbus-retu-wdt-constify-info-struct.patch | 13 ++ 4 files changed, 389 insertions(+), 181 deletions(-) create mode 100644 target/linux/omap24xx/patches-2.6.38/534-cbus-retu-wdt-remove-unused-interfaces.patch create mode 100644 target/linux/omap24xx/patches-2.6.38/540-cbus-retu-wdt-remove-static-variables.patch create mode 100644 target/linux/omap24xx/patches-2.6.38/545-cbus-retu-wdt-constify-info-struct.patch diff --git a/target/linux/omap24xx/patches-2.6.38/534-cbus-retu-wdt-remove-unused-interfaces.patch b/target/linux/omap24xx/patches-2.6.38/534-cbus-retu-wdt-remove-unused-interfaces.patch new file mode 100644 index 00000000000..b7f73839e1a --- /dev/null +++ b/target/linux/omap24xx/patches-2.6.38/534-cbus-retu-wdt-remove-unused-interfaces.patch @@ -0,0 +1,182 @@ +Index: linux-2.6.38-rc6/drivers/cbus/retu-wdt.c +=================================================================== +--- linux-2.6.38-rc6.orig/drivers/cbus/retu-wdt.c 2011-03-04 15:45:37.533948567 +0100 ++++ linux-2.6.38-rc6/drivers/cbus/retu-wdt.c 2011-03-04 15:46:21.312816961 +0100 +@@ -52,7 +52,6 @@ static DEFINE_MUTEX(retu_wdt_mutex); + + /* Current period of watchdog */ + static unsigned int period_val = RETU_WDT_DEFAULT_TIMER; +-static int counter_param = RETU_WDT_MAX_TIMER; + + struct retu_wdt_dev { + struct device *dev; +@@ -109,56 +108,6 @@ static void retu_wdt_ping_work(struct wo + retu_wdt_ping_enable(wdev); + } + +-static ssize_t retu_wdt_period_show(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- /* Show current max counter */ +- return sprintf(buf, "%u\n", (u16)period_val); +-} +- +-/* +- * Note: This inteface is non-standard and likely to disappear! +- * Use /dev/watchdog instead, that's the standard. +- */ +-static ssize_t retu_wdt_period_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- unsigned int new_period; +- int ret; +- +-#ifdef CONFIG_WATCHDOG_NOWAYOUT +- retu_wdt_ping_disable(retu_wdt); +-#endif +- +- if (sscanf(buf, "%u", &new_period) != 1) { +- printk(KERN_ALERT "retu_wdt_period_store: Invalid input\n"); +- return -EINVAL; +- } +- +- ret = retu_modify_counter(new_period); +- if (ret < 0) +- return ret; +- +- return strnlen(buf, count); +-} +- +-static ssize_t retu_wdt_counter_show(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- u16 counter; +- +- /* Show current value in watchdog counter */ +- counter = retu_read_reg(dev, RETU_REG_WATCHDOG); +- +- /* Only the 5 LSB are important */ +- return snprintf(buf, PAGE_SIZE, "%u\n", (counter & 0x3F)); +-} +- +-static DEVICE_ATTR(period, S_IRUGO | S_IWUSR, retu_wdt_period_show, \ +- retu_wdt_period_store); +-static DEVICE_ATTR(counter, S_IRUGO, retu_wdt_counter_show, NULL); +- + static int retu_wdt_open(struct inode *inode, struct file *file) + { + if (test_and_set_bit(0, &retu_wdt->users)) +@@ -232,18 +181,6 @@ static long retu_wdt_ioctl(struct file * + return 0; + } + +-/* Start kicking retu watchdog until user space starts doing the kicking */ +-static int __devinit retu_wdt_ping(void) +-{ +-#ifdef CONFIG_WATCHDOG_NOWAYOUT +- retu_modify_counter(RETU_WDT_MAX_TIMER); +-#else +- retu_wdt_ping_enable(retu_wdt); +-#endif +- +- return 0; +-} +- + static const struct file_operations retu_wdt_fops = { + .owner = THIS_MODULE, + .write = retu_wdt_write, +@@ -252,8 +189,6 @@ static const struct file_operations retu + .release = retu_wdt_release, + }; + +-/*----------------------------------------------------------------------------*/ +- + static int __init retu_wdt_probe(struct platform_device *pdev) + { + struct retu_wdt_dev *wdev; +@@ -265,18 +200,6 @@ static int __init retu_wdt_probe(struct + + wdev->dev = &pdev->dev; + +- ret = device_create_file(&pdev->dev, &dev_attr_period); +- if (ret) { +- dev_err(&pdev->dev, "Error creating sysfs period\n"); +- goto free1; +- } +- +- ret = device_create_file(&pdev->dev, &dev_attr_counter); +- if (ret) { +- dev_err(&pdev->dev, "Error creating sysfs counter\n"); +- goto free2; +- } +- + platform_set_drvdata(pdev, wdev); + retu_wdt = wdev; + wdev->retu_wdt_miscdev.parent = &pdev->dev; +@@ -286,38 +209,21 @@ static int __init retu_wdt_probe(struct + + ret = misc_register(&(wdev->retu_wdt_miscdev)); + if (ret) +- goto free3; ++ goto err_free_wdev; + + INIT_DELAYED_WORK(&wdev->ping_work, retu_wdt_ping_work); + +- /* passed as module parameter? */ +- ret = retu_modify_counter(counter_param); +- if (ret == -EINVAL) { +- ret = retu_modify_counter(RETU_WDT_DEFAULT_TIMER); +- dev_dbg(&pdev->dev, "Initializing to default value\n"); +- } +- +- /* Kick the watchdog for kernel booting to finish */ ++ /* Kick the watchdog for kernel booting to finish. ++ * If nowayout is not set, we start the ping work. */ ++#ifdef CONFIG_WATCHDOG_NOWAYOUT + retu_modify_counter(RETU_WDT_MAX_TIMER); +- +- ret = retu_wdt_ping(); +- if (ret < 0) { +- dev_err(&pdev->dev, "Failed to ping\n"); +- goto free4; +- } ++#else ++ retu_wdt_ping_enable(retu_wdt); ++#endif + + return 0; + +-free4: +- misc_deregister(&wdev->retu_wdt_miscdev); +- +-free3: +- device_remove_file(&pdev->dev, &dev_attr_counter); +- +-free2: +- device_remove_file(&pdev->dev, &dev_attr_period); +- +-free1: ++err_free_wdev: + kfree(wdev); + + return ret; +@@ -329,8 +235,6 @@ static int __devexit retu_wdt_remove(str + + wdev = platform_get_drvdata(pdev); + misc_deregister(&wdev->retu_wdt_miscdev); +- device_remove_file(&pdev->dev, &dev_attr_period); +- device_remove_file(&pdev->dev, &dev_attr_counter); + cancel_delayed_work_sync(&wdev->ping_work); + kfree(wdev); + +@@ -356,9 +260,7 @@ static void __exit retu_wdt_exit(void) + + module_init(retu_wdt_init); + module_exit(retu_wdt_exit); +-module_param(counter_param, int, 0); + + MODULE_DESCRIPTION("Retu WatchDog"); + MODULE_AUTHOR("Amit Kucheria"); + MODULE_LICENSE("GPL"); +- diff --git a/target/linux/omap24xx/patches-2.6.38/535-cbus-retu-wdt-cleanup.patch b/target/linux/omap24xx/patches-2.6.38/535-cbus-retu-wdt-cleanup.patch index 4b650686fdb..3ec78d1dd77 100644 --- a/target/linux/omap24xx/patches-2.6.38/535-cbus-retu-wdt-cleanup.patch +++ b/target/linux/omap24xx/patches-2.6.38/535-cbus-retu-wdt-cleanup.patch @@ -1,73 +1,8 @@ Index: linux-2.6.38-rc6/drivers/cbus/retu-wdt.c =================================================================== ---- linux-2.6.38-rc6.orig/drivers/cbus/retu-wdt.c 2011-03-02 16:49:51.231863891 +0100 -+++ linux-2.6.38-rc6/drivers/cbus/retu-wdt.c 2011-03-02 16:53:47.189454637 +0100 -@@ -52,7 +52,6 @@ static DEFINE_MUTEX(retu_wdt_mutex); - - /* Current period of watchdog */ - static unsigned int period_val = RETU_WDT_DEFAULT_TIMER; --static int counter_param = RETU_WDT_MAX_TIMER; - - struct retu_wdt_dev { - struct device *dev; -@@ -109,56 +108,6 @@ static void retu_wdt_ping_work(struct wo - retu_wdt_ping_enable(wdev); - } - --static ssize_t retu_wdt_period_show(struct device *dev, -- struct device_attribute *attr, char *buf) --{ -- /* Show current max counter */ -- return sprintf(buf, "%u\n", (u16)period_val); --} -- --/* -- * Note: This inteface is non-standard and likely to disappear! -- * Use /dev/watchdog instead, that's the standard. -- */ --static ssize_t retu_wdt_period_store(struct device *dev, -- struct device_attribute *attr, -- const char *buf, size_t count) --{ -- unsigned int new_period; -- int ret; -- --#ifdef CONFIG_WATCHDOG_NOWAYOUT -- retu_wdt_ping_disable(retu_wdt); --#endif -- -- if (sscanf(buf, "%u", &new_period) != 1) { -- printk(KERN_ALERT "retu_wdt_period_store: Invalid input\n"); -- return -EINVAL; -- } -- -- ret = retu_modify_counter(new_period); -- if (ret < 0) -- return ret; -- -- return strnlen(buf, count); --} -- --static ssize_t retu_wdt_counter_show(struct device *dev, -- struct device_attribute *attr, char *buf) --{ -- u16 counter; -- -- /* Show current value in watchdog counter */ -- counter = retu_read_reg(dev, RETU_REG_WATCHDOG); -- -- /* Only the 5 LSB are important */ -- return snprintf(buf, PAGE_SIZE, "%u\n", (counter & 0x3F)); --} -- --static DEVICE_ATTR(period, S_IRUGO | S_IWUSR, retu_wdt_period_show, \ -- retu_wdt_period_store); --static DEVICE_ATTR(counter, S_IRUGO, retu_wdt_counter_show, NULL); -- - static int retu_wdt_open(struct inode *inode, struct file *file) - { - if (test_and_set_bit(0, &retu_wdt->users)) -@@ -175,9 +124,9 @@ static int retu_wdt_release(struct inode +--- linux-2.6.38-rc6.orig/drivers/cbus/retu-wdt.c 2011-03-04 15:46:21.312816961 +0100 ++++ linux-2.6.38-rc6/drivers/cbus/retu-wdt.c 2011-03-04 15:46:54.658384947 +0100 +@@ -124,9 +124,9 @@ static int retu_wdt_release(struct inode struct retu_wdt_dev *wdev = file->private_data; #ifndef CONFIG_WATCHDOG_NOWAYOUT @@ -79,116 +14,3 @@ Index: linux-2.6.38-rc6/drivers/cbus/retu-wdt.c return 0; } -@@ -232,18 +181,6 @@ static long retu_wdt_ioctl(struct file * - return 0; - } - --/* Start kicking retu watchdog until user space starts doing the kicking */ --static int __devinit retu_wdt_ping(void) --{ --#ifdef CONFIG_WATCHDOG_NOWAYOUT -- retu_modify_counter(RETU_WDT_MAX_TIMER); --#else -- retu_wdt_ping_enable(retu_wdt); --#endif -- -- return 0; --} -- - static const struct file_operations retu_wdt_fops = { - .owner = THIS_MODULE, - .write = retu_wdt_write, -@@ -252,8 +189,6 @@ static const struct file_operations retu - .release = retu_wdt_release, - }; - --/*----------------------------------------------------------------------------*/ -- - static int __init retu_wdt_probe(struct platform_device *pdev) - { - struct retu_wdt_dev *wdev; -@@ -265,18 +200,6 @@ static int __init retu_wdt_probe(struct - - wdev->dev = &pdev->dev; - -- ret = device_create_file(&pdev->dev, &dev_attr_period); -- if (ret) { -- dev_err(&pdev->dev, "Error creating sysfs period\n"); -- goto free1; -- } -- -- ret = device_create_file(&pdev->dev, &dev_attr_counter); -- if (ret) { -- dev_err(&pdev->dev, "Error creating sysfs counter\n"); -- goto free2; -- } -- - platform_set_drvdata(pdev, wdev); - retu_wdt = wdev; - wdev->retu_wdt_miscdev.parent = &pdev->dev; -@@ -286,38 +209,21 @@ static int __init retu_wdt_probe(struct - - ret = misc_register(&(wdev->retu_wdt_miscdev)); - if (ret) -- goto free3; -+ goto err_free_wdev; - - INIT_DELAYED_WORK(&wdev->ping_work, retu_wdt_ping_work); - -- /* passed as module parameter? */ -- ret = retu_modify_counter(counter_param); -- if (ret == -EINVAL) { -- ret = retu_modify_counter(RETU_WDT_DEFAULT_TIMER); -- dev_dbg(&pdev->dev, "Initializing to default value\n"); -- } -- -- /* Kick the watchdog for kernel booting to finish */ -+ /* Kick the watchdog for kernel booting to finish. -+ * If nowayout is not set, we start the ping work. */ -+#ifdef CONFIG_WATCHDOG_NOWAYOUT - retu_modify_counter(RETU_WDT_MAX_TIMER); -- -- ret = retu_wdt_ping(); -- if (ret < 0) { -- dev_err(&pdev->dev, "Failed to ping\n"); -- goto free4; -- } -+#else -+ retu_wdt_ping_enable(retu_wdt); -+#endif - - return 0; - --free4: -- misc_deregister(&wdev->retu_wdt_miscdev); -- --free3: -- device_remove_file(&pdev->dev, &dev_attr_counter); -- --free2: -- device_remove_file(&pdev->dev, &dev_attr_period); -- --free1: -+err_free_wdev: - kfree(wdev); - - return ret; -@@ -329,8 +235,6 @@ static int __devexit retu_wdt_remove(str - - wdev = platform_get_drvdata(pdev); - misc_deregister(&wdev->retu_wdt_miscdev); -- device_remove_file(&pdev->dev, &dev_attr_period); -- device_remove_file(&pdev->dev, &dev_attr_counter); - cancel_delayed_work_sync(&wdev->ping_work); - kfree(wdev); - -@@ -356,9 +260,7 @@ static void __exit retu_wdt_exit(void) - - module_init(retu_wdt_init); - module_exit(retu_wdt_exit); --module_param(counter_param, int, 0); - - MODULE_DESCRIPTION("Retu WatchDog"); - MODULE_AUTHOR("Amit Kucheria"); - MODULE_LICENSE("GPL"); -- diff --git a/target/linux/omap24xx/patches-2.6.38/540-cbus-retu-wdt-remove-static-variables.patch b/target/linux/omap24xx/patches-2.6.38/540-cbus-retu-wdt-remove-static-variables.patch new file mode 100644 index 00000000000..14d31112e78 --- /dev/null +++ b/target/linux/omap24xx/patches-2.6.38/540-cbus-retu-wdt-remove-static-variables.patch @@ -0,0 +1,191 @@ +Index: linux-2.6.38-rc6/drivers/cbus/retu-wdt.c +=================================================================== +--- linux-2.6.38-rc6.orig/drivers/cbus/retu-wdt.c 2011-03-04 16:22:03.524019824 +0100 ++++ linux-2.6.38-rc6/drivers/cbus/retu-wdt.c 2011-03-04 16:22:31.186357952 +0100 +@@ -7,6 +7,8 @@ + * + * Written by Amit Kucheria + * ++ * Cleanups by Michael Buesch (C) 2011 ++ * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. +@@ -48,37 +50,31 @@ + #define RETU_WDT_DEFAULT_TIMER 32 + #define RETU_WDT_MAX_TIMER 63 + +-static DEFINE_MUTEX(retu_wdt_mutex); +- +-/* Current period of watchdog */ +-static unsigned int period_val = RETU_WDT_DEFAULT_TIMER; +- + struct retu_wdt_dev { + struct device *dev; ++ unsigned int period_val; /* Current period of watchdog */ + unsigned long users; +- struct miscdevice retu_wdt_miscdev; ++ struct miscdevice miscdev; + struct delayed_work ping_work; ++ struct mutex mutex; + }; + +-static struct retu_wdt_dev *retu_wdt; + +-static int _retu_modify_counter(unsigned int new) ++static inline void _retu_modify_counter(struct retu_wdt_dev *wdev, ++ unsigned int new) + { +- if (retu_wdt) +- retu_write_reg(retu_wdt->dev, RETU_REG_WATCHDOG, (u16)new); +- +- return 0; ++ retu_write_reg(wdev->dev, RETU_REG_WATCHDOG, (u16)new); + } + +-static int retu_modify_counter(unsigned int new) ++static int retu_modify_counter(struct retu_wdt_dev *wdev, unsigned int new) + { + if (new < RETU_WDT_MIN_TIMER || new > RETU_WDT_MAX_TIMER) + return -EINVAL; + +- mutex_lock(&retu_wdt_mutex); +- period_val = new; +- _retu_modify_counter(period_val); +- mutex_unlock(&retu_wdt_mutex); ++ mutex_lock(&wdev->mutex); ++ wdev->period_val = new; ++ _retu_modify_counter(wdev, wdev->period_val); ++ mutex_unlock(&wdev->mutex); + + return 0; + } +@@ -90,14 +86,14 @@ static int retu_modify_counter(unsigned + */ + static void retu_wdt_ping_enable(struct retu_wdt_dev *wdev) + { +- _retu_modify_counter(RETU_WDT_MAX_TIMER); ++ _retu_modify_counter(wdev, RETU_WDT_MAX_TIMER); + schedule_delayed_work(&wdev->ping_work, + round_jiffies_relative(RETU_WDT_DEFAULT_TIMER * HZ)); + } + + static void retu_wdt_ping_disable(struct retu_wdt_dev *wdev) + { +- _retu_modify_counter(RETU_WDT_MAX_TIMER); ++ _retu_modify_counter(wdev, RETU_WDT_MAX_TIMER); + cancel_delayed_work_sync(&wdev->ping_work); + } + +@@ -110,18 +106,21 @@ static void retu_wdt_ping_work(struct wo + + static int retu_wdt_open(struct inode *inode, struct file *file) + { +- if (test_and_set_bit(0, &retu_wdt->users)) ++ struct miscdevice *mdev = file->private_data; ++ struct retu_wdt_dev *wdev = container_of(mdev, struct retu_wdt_dev, miscdev); ++ ++ if (test_and_set_bit(0, &wdev->users)) + return -EBUSY; + +- file->private_data = (void *)retu_wdt; +- retu_wdt_ping_disable(retu_wdt); ++ retu_wdt_ping_disable(wdev); + + return nonseekable_open(inode, file); + } + + static int retu_wdt_release(struct inode *inode, struct file *file) + { +- struct retu_wdt_dev *wdev = file->private_data; ++ struct miscdevice *mdev = file->private_data; ++ struct retu_wdt_dev *wdev = container_of(mdev, struct retu_wdt_dev, miscdev); + + #ifndef CONFIG_WATCHDOG_NOWAYOUT + retu_wdt_ping_enable(wdev); +@@ -134,8 +133,11 @@ static int retu_wdt_release(struct inode + static ssize_t retu_wdt_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) + { ++ struct miscdevice *mdev = file->private_data; ++ struct retu_wdt_dev *wdev = container_of(mdev, struct retu_wdt_dev, miscdev); ++ + if (len) +- retu_modify_counter(RETU_WDT_MAX_TIMER); ++ retu_modify_counter(wdev, RETU_WDT_MAX_TIMER); + + return len; + } +@@ -143,6 +145,8 @@ static ssize_t retu_wdt_write(struct fil + static long retu_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) + { ++ struct miscdevice *mdev = file->private_data; ++ struct retu_wdt_dev *wdev = container_of(mdev, struct retu_wdt_dev, miscdev); + int new_margin; + + static struct watchdog_info ident = { +@@ -167,15 +171,15 @@ static long retu_wdt_ioctl(struct file * + return put_user(omap_prcm_get_reset_sources(), + (int __user *)arg); + case WDIOC_KEEPALIVE: +- retu_modify_counter(RETU_WDT_MAX_TIMER); ++ retu_modify_counter(wdev, RETU_WDT_MAX_TIMER); + break; + case WDIOC_SETTIMEOUT: + if (get_user(new_margin, (int __user *)arg)) + return -EFAULT; +- retu_modify_counter(new_margin); ++ retu_modify_counter(wdev, new_margin); + /* Fall through */ + case WDIOC_GETTIMEOUT: +- return put_user(period_val, (int __user *)arg); ++ return put_user(wdev->period_val, (int __user *)arg); + } + + return 0; +@@ -199,15 +203,17 @@ static int __init retu_wdt_probe(struct + return -ENOMEM; + + wdev->dev = &pdev->dev; ++ wdev->period_val = RETU_WDT_DEFAULT_TIMER; ++ mutex_init(&wdev->mutex); + + platform_set_drvdata(pdev, wdev); +- retu_wdt = wdev; +- wdev->retu_wdt_miscdev.parent = &pdev->dev; +- wdev->retu_wdt_miscdev.minor = WATCHDOG_MINOR; +- wdev->retu_wdt_miscdev.name = "watchdog"; +- wdev->retu_wdt_miscdev.fops = &retu_wdt_fops; + +- ret = misc_register(&(wdev->retu_wdt_miscdev)); ++ wdev->miscdev.parent = &pdev->dev; ++ wdev->miscdev.minor = WATCHDOG_MINOR; ++ wdev->miscdev.name = "watchdog"; ++ wdev->miscdev.fops = &retu_wdt_fops; ++ ++ ret = misc_register(&wdev->miscdev); + if (ret) + goto err_free_wdev; + +@@ -216,9 +222,9 @@ static int __init retu_wdt_probe(struct + /* Kick the watchdog for kernel booting to finish. + * If nowayout is not set, we start the ping work. */ + #ifdef CONFIG_WATCHDOG_NOWAYOUT +- retu_modify_counter(RETU_WDT_MAX_TIMER); ++ retu_modify_counter(wdev, RETU_WDT_MAX_TIMER); + #else +- retu_wdt_ping_enable(retu_wdt); ++ retu_wdt_ping_enable(wdev); + #endif + + return 0; +@@ -234,7 +240,7 @@ static int __devexit retu_wdt_remove(str + struct retu_wdt_dev *wdev; + + wdev = platform_get_drvdata(pdev); +- misc_deregister(&wdev->retu_wdt_miscdev); ++ misc_deregister(&wdev->miscdev); + cancel_delayed_work_sync(&wdev->ping_work); + kfree(wdev); + diff --git a/target/linux/omap24xx/patches-2.6.38/545-cbus-retu-wdt-constify-info-struct.patch b/target/linux/omap24xx/patches-2.6.38/545-cbus-retu-wdt-constify-info-struct.patch new file mode 100644 index 00000000000..8d6d2bb8cb6 --- /dev/null +++ b/target/linux/omap24xx/patches-2.6.38/545-cbus-retu-wdt-constify-info-struct.patch @@ -0,0 +1,13 @@ +Index: linux-2.6.38-rc6/drivers/cbus/retu-wdt.c +=================================================================== +--- linux-2.6.38-rc6.orig/drivers/cbus/retu-wdt.c 2011-03-04 16:21:39.106113985 +0100 ++++ linux-2.6.38-rc6/drivers/cbus/retu-wdt.c 2011-03-04 16:21:48.503540758 +0100 +@@ -149,7 +149,7 @@ static long retu_wdt_ioctl(struct file * + struct retu_wdt_dev *wdev = container_of(mdev, struct retu_wdt_dev, miscdev); + int new_margin; + +- static struct watchdog_info ident = { ++ static const struct watchdog_info ident = { + .identity = "Retu Watchdog", + .options = WDIOF_SETTIMEOUT, + .firmware_version = 0,