From 2a3662c653ecbe6a86fab8d3fee4063ccbf16b58 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Mon, 20 May 2024 13:25:34 +0200 Subject: [PATCH 1/6] implement cross platform update possibility for intelnuc <> generic-x86_64 because in future the intelnuc platform will be renamed to "generic-x86_64" because we are not limited to the intel NUC x86_64 hardware anymore. --- .../external/overlay/base/bin/fwinstall.sh | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/buildroot-external/package/recovery-system/external/overlay/base/bin/fwinstall.sh b/buildroot-external/package/recovery-system/external/overlay/base/bin/fwinstall.sh index f326698a39..75c0ba3bd6 100755 --- a/buildroot-external/package/recovery-system/external/overlay/base/bin/fwinstall.sh +++ b/buildroot-external/package/recovery-system/external/overlay/base/bin/fwinstall.sh @@ -5,7 +5,7 @@ # either archived or unarchived, verifies its validity and installs it # unattended accordingly. # -# Copyright (c) 2018-2021 Jens Maus +# Copyright (c) 2018-2024 Jens Maus # Apache 2.0 License applies # @@ -435,8 +435,12 @@ fwinstall() exit 1 fi - # check if both PLATFORM match - if [[ "${ROOTFS_PLATFORM}" != "${IMG_PLATFORM}" ]]; then + # check if both PLATFORM match including exceptions for + # cross platform updates/changes + if [[ "${ROOTFS_PLATFORM}" == "intelnuc" && "${IMG_PLATFORM}" == "generic-x86_64" ]] || + [[ "${ROOTFS_PLATFORM}" == "generic-x86_64" && "${IMG_PLATFORM}" == "intelnuc" ]]; then + echo "INFO: cross updating ${ROOTFS_PLATFORM} to ${IMG_PLATFORM}
" + elif [[ "${ROOTFS_PLATFORM}" != "${IMG_PLATFORM}" ]]; then echo "ERROR: incorrect hardware platform (${IMG_PLATFORM} != ${ROOTFS_PLATFORM})
" exit 1 fi @@ -535,8 +539,12 @@ fwinstall() exit 1 fi - # check if both PLATFORM match - if [[ "${BOOTFS_PLATFORM}" != "${IMG_PLATFORM}" ]]; then + # check if both PLATFORM match including exceptions for + # cross platform updates/changes + if [[ "${BOOTFS_PLATFORM}" == "intelnuc" && "${IMG_PLATFORM}" == "generic-x86_64" ]] || + [[ "${BOOTFS_PLATFORM}" == "generic-x86_64" && "${IMG_PLATFORM}" == "intelnuc" ]]; then + echo "INFO: cross updating ${BOOTFS_PLATFORM} to ${IMG_PLATFORM}
" + elif [[ "${BOOTFS_PLATFORM}" != "${IMG_PLATFORM}" ]]; then echo "ERROR: incorrect hardware platform (${IMG_PLATFORM} != ${BOOTFS_PLATFORM})
" exit 1 fi @@ -665,8 +673,12 @@ fwinstall() exit 1 fi - # check if both PLATFORM match - if [[ "${BOOTFS_PLATFORM}" != "${IMG_PLATFORM}" ]]; then + # check if both PLATFORM match including exceptions for + # cross platform updates/changes + if [[ "${BOOTFS_PLATFORM}" == "intelnuc" && "${IMG_PLATFORM}" == "generic-x86_64" ]] || + [[ "${BOOTFS_PLATFORM}" == "generic-x86_64" && "${IMG_PLATFORM}" == "intelnuc" ]]; then + echo "INFO: cross updating ${BOOTFS_PLATFORM} to ${IMG_PLATFORM}
" + elif [[ "${BOOTFS_PLATFORM}" != "${IMG_PLATFORM}" ]]; then echo "ERROR: incorrect hardware platform (${IMG_PLATFORM} != ${BOOTFS_PLATFORM})
" exit 1 fi @@ -799,8 +811,12 @@ fwinstall() exit 1 fi - # check if both PLATFORM match - if [[ "${ROOTFS_PLATFORM}" != "${IMG_PLATFORM}" ]]; then + # check if both PLATFORM match including exceptions for + # cross platform updates/changes + if [[ "${ROOTFS_PLATFORM}" == "intelnuc" && "${IMG_PLATFORM}" == "generic-x86_64" ]] || + [[ "${ROOTFS_PLATFORM}" == "generic-x86_64" && "${IMG_PLATFORM}" == "intelnuc" ]]; then + echo "INFO: cross updating ${ROOTFS_PLATFORM} to ${IMG_PLATFORM}
" + elif [[ "${ROOTFS_PLATFORM}" != "${IMG_PLATFORM}" ]]; then echo "ERROR: incorrect hardware platform (${IMG_PLATFORM} != ${ROOTFS_PLATFORM})
" exit 1 fi From c4a8ded5770fe22bdf22bb34200eb0ce5a5a3107 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Mon, 20 May 2024 16:10:12 +0200 Subject: [PATCH 2/6] split usb core changes revert patch between kernel 6.6.31+ and previous kernel versions (raspberrypi) by adding dedicated 6.6.31+ patch files to the global patch directories. --- ...changes-causing-issues-with-Z-Wave.m.patch | 652 ++++++++++++++++++ .../patches/linux-headers/6.6.31 | 1 + ...changes-causing-issues-with-Z-Wave.m.patch | 49 +- 3 files changed, 676 insertions(+), 26 deletions(-) create mode 100644 buildroot-external/board/rpi4/kernel-patches/0003-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch create mode 120000 buildroot-external/patches/linux-headers/6.6.31 rename buildroot-external/patches/linux/{ => 6.6.31}/0002-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch (93%) diff --git a/buildroot-external/board/rpi4/kernel-patches/0003-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch b/buildroot-external/board/rpi4/kernel-patches/0003-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch new file mode 100644 index 0000000000..bd05bc6693 --- /dev/null +++ b/buildroot-external/board/rpi4/kernel-patches/0003-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch @@ -0,0 +1,652 @@ +From 85cfbef1cf29aba24abe21409b180b7bea76e562 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= +Date: Wed, 6 Mar 2024 13:25:41 +0100 +Subject: [PATCH] Revert USB core changes causing issues with Z-Wave.me UZB + stick +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Workaround for issues described on GH [1] and reported in [2]. + +* Revert "USB: core: Fix oversight in SuperSpeed initialization" + This reverts commit 59cf445754566984fd55af19ba7146c76e6627bc. + +* Revert "USB: core: Fix race by not overwriting udev->descriptor in hub_port_init()" + This reverts commit ff33299ec8bb80cdcc073ad9c506bd79bb2ed20b. + +* Revert "USB: core: Change usb_get_device_descriptor() API" + This reverts commit de28e469da75359a2bb8cd8778b78aa64b1be1f4. + +* Revert "USB: core: Unite old scheme and new scheme descriptor reads" + This reverts commit 85d07c55621676d47d873d2749b88f783cd4d5a1. + +[1] https://github.com/home-assistant/operating-system/issues/2995 +[2] https://lore.kernel.org/linux-usb/1e954652-dfb3-4248-beea-b8a449128ff0@sairon.cz/ + +Signed-off-by: Jan Čermák +--- + drivers/usb/core/hcd.c | 10 +- + drivers/usb/core/hub.c | 335 ++++++++++++++++--------------------- + drivers/usb/core/message.c | 29 ++-- + drivers/usb/core/usb.h | 4 +- + 4 files changed, 166 insertions(+), 212 deletions(-) + +diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c +index 12b6dfeaf658c..d895f6ebbc400 100644 +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -958,7 +958,6 @@ static int register_root_hub(struct usb_hcd *hcd) + { + struct device *parent_dev = hcd->self.controller; + struct usb_device *usb_dev = hcd->self.root_hub; +- struct usb_device_descriptor *descr; + const int devnum = 1; + int retval; + +@@ -970,16 +969,13 @@ static int register_root_hub(struct usb_hcd *hcd) + mutex_lock(&usb_bus_idr_lock); + + usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); +- descr = usb_get_device_descriptor(usb_dev); +- if (IS_ERR(descr)) { +- retval = PTR_ERR(descr); ++ retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); ++ if (retval != sizeof usb_dev->descriptor) { + mutex_unlock(&usb_bus_idr_lock); + dev_dbg (parent_dev, "can't read %s device descriptor %d\n", + dev_name(&usb_dev->dev), retval); +- return retval; ++ return (retval < 0) ? retval : -EMSGSIZE; + } +- usb_dev->descriptor = *descr; +- kfree(descr); + + if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) { + retval = usb_get_bos_descriptor(usb_dev); +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 71635dfa741d2..b937bf8b6b3d3 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -4722,67 +4722,6 @@ static int hub_enable_device(struct usb_device *udev) + return hcd->driver->enable_device(hcd, udev); + } + +-/* +- * Get the bMaxPacketSize0 value during initialization by reading the +- * device's device descriptor. Since we don't already know this value, +- * the transfer is unsafe and it ignores I/O errors, only testing for +- * reasonable received values. +- * +- * For "old scheme" initialization, size will be 8 so we read just the +- * start of the device descriptor, which should work okay regardless of +- * the actual bMaxPacketSize0 value. For "new scheme" initialization, +- * size will be 64 (and buf will point to a sufficiently large buffer), +- * which might not be kosher according to the USB spec but it's what +- * Windows does and what many devices expect. +- * +- * Returns: bMaxPacketSize0 or a negative error code. +- */ +-static int get_bMaxPacketSize0(struct usb_device *udev, +- struct usb_device_descriptor *buf, int size, bool first_time) +-{ +- int i, rc; +- +- /* +- * Retry on all errors; some devices are flakey. +- * 255 is for WUSB devices, we actually need to use +- * 512 (WUSB1.0[4.8.1]). +- */ +- for (i = 0; i < GET_MAXPACKET0_TRIES; ++i) { +- /* Start with invalid values in case the transfer fails */ +- buf->bDescriptorType = buf->bMaxPacketSize0 = 0; +- rc = usb_control_msg(udev, usb_rcvaddr0pipe(), +- USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, +- USB_DT_DEVICE << 8, 0, +- buf, size, +- initial_descriptor_timeout); +- switch (buf->bMaxPacketSize0) { +- case 8: case 16: case 32: case 64: case 9: +- if (buf->bDescriptorType == USB_DT_DEVICE) { +- rc = buf->bMaxPacketSize0; +- break; +- } +- fallthrough; +- default: +- if (rc >= 0) +- rc = -EPROTO; +- break; +- } +- +- /* +- * Some devices time out if they are powered on +- * when already connected. They need a second +- * reset, so return early. But only on the first +- * attempt, lest we get into a time-out/reset loop. +- */ +- if (rc > 0 || (rc == -ETIMEDOUT && first_time && +- udev->speed > USB_SPEED_FULL)) +- break; +- } +- return rc; +-} +- +-#define GET_DESCRIPTOR_BUFSIZE 64 +- + /* Reset device, (re)assign address, get device descriptor. + * Device connection must be stable, no more debouncing needed. + * Returns device in USB_STATE_ADDRESS, except on error. +@@ -4792,17 +4731,10 @@ static int get_bMaxPacketSize0(struct usb_device *udev, + * the port lock. For a newly detected device that is not accessible + * through any global pointers, it's not necessary to lock the device, + * but it is still necessary to lock the port. +- * +- * For a newly detected device, @dev_descr must be NULL. The device +- * descriptor retrieved from the device will then be stored in +- * @udev->descriptor. For an already existing device, @dev_descr +- * must be non-NULL. The device descriptor will be stored there, +- * not in @udev->descriptor, because descriptors for registered +- * devices are meant to be immutable. + */ + static int + hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, +- int retry_counter, struct usb_device_descriptor *dev_descr) ++ int retry_counter) + { + struct usb_device *hdev = hub->hdev; + struct usb_hcd *hcd = bus_to_hcd(hdev->bus); +@@ -4814,13 +4746,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, + int devnum = udev->devnum; + const char *driver_name; + bool do_new_scheme; +- const bool initial = !dev_descr; +- int maxp0; +- struct usb_device_descriptor *buf, *descr; +- +- buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO); +- if (!buf) +- return -ENOMEM; + + /* root hub ports have a slightly longer reset period + * (from USB 2.0 spec, section 7.1.7.5) +@@ -4853,31 +4778,31 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, + } + oldspeed = udev->speed; + +- if (initial) { +- /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... +- * it's fixed size except for full speed devices. ++ /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... ++ * it's fixed size except for full speed devices. ++ * For Wireless USB devices, ep0 max packet is always 512 (tho ++ * reported as 0xff in the device descriptor). WUSB1.0[4.8.1]. ++ */ ++ switch (udev->speed) { ++ case USB_SPEED_SUPER_PLUS: ++ case USB_SPEED_SUPER: ++ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512); ++ break; ++ case USB_SPEED_HIGH: /* fixed at 64 */ ++ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); ++ break; ++ case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ ++ /* to determine the ep0 maxpacket size, try to read ++ * the device descriptor to get bMaxPacketSize0 and ++ * then correct our initial guess. + */ +- switch (udev->speed) { +- case USB_SPEED_SUPER_PLUS: +- case USB_SPEED_SUPER: +- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512); +- break; +- case USB_SPEED_HIGH: /* fixed at 64 */ +- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); +- break; +- case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ +- /* to determine the ep0 maxpacket size, try to read +- * the device descriptor to get bMaxPacketSize0 and +- * then correct our initial guess. +- */ +- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); +- break; +- case USB_SPEED_LOW: /* fixed at 8 */ +- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8); +- break; +- default: +- goto fail; +- } ++ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); ++ break; ++ case USB_SPEED_LOW: /* fixed at 8 */ ++ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8); ++ break; ++ default: ++ goto fail; + } + + speed = usb_speed_string(udev->speed); +@@ -4897,24 +4822,22 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, + if (udev->speed < USB_SPEED_SUPER) + dev_info(&udev->dev, + "%s %s USB device number %d using %s\n", +- (initial ? "new" : "reset"), speed, ++ (udev->config) ? "reset" : "new", speed, + devnum, driver_name); + +- if (initial) { +- /* Set up TT records, if needed */ +- if (hdev->tt) { +- udev->tt = hdev->tt; +- udev->ttport = hdev->ttport; +- } else if (udev->speed != USB_SPEED_HIGH +- && hdev->speed == USB_SPEED_HIGH) { +- if (!hub->tt.hub) { +- dev_err(&udev->dev, "parent hub has no TT\n"); +- retval = -EINVAL; +- goto fail; +- } +- udev->tt = &hub->tt; +- udev->ttport = port1; ++ /* Set up TT records, if needed */ ++ if (hdev->tt) { ++ udev->tt = hdev->tt; ++ udev->ttport = hdev->ttport; ++ } else if (udev->speed != USB_SPEED_HIGH ++ && hdev->speed == USB_SPEED_HIGH) { ++ if (!hub->tt.hub) { ++ dev_err(&udev->dev, "parent hub has no TT\n"); ++ retval = -EINVAL; ++ goto fail; + } ++ udev->tt = &hub->tt; ++ udev->ttport = port1; + } + + /* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way? +@@ -4938,6 +4861,9 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, + } + + if (do_new_scheme) { ++ struct usb_device_descriptor *buf; ++ int r = 0; ++ + retval = hub_enable_device(udev); + if (retval < 0) { + dev_err(&udev->dev, +@@ -4946,14 +4872,52 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, + goto fail; + } + +- maxp0 = get_bMaxPacketSize0(udev, buf, +- GET_DESCRIPTOR_BUFSIZE, retries == 0); +- if (maxp0 > 0 && !initial && +- maxp0 != udev->descriptor.bMaxPacketSize0) { +- dev_err(&udev->dev, "device reset changed ep0 maxpacket size!\n"); +- retval = -ENODEV; +- goto fail; ++#define GET_DESCRIPTOR_BUFSIZE 64 ++ buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO); ++ if (!buf) { ++ retval = -ENOMEM; ++ continue; ++ } ++ ++ /* Retry on all errors; some devices are flakey. ++ * 255 is for WUSB devices, we actually need to use ++ * 512 (WUSB1.0[4.8.1]). ++ */ ++ for (operations = 0; operations < GET_MAXPACKET0_TRIES; ++ ++operations) { ++ buf->bMaxPacketSize0 = 0; ++ r = usb_control_msg(udev, usb_rcvaddr0pipe(), ++ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, ++ USB_DT_DEVICE << 8, 0, ++ buf, GET_DESCRIPTOR_BUFSIZE, ++ initial_descriptor_timeout); ++ switch (buf->bMaxPacketSize0) { ++ case 8: case 16: case 32: case 64: case 255: ++ if (buf->bDescriptorType == ++ USB_DT_DEVICE) { ++ r = 0; ++ break; ++ } ++ fallthrough; ++ default: ++ if (r == 0) ++ r = -EPROTO; ++ break; ++ } ++ /* ++ * Some devices time out if they are powered on ++ * when already connected. They need a second ++ * reset. But only on the first attempt, ++ * lest we get into a time out/reset loop ++ */ ++ if (r == 0 || (r == -ETIMEDOUT && ++ retries == 0 && ++ udev->speed > USB_SPEED_FULL)) ++ break; + } ++ udev->descriptor.bMaxPacketSize0 = ++ buf->bMaxPacketSize0; ++ kfree(buf); + + retval = hub_port_reset(hub, port1, udev, delay, false); + if (retval < 0) /* error or disconnect */ +@@ -4964,13 +4928,14 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, + retval = -ENODEV; + goto fail; + } +- if (maxp0 < 0) { +- if (maxp0 != -ENODEV) ++ if (r) { ++ if (r != -ENODEV) + dev_err(&udev->dev, "device descriptor read/64, error %d\n", +- maxp0); +- retval = maxp0; ++ r); ++ retval = -EMSGSIZE; + continue; + } ++#undef GET_DESCRIPTOR_BUFSIZE + } + + for (operations = 0; operations < SET_ADDRESS_TRIES; ++operations) { +@@ -5011,21 +4976,18 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, + if (do_new_scheme) + break; + +- maxp0 = get_bMaxPacketSize0(udev, buf, 8, retries == 0); +- if (maxp0 < 0) { +- retval = maxp0; ++ retval = usb_get_device_descriptor(udev, 8); ++ if (retval < 8) { + if (retval != -ENODEV) + dev_err(&udev->dev, + "device descriptor read/8, error %d\n", + retval); ++ if (retval >= 0) ++ retval = -EMSGSIZE; + } else { + u32 delay; + +- if (!initial && maxp0 != udev->descriptor.bMaxPacketSize0) { +- dev_err(&udev->dev, "device reset changed ep0 maxpacket size!\n"); +- retval = -ENODEV; +- goto fail; +- } ++ retval = 0; + + delay = udev->parent->hub_delay; + udev->hub_delay = min_t(u32, delay, +@@ -5044,61 +5006,48 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, + goto fail; + + /* +- * Check the ep0 maxpacket guess and correct it if necessary. +- * maxp0 is the value stored in the device descriptor; +- * i is the value it encodes (logarithmic for SuperSpeed or greater). ++ * Some superspeed devices have finished the link training process ++ * and attached to a superspeed hub port, but the device descriptor ++ * got from those devices show they aren't superspeed devices. Warm ++ * reset the port attached by the devices can fix them. + */ +- i = maxp0; +- if (udev->speed >= USB_SPEED_SUPER) { +- if (maxp0 <= 16) +- i = 1 << maxp0; +- else +- i = 0; /* Invalid */ +- } +- if (usb_endpoint_maxp(&udev->ep0.desc) == i) { +- ; /* Initial ep0 maxpacket guess is right */ +- } else if ((udev->speed == USB_SPEED_FULL || +- udev->speed == USB_SPEED_HIGH) && +- (i == 8 || i == 16 || i == 32 || i == 64)) { +- /* Initial guess is wrong; use the descriptor's value */ ++ if ((udev->speed >= USB_SPEED_SUPER) && ++ (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) { ++ dev_err(&udev->dev, "got a wrong device descriptor, " ++ "warm reset device\n"); ++ hub_port_reset(hub, port1, udev, ++ HUB_BH_RESET_TIME, true); ++ retval = -EINVAL; ++ goto fail; ++ } ++ ++ if (udev->descriptor.bMaxPacketSize0 == 0xff || ++ udev->speed >= USB_SPEED_SUPER) ++ i = 512; ++ else ++ i = udev->descriptor.bMaxPacketSize0; ++ if (usb_endpoint_maxp(&udev->ep0.desc) != i) { ++ if (udev->speed == USB_SPEED_LOW || ++ !(i == 8 || i == 16 || i == 32 || i == 64)) { ++ dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i); ++ retval = -EMSGSIZE; ++ goto fail; ++ } + if (udev->speed == USB_SPEED_FULL) + dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i); + else + dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i); + usb_ep0_reinit(udev); +- } else { +- /* Initial guess is wrong and descriptor's value is invalid */ +- dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", maxp0); +- retval = -EMSGSIZE; +- goto fail; + } + +- descr = usb_get_device_descriptor(udev); +- if (IS_ERR(descr)) { +- retval = PTR_ERR(descr); ++ retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE); ++ if (retval < (signed)sizeof(udev->descriptor)) { + if (retval != -ENODEV) + dev_err(&udev->dev, "device descriptor read/all, error %d\n", + retval); +- goto fail; +- } +- if (initial) +- udev->descriptor = *descr; +- else +- *dev_descr = *descr; +- kfree(descr); +- +- /* +- * Some superspeed devices have finished the link training process +- * and attached to a superspeed hub port, but the device descriptor +- * got from those devices show they aren't superspeed devices. Warm +- * reset the port attached by the devices can fix them. +- */ +- if ((udev->speed >= USB_SPEED_SUPER) && +- (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) { +- dev_err(&udev->dev, "got a wrong device descriptor, warm reset device\n"); +- hub_port_reset(hub, port1, udev, HUB_BH_RESET_TIME, true); +- retval = -EINVAL; ++ if (retval >= 0) ++ retval = -ENOMSG; + goto fail; + } + +@@ -5124,7 +5073,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, + hub_port_disable(hub, port1, 0); + update_devnum(udev, devnum); /* for disconnect processing */ + } +- kfree(buf); + return retval; + } + +@@ -5205,7 +5153,7 @@ hub_power_remaining(struct usb_hub *hub) + + + static int descriptors_changed(struct usb_device *udev, +- struct usb_device_descriptor *new_device_descriptor, ++ struct usb_device_descriptor *old_device_descriptor, + struct usb_host_bos *old_bos) + { + int changed = 0; +@@ -5216,8 +5164,8 @@ static int descriptors_changed(struct usb_device *udev, + int length; + char *buf; + +- if (memcmp(&udev->descriptor, new_device_descriptor, +- sizeof(*new_device_descriptor)) != 0) ++ if (memcmp(&udev->descriptor, old_device_descriptor, ++ sizeof(*old_device_descriptor)) != 0) + return 1; + + if ((old_bos && !udev->bos) || (!old_bos && udev->bos)) +@@ -5394,7 +5342,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, + } + + /* reset (non-USB 3.0 devices) and get descriptor */ +- status = hub_port_init(hub, udev, port1, i, NULL); ++ status = hub_port_init(hub, udev, port1, i); + if (status < 0) + goto loop; + +@@ -5541,8 +5489,9 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, + { + struct usb_port *port_dev = hub->ports[port1 - 1]; + struct usb_device *udev = port_dev->child; +- struct usb_device_descriptor *descr; ++ struct usb_device_descriptor descriptor; + int status = -ENODEV; ++ int retval; + + dev_dbg(&port_dev->dev, "status %04x, change %04x, %s\n", portstatus, + portchange, portspeed(hub, portstatus)); +@@ -5569,20 +5518,23 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, + * changed device descriptors before resuscitating the + * device. + */ +- descr = usb_get_device_descriptor(udev); +- if (IS_ERR(descr)) { ++ descriptor = udev->descriptor; ++ retval = usb_get_device_descriptor(udev, ++ sizeof(udev->descriptor)); ++ if (retval < 0) { + dev_dbg(&udev->dev, +- "can't read device descriptor %ld\n", +- PTR_ERR(descr)); ++ "can't read device descriptor %d\n", ++ retval); + } else { +- if (descriptors_changed(udev, descr, ++ if (descriptors_changed(udev, &descriptor, + udev->bos)) { + dev_dbg(&udev->dev, + "device descriptor has changed\n"); ++ /* for disconnect() calls */ ++ udev->descriptor = descriptor; + } else { + status = 0; /* Nothing to do */ + } +- kfree(descr); + } + #ifdef CONFIG_PM + } else if (udev->state == USB_STATE_SUSPENDED && +@@ -6039,7 +5991,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) + struct usb_device *parent_hdev = udev->parent; + struct usb_hub *parent_hub; + struct usb_hcd *hcd = bus_to_hcd(udev->bus); +- struct usb_device_descriptor descriptor; ++ struct usb_device_descriptor descriptor = udev->descriptor; + struct usb_host_bos *bos; + int i, j, ret = 0; + int port1 = udev->portnum; +@@ -6075,7 +6027,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) + /* ep0 maxpacket size may change; let the HCD know about it. + * Other endpoints will be handled by re-enumeration. */ + usb_ep0_reinit(udev); +- ret = hub_port_init(parent_hub, udev, port1, i, &descriptor); ++ ret = hub_port_init(parent_hub, udev, port1, i); + if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV) + break; + } +@@ -6087,6 +6039,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) + /* Device might have changed firmware (DFU or similar) */ + if (descriptors_changed(udev, &descriptor, bos)) { + dev_info(&udev->dev, "device firmware changed\n"); ++ udev->descriptor = descriptor; /* for disconnect() calls */ + goto re_enumerate; + } + +diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c +index 077dfe48d01c1..0d2bfc909019b 100644 +--- a/drivers/usb/core/message.c ++++ b/drivers/usb/core/message.c +@@ -1041,35 +1041,40 @@ char *usb_cache_string(struct usb_device *udev, int index) + EXPORT_SYMBOL_GPL(usb_cache_string); + + /* +- * usb_get_device_descriptor - read the device descriptor +- * @udev: the device whose device descriptor should be read ++ * usb_get_device_descriptor - (re)reads the device descriptor (usbcore) ++ * @dev: the device whose device descriptor is being updated ++ * @size: how much of the descriptor to read + * + * Context: task context, might sleep. + * ++ * Updates the copy of the device descriptor stored in the device structure, ++ * which dedicates space for this purpose. ++ * + * Not exported, only for use by the core. If drivers really want to read + * the device descriptor directly, they can call usb_get_descriptor() with + * type = USB_DT_DEVICE and index = 0. + * +- * Returns: a pointer to a dynamically allocated usb_device_descriptor +- * structure (which the caller must deallocate), or an ERR_PTR value. ++ * This call is synchronous, and may not be used in an interrupt context. ++ * ++ * Return: The number of bytes received on success, or else the status code ++ * returned by the underlying usb_control_msg() call. + */ +-struct usb_device_descriptor *usb_get_device_descriptor(struct usb_device *udev) ++int usb_get_device_descriptor(struct usb_device *dev, unsigned int size) + { + struct usb_device_descriptor *desc; + int ret; + ++ if (size > sizeof(*desc)) ++ return -EINVAL; + desc = kmalloc(sizeof(*desc), GFP_NOIO); + if (!desc) +- return ERR_PTR(-ENOMEM); +- +- ret = usb_get_descriptor(udev, USB_DT_DEVICE, 0, desc, sizeof(*desc)); +- if (ret == sizeof(*desc)) +- return desc; ++ return -ENOMEM; + ++ ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size); + if (ret >= 0) +- ret = -EMSGSIZE; ++ memcpy(&dev->descriptor, desc, size); + kfree(desc); +- return ERR_PTR(ret); ++ return ret; + } + + /* +diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h +index 60363153fc3f3..69ca59841083b 100644 +--- a/drivers/usb/core/usb.h ++++ b/drivers/usb/core/usb.h +@@ -43,8 +43,8 @@ extern bool usb_endpoint_is_ignored(struct usb_device *udev, + struct usb_endpoint_descriptor *epd); + extern int usb_remove_device(struct usb_device *udev); + +-extern struct usb_device_descriptor *usb_get_device_descriptor( +- struct usb_device *udev); ++extern int usb_get_device_descriptor(struct usb_device *dev, ++ unsigned int size); + extern int usb_set_isoch_delay(struct usb_device *dev); + extern int usb_get_bos_descriptor(struct usb_device *dev); + extern void usb_release_bos_descriptor(struct usb_device *dev); +-- +2.34.1 + diff --git a/buildroot-external/patches/linux-headers/6.6.31 b/buildroot-external/patches/linux-headers/6.6.31 new file mode 120000 index 0000000000..c313fab128 --- /dev/null +++ b/buildroot-external/patches/linux-headers/6.6.31 @@ -0,0 +1 @@ +../linux/6.6.31 \ No newline at end of file diff --git a/buildroot-external/patches/linux/0002-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch b/buildroot-external/patches/linux/6.6.31/0002-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch similarity index 93% rename from buildroot-external/patches/linux/0002-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch rename to buildroot-external/patches/linux/6.6.31/0002-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch index dd7bfa7852..0a9221b3a4 100644 --- a/buildroot-external/patches/linux/0002-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch +++ b/buildroot-external/patches/linux/6.6.31/0002-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch @@ -1,4 +1,4 @@ -From 85cfbef1cf29aba24abe21409b180b7bea76e562 Mon Sep 17 00:00:00 2001 +From f9037c133775498d0ff2f035a957ce4f294e4e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= Date: Wed, 6 Mar 2024 13:25:41 +0100 Subject: [PATCH] Revert USB core changes causing issues with Z-Wave.me UZB @@ -27,10 +27,10 @@ Workaround for issues described on GH [1] and reported in [2]. Signed-off-by: Jan Čermák --- drivers/usb/core/hcd.c | 10 +- - drivers/usb/core/hub.c | 335 ++++++++++++++++--------------------- + drivers/usb/core/hub.c | 336 ++++++++++++++++--------------------- drivers/usb/core/message.c | 29 ++-- drivers/usb/core/usb.h | 4 +- - 4 files changed, 166 insertions(+), 212 deletions(-) + 4 files changed, 166 insertions(+), 213 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 12b6dfeaf658c..d895f6ebbc400 100644 @@ -65,10 +65,10 @@ index 12b6dfeaf658c..d895f6ebbc400 100644 if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) { retval = usb_get_bos_descriptor(usb_dev); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 71635dfa741d2..b937bf8b6b3d3 100644 +index 1ba3feb5e1900..ef1d63537a9b7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c -@@ -4722,67 +4722,6 @@ static int hub_enable_device(struct usb_device *udev) +@@ -4742,67 +4742,6 @@ static int hub_enable_device(struct usb_device *udev) return hcd->driver->enable_device(hcd, udev); } @@ -136,7 +136,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 /* Reset device, (re)assign address, get device descriptor. * Device connection must be stable, no more debouncing needed. * Returns device in USB_STATE_ADDRESS, except on error. -@@ -4792,17 +4731,10 @@ static int get_bMaxPacketSize0(struct usb_device *udev, +@@ -4812,17 +4751,10 @@ static int get_bMaxPacketSize0(struct usb_device *udev, * the port lock. For a newly detected device that is not accessible * through any global pointers, it's not necessary to lock the device, * but it is still necessary to lock the port. @@ -155,7 +155,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 { struct usb_device *hdev = hub->hdev; struct usb_hcd *hcd = bus_to_hcd(hdev->bus); -@@ -4814,13 +4746,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, +@@ -4834,13 +4766,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, int devnum = udev->devnum; const char *driver_name; bool do_new_scheme; @@ -169,7 +169,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 /* root hub ports have a slightly longer reset period * (from USB 2.0 spec, section 7.1.7.5) -@@ -4853,31 +4778,31 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, +@@ -4873,31 +4798,31 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, } oldspeed = udev->speed; @@ -225,7 +225,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 } speed = usb_speed_string(udev->speed); -@@ -4897,24 +4822,22 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, +@@ -4917,24 +4842,22 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, if (udev->speed < USB_SPEED_SUPER) dev_info(&udev->dev, "%s %s USB device number %d using %s\n", @@ -263,7 +263,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 } /* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way? -@@ -4938,6 +4861,9 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, +@@ -4958,6 +4881,9 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, } if (do_new_scheme) { @@ -273,7 +273,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 retval = hub_enable_device(udev); if (retval < 0) { dev_err(&udev->dev, -@@ -4946,14 +4872,52 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, +@@ -4966,14 +4892,52 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, goto fail; } @@ -333,7 +333,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 retval = hub_port_reset(hub, port1, udev, delay, false); if (retval < 0) /* error or disconnect */ -@@ -4964,13 +4928,14 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, +@@ -4984,13 +4948,14 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, retval = -ENODEV; goto fail; } @@ -352,7 +352,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 } for (operations = 0; operations < SET_ADDRESS_TRIES; ++operations) { -@@ -5011,21 +4976,18 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, +@@ -5031,21 +4996,18 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, if (do_new_scheme) break; @@ -379,7 +379,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 delay = udev->parent->hub_delay; udev->hub_delay = min_t(u32, delay, -@@ -5044,62 +5006,48 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, +@@ -5064,62 +5026,48 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, goto fail; /* @@ -472,7 +472,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 goto fail; } -@@ -5124,7 +5073,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, +@@ -5145,7 +5093,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, hub_port_disable(hub, port1, 0); update_devnum(udev, devnum); /* for disconnect processing */ } @@ -480,7 +480,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 return retval; } -@@ -5205,7 +5153,7 @@ hub_power_remaining(struct usb_hub *hub) +@@ -5226,7 +5173,7 @@ hub_power_remaining(struct usb_hub *hub) static int descriptors_changed(struct usb_device *udev, @@ -489,7 +489,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 struct usb_host_bos *old_bos) { int changed = 0; -@@ -5216,8 +5164,8 @@ static int descriptors_changed(struct usb_device *udev, +@@ -5237,8 +5184,8 @@ static int descriptors_changed(struct usb_device *udev, int length; char *buf; @@ -500,7 +500,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 return 1; if ((old_bos && !udev->bos) || (!old_bos && udev->bos)) -@@ -5394,7 +5342,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, +@@ -5415,7 +5362,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, } /* reset (non-USB 3.0 devices) and get descriptor */ @@ -509,7 +509,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 if (status < 0) goto loop; -@@ -5541,8 +5489,9 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, +@@ -5562,8 +5509,9 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, { struct usb_port *port_dev = hub->ports[port1 - 1]; struct usb_device *udev = port_dev->child; @@ -520,7 +520,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 dev_dbg(&port_dev->dev, "status %04x, change %04x, %s\n", portstatus, portchange, portspeed(hub, portstatus)); -@@ -5569,20 +5518,23 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, +@@ -5590,20 +5538,23 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, * changed device descriptors before resuscitating the * device. */ @@ -550,7 +550,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 } #ifdef CONFIG_PM } else if (udev->state == USB_STATE_SUSPENDED && -@@ -6039,7 +5991,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) +@@ -6060,7 +6011,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) struct usb_device *parent_hdev = udev->parent; struct usb_hub *parent_hub; struct usb_hcd *hcd = bus_to_hcd(udev->bus); @@ -559,7 +559,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 struct usb_host_bos *bos; int i, j, ret = 0; int port1 = udev->portnum; -@@ -6075,7 +6027,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) +@@ -6096,7 +6047,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) /* ep0 maxpacket size may change; let the HCD know about it. * Other endpoints will be handled by re-enumeration. */ usb_ep0_reinit(udev); @@ -568,7 +568,7 @@ index 71635dfa741d2..b937bf8b6b3d3 100644 if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV) break; } -@@ -6087,6 +6039,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) +@@ -6108,6 +6059,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) /* Device might have changed firmware (DFU or similar) */ if (descriptors_changed(udev, &descriptor, bos)) { dev_info(&udev->dev, "device firmware changed\n"); @@ -648,6 +648,3 @@ index 60363153fc3f3..69ca59841083b 100644 extern int usb_set_isoch_delay(struct usb_device *dev); extern int usb_get_bos_descriptor(struct usb_device *dev); extern void usb_release_bos_descriptor(struct usb_device *dev); --- -2.34.1 - From 7d667716776387e7e04c2319c8af7a3c61d4f4b8 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Mon, 20 May 2024 23:19:47 +0200 Subject: [PATCH 3/6] add potential fix for HmIP-ESI input field precision issue since 3.75.7 (this refs #2712) --- .../0119-WebUI-Fix-ProofAndSetValue.patch | 22 +- .../www/config/easymodes/etc/uiElements.tcl | 254 ++++++++++++++++-- .../config/easymodes/etc/uiElements.tcl.orig | 254 ++++++++++++++++-- 3 files changed, 488 insertions(+), 42 deletions(-) diff --git a/buildroot-external/patches/occu/0119-WebUI-Fix-ProofAndSetValue.patch b/buildroot-external/patches/occu/0119-WebUI-Fix-ProofAndSetValue.patch index d4f618ad8f..95dc1bf2e0 100644 --- a/buildroot-external/patches/occu/0119-WebUI-Fix-ProofAndSetValue.patch +++ b/buildroot-external/patches/occu/0119-WebUI-Fix-ProofAndSetValue.patch @@ -161,7 +161,16 @@ default {return "max value not available"} } } -@@ -163,7 +173,7 @@ +@@ -82,7 +92,7 @@ + + # Limit float to 1 decimal places + if {([llength [split $min "."]] == 2) || ([llength [split $max "."]] == 2)} { +- if {$param != "METER_CONSTANT_VOLUME"} { ++ if {($param != "METER_CONSTANT_VOLUME") && ($param != "METER_CONSTANT_ENERGY")} { + set min [format {%1.1f} $min] + set max [format {%1.1f} $max] + } else { +@@ -178,7 +188,7 @@ hmip-usbsm { if {$param == "TX_THRESHOLD_POWER"} {return "W (0.0 - [getUserDefinedMaxValue $devType $param])"} @@ -170,7 +179,16 @@ } default {return "missing description"} } -@@ -298,7 +308,7 @@ +@@ -256,7 +266,7 @@ + + # Limit float to 2 decimal places + if {[llength [split $value "."]] == 2} { +- if {$param != "METER_CONSTANT_VOLUME"} { ++ if {($param != "METER_CONSTANT_VOLUME") && ($param != "METER_CONSTANT_ENERGY")} { + catch {set value [format {%1.1f} $value]} + } else { + catch {set value [format {%1.2f} $value]} +@@ -339,7 +349,7 @@ } set s "3/Imp" + } + + if {[string equal $param "METER_CONSTANT_ENERGY"] == 1} { + set unit "Imp/kWh" + } + return "$unit" } @@ -179,7 +194,7 @@ proc getUserDefinedCondTXThresholdUnitMinMaxDescr {devType param} { } } -proc getTextField {param value chn prn {extraparam ""}} { +proc getTextField {param value chn prn {extraparam ""} {superExtra ""}} { # exec echo "getTextField: $extraparam" >> /tmp/textField.log @@ -191,6 +206,8 @@ proc getTextField {param value chn prn {extraparam ""}} { array set param_descr $descr($param) set minValue $param_descr(MIN) set maxValue $param_descr(MAX) + set maxLength "" + set sizeTextfield 5 if {[string first "." $param_descr(MIN)] != -1} { set minValue [format {%1.1f} $minValue] @@ -213,10 +230,20 @@ proc getTextField {param value chn prn {extraparam ""}} { } } - if {[string equal $dev_descr(TYPE) "HmIPW-WGD"] == 1} { + if {([string equal $dev_descr(TYPE) "HmIPW-WGD"] == 1) || ([string equal $dev_descr(TYPE) "HmIPW-WGD-PL"] == 1)} { if {$param == "MAIN_TEXT" || $param == "SUB_TEXT"} { set minValue "stringUTF8" set maxValue "stringUTF8" + set maxLength "maxLength=16" + } + } + + if {([string equal $dev_descr(TYPE) "HmIP-ESI"] == 1)} { + if {$param == "METER_OBIS_SEARCH_STRING"} { + set minValue "stringUTF8" + set maxValue "stringUTF8" + set maxLength "maxLength=16" + set sizeTextfield 16 } } @@ -225,11 +252,25 @@ proc getTextField {param value chn prn {extraparam ""}} { if {$param == "CALIBRATION_PPM_VAL"} {set maxValue 10000} } +set comment { + if {$param == "DIM_LEVEL_LOWEST"} { + set onMinLevel [expr $extraparam * 1.0] + if {($onMinLevel < 0.5)} { + set minValue $minValue + } else { + set minValue $onMinLevel + } + } +} set elemId 'separate_CHANNEL\_$chn\_$prn' # Limit float to 2 decimal places if {[llength [split $value "."]] == 2} { - set value [format {%1.1f} $value] + if {($param != "METER_CONSTANT_VOLUME") && ($param != "METER_CONSTANT_ENERGY")} { + catch {set value [format {%1.1f} $value]} + } else { + catch {set value [format {%1.2f} $value]} + } } # Convert float to int - sometimes the parameter UTC_* comes as float instead of int (for whatever reason). This will cause an error. @@ -244,7 +285,7 @@ proc getTextField {param value chn prn {extraparam ""}} { if {$param == "TRIGGER_ANGLE" && [info exists descr(TRIGGER_ANGLE_2)] == 1} { upvar valTriggerAngle2 triggerAngle2 - set s "" + set s "" cgi_javascript { puts "var maxTriggerAngle = parseInt($maxValue), minTriggerAngle = parseInt($minValue);" puts { @@ -275,13 +316,13 @@ proc getTextField {param value chn prn {extraparam ""}} { } } else { if {$param == "NUMERIC_PIN_CODE"} { - set s "" + set s "" } elseif {($param == "VOLTAGE_0") || ($param == "VOLTAGE_100")} { - set s "" + set s "" } elseif {$minValue == "stringUTF8"} { - set s "" + set s "" } else { - set s "" + set s "" } } @@ -396,7 +437,7 @@ proc getButtonChannelConfiguration {{extraDescription ""}} { return $html } -proc getDeactivateLongKeypress {p profile special_input_id prn {optionDisable 0} {optionEnable 1}} { +proc getDeactivateLongKeypress {p profile special_input_id prn {optionDisable 0} {optionEnable 1} {callback ""}} { upvar $profile PROFILE upvar $p ps upvar pref pref @@ -415,7 +456,7 @@ proc getDeactivateLongKeypress {p profile special_input_id prn {optionDisable 0} array_clear options set options($optionDisable) "\${optionDisable}" set options($optionEnable) "\${optionEnable}" - append html "[get_ComboBox options $param ${special_input_id}_$prn\_$pref PROFILE $param]" + append html "[get_ComboBox options $param ${special_input_id}_$prn\_$pref PROFILE $param $callback]" append html "" } return $html @@ -483,7 +524,10 @@ proc getHelpIcon {topic {x 0} {y 0}} { "COND_TX_DECISION_ABOVE_BELOW" {set x 450; set y 80} "CONTACT_BOOST" {set x 450; set y 180} "DELAY_COMPENSATION" {set x 450; set y 100} + "DEVICE_OPERATION_MODE_RGBW" {set x 650; set y 200} "DEVICE_SENSOR_SENSITIVITY" {set x 450; set y 180} + "DIM_LEVEL_HIGHEST" {set x 450; set y 55} + "DIM_LEVEL_LOWEST" {set x 450; set y 125} "DIM_STEP" {set x 500; set y 150} "DISABLE_DEVICE_ALIVE_SIGNAL" {set x 500; set y 75 } "DURATION_5MIN" {set x 500; set y 160} @@ -494,16 +538,19 @@ proc getHelpIcon {topic {x 0} {y 0}} { "HEATING_COOLING" {set x 450; set y 160} "HUMIDITY_LIMIT_DISABLE" {set x 500; set y 200} "HUMIDITY_LIMIT_VALUE" {set x 450; set y 85} + "INPUT_COPRO_ENABLED" {set x 500; set y 250} "LOCAL_RESET_DISABLED" {set x 500; set y 130} "MOUNTING_ORIENTATION" {set x 450; set y 75} "MOUNTING_ORIENTATION_A" {set x 450; set y 75} "ON_MIN_LEVEL" {set x 400; set y 80} "OPTIMUM_START_STOP" {set x 450; set y 80} "PSM_CHANNEL_OPERATION_MODE" {set x 450; set y 100} + "PYRO_CHANNEL_OPERATION_MODE" {set x 500; set y 375} "OUTPUT_SWAP" {set x 450; set y 100} "OUTPUT_SWAP_SERVO" {set x 450; set y 50} "PERMANENT_FULL_RX" {set x 500; set y 160} "PIR_SENSITIVITY" {set x 500; set y 210} + "POWERUP_JUMPTARGET_RGBW" {set x 450; set y 75} "PWM_AT_LOW_VALVE_POSITION" {set x 500; set y 130} "REPEAT_ENABLE" {set x 500; set y 210} "ROUTER_MODULE_ENABLED" {set x 500; set y 120} @@ -563,7 +610,8 @@ proc getTimeSelector {paramDescr p profile type prn special_input_id timebase op set paramBaseDescr "SERVO_SPEED_UNIT" set paramFactorDescr "SERVO_SPEED_FACTOR" } - set javascriptDelay 100 + + set javascriptDelay 10 incr pref append html "" @@ -761,7 +809,7 @@ proc getPowerUpSelector {chn p special_input_id} { append html "" append html "
" - append html "" + append html "" } ### @@ -951,7 +999,7 @@ proc getPowerUpSelector {chn p special_input_id} { append html "" append html "
" - append html "" + append html "" } ### @@ -964,7 +1012,7 @@ proc getPowerUpSelector {chn p special_input_id} { append html "[getOptionBox '$param' options $ps($param) $chn $prn]" append html "" } -} + } append html "" } # ******* @@ -1101,7 +1149,7 @@ proc getPowerUpSelectorAcousticSignal {chn p special_input_id} { append html "" append html "
" - append html "" + append html "" } ### @@ -1648,6 +1696,172 @@ proc getPowerUpSelectorShutterBlind {chn p special_input_id model} { return $html } +proc getPowerUpSelectorUniversalLightReceiver {chn p special_input_id mode {isDALI 0}} { + + # isDALI should be 1 for the HmIP-DRG-DALI + + global psDescr dev_descr ch_descr + upvar psDescr psDescr + upvar $p ps + upvar prn prn + + set chType $ch_descr(TYPE) + set specialID "[getSpecialID $special_input_id]" + set html "" + + set param POWERUP_JUMPTARGET + incr prn + set powerupModePrn $prn + append html "" + append html "\${stringTableDimmerPowerUpAction}" + option POWERUP_JUMPTARGET_HMIP + append html "[getOptionBox '$param' options $ps($param) $chn $prn "onchange=\"powerUP_showRelevantData($chn, this.value,$prn);\""] [getHelpIcon $param\_RGBW]" + append html "" + + append html "" + + set param POWERUP_ON_LEVEL + if { [info exists ps($param)] == 1 } { + incr prn + append html "" + if {$mode == 0} { + # The actor acts as switch actor (ON/OFF). Here we set the ON value to 100%. This is invisible for the user. + append html "" + } else { + append html "" + option RAW_0_100Percent + append html "" + } + append html "" + } + + set param POWERUP_ONDELAY_UNIT + if { [info exists ps($param)] == 1 } { + incr prn + append html "" + append html "" + append html [getComboBox $chn $prn "$specialID" "delay"] + append html "" + + append html [getTimeUnitComboBox $param $ps($param) $chn $prn $special_input_id] + + incr prn + set param POWERUP_ONDELAY_VALUE + append html "" + append html "" + + append html "" + + append html "" + append html "" + append html "" + } + + set param POWERUP_ONTIME_UNIT + if { [info exists ps($param)] == 1 } { + incr prn + append html "" + append html "" + append html [getComboBox $chn $prn "$specialID" "timeOnOff"] + append html "" + + append html [getTimeUnitComboBox $param $ps($param) $chn $prn $special_input_id] + + incr prn + set param POWERUP_ONTIME_VALUE + append html "" + append html "" + + append html "" + + append html "" + append html "" + append html "" + } + + set param POWERUP_ON_COLOR_TEMPERATURE + # mode 2 = DIMMER_TUNABLE_WHITE + # The RGB mode (mode 3) of the DALI device is capable of TUNABLE_WHITE - the HmIP-RGBW is not. + # mode 5 = HmIP-LSC + if { ([info exists ps($param)] == 1) && (($mode == 2) || ($mode == 5) || (($isDALI == 1) && ($mode == 3))) } { + incr prn + append html "" + append html "" + append html "" + append html "" + } + + set param POWERUP_ON_HUE + # mode 3 = DIMMER_RGB - mode 4 = DIMMER_RGBW mode5 = HmIP-LSC + if { ([info exists ps($param)] == 1) && (($mode == 3) || ($mode == 4) || ($mode == 5)) } { + incr prn + append html "" + append html "" + append html "" + append html "" + } + + # The device documentations describes this parameter as POWERUP_ON_LEVEL_2 + set param POWERUP_ON_SATURATION + if { ([info exists ps($param)] == 1) && (($mode == 3) || ($mode == 4) || ($mode == 5)) } { + incr prn + append html "" + append html "" + append html "" + append html "" + } + + append html "
\${lblPowerUpOnLevel}[getOptionBox '$param' options $ps($param) $chn $prn]
\${stringTableOnDelay}
\${stringTableOnDelayValue}[getTextField $param $ps($param) $chn $prn] [getMinMaxValueDescr $param]

\${stringTableOnTime}
\${stringTableOnTimeValue}[getTextField $param $ps($param) $chn $prn] [getMinMaxValueDescr $param]

\${lblPowerUpOnColorTemperature}[getTextField $param $ps($param) $chn $prn] [getMinMaxValueDescr $param] [getUnit $param] [getHelpIcon $param\_RGBW 450 75]
\${lblPowerUpOnHue}[getTextField $param $ps($param) $chn $prn] [getMinMaxValueDescr $param] [getHelpIcon $param 450 75]
\${lblPowerUpOnSaturation}[getTextField $param $ps($param) $chn $prn] [getMinMaxValueDescr $param] [getHelpIcon $param 450 75]
" + + ### JS ### + + append html "" + + return $html +} + proc addHintHeatingGroupDevice {address} { append html "" + append html "" } ### @@ -941,7 +989,7 @@ proc getPowerUpSelector {chn p special_input_id} { append html "" append html "
" - append html "" + append html "" } ### @@ -954,7 +1002,7 @@ proc getPowerUpSelector {chn p special_input_id} { append html "[getOptionBox '$param' options $ps($param) $chn $prn]" append html "" } -} + } append html "" } # ******* @@ -1091,7 +1139,7 @@ proc getPowerUpSelectorAcousticSignal {chn p special_input_id} { append html "" append html "
" - append html "" + append html "" } ### @@ -1638,6 +1686,172 @@ proc getPowerUpSelectorShutterBlind {chn p special_input_id model} { return $html } +proc getPowerUpSelectorUniversalLightReceiver {chn p special_input_id mode {isDALI 0}} { + + # isDALI should be 1 for the HmIP-DRG-DALI + + global psDescr dev_descr ch_descr + upvar psDescr psDescr + upvar $p ps + upvar prn prn + + set chType $ch_descr(TYPE) + set specialID "[getSpecialID $special_input_id]" + set html "" + + set param POWERUP_JUMPTARGET + incr prn + set powerupModePrn $prn + append html "" + append html "\${stringTableDimmerPowerUpAction}" + option POWERUP_JUMPTARGET_HMIP + append html "[getOptionBox '$param' options $ps($param) $chn $prn "onchange=\"powerUP_showRelevantData($chn, this.value,$prn);\""] [getHelpIcon $param\_RGBW]" + append html "" + + append html "" + + set param POWERUP_ON_LEVEL + if { [info exists ps($param)] == 1 } { + incr prn + append html "" + if {$mode == 0} { + # The actor acts as switch actor (ON/OFF). Here we set the ON value to 100%. This is invisible for the user. + append html "" + } else { + append html "" + option RAW_0_100Percent + append html "" + } + append html "" + } + + set param POWERUP_ONDELAY_UNIT + if { [info exists ps($param)] == 1 } { + incr prn + append html "" + append html "" + append html [getComboBox $chn $prn "$specialID" "delay"] + append html "" + + append html [getTimeUnitComboBox $param $ps($param) $chn $prn $special_input_id] + + incr prn + set param POWERUP_ONDELAY_VALUE + append html "" + append html "" + + append html "" + + append html "" + append html "" + append html "" + } + + set param POWERUP_ONTIME_UNIT + if { [info exists ps($param)] == 1 } { + incr prn + append html "" + append html "" + append html [getComboBox $chn $prn "$specialID" "timeOnOff"] + append html "" + + append html [getTimeUnitComboBox $param $ps($param) $chn $prn $special_input_id] + + incr prn + set param POWERUP_ONTIME_VALUE + append html "" + append html "" + + append html "" + + append html "" + append html "" + append html "" + } + + set param POWERUP_ON_COLOR_TEMPERATURE + # mode 2 = DIMMER_TUNABLE_WHITE + # The RGB mode (mode 3) of the DALI device is capable of TUNABLE_WHITE - the HmIP-RGBW is not. + # mode 5 = HmIP-LSC + if { ([info exists ps($param)] == 1) && (($mode == 2) || ($mode == 5) || (($isDALI == 1) && ($mode == 3))) } { + incr prn + append html "" + append html "" + append html "" + append html "" + } + + set param POWERUP_ON_HUE + # mode 3 = DIMMER_RGB - mode 4 = DIMMER_RGBW mode5 = HmIP-LSC + if { ([info exists ps($param)] == 1) && (($mode == 3) || ($mode == 4) || ($mode == 5)) } { + incr prn + append html "" + append html "" + append html "" + append html "" + } + + # The device documentations describes this parameter as POWERUP_ON_LEVEL_2 + set param POWERUP_ON_SATURATION + if { ([info exists ps($param)] == 1) && (($mode == 3) || ($mode == 4) || ($mode == 5)) } { + incr prn + append html "" + append html "" + append html "" + append html "" + } + + append html "
\${lblPowerUpOnLevel}[getOptionBox '$param' options $ps($param) $chn $prn]
\${stringTableOnDelay}
\${stringTableOnDelayValue}[getTextField $param $ps($param) $chn $prn] [getMinMaxValueDescr $param]

\${stringTableOnTime}
\${stringTableOnTimeValue}[getTextField $param $ps($param) $chn $prn] [getMinMaxValueDescr $param]

\${lblPowerUpOnColorTemperature}[getTextField $param $ps($param) $chn $prn] [getMinMaxValueDescr $param] [getUnit $param] [getHelpIcon $param\_RGBW 450 75]
\${lblPowerUpOnHue}[getTextField $param $ps($param) $chn $prn] [getMinMaxValueDescr $param] [getHelpIcon $param 450 75]
\${lblPowerUpOnSaturation}[getTextField $param $ps($param) $chn $prn] [getMinMaxValueDescr $param] [getHelpIcon $param 450 75]
" + + ### JS ### + + append html "" + + return $html +} + proc addHintHeatingGroupDevice {address} { append html "