diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/.bumpversion.cfg checkbox-support-0.51.0~ppa~ubuntu21.10.1/.bumpversion.cfg --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/.bumpversion.cfg 2021-05-27 06:47:04.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/.bumpversion.cfg 2021-07-12 15:29:05.000000000 +0000 @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.50.0 +current_version = 0.51.0 parse = (?P\d+)\.(?P\d+)(\.(?P\d+))?((?P\.?[a-z]+)(?P\d+))? serialize = {major}.{minor}.{patch}{release}{N} diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/parsers/tests/test_udevadm.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/parsers/tests/test_udevadm.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/parsers/tests/test_udevadm.py 2021-05-27 06:47:04.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/parsers/tests/test_udevadm.py 2021-07-12 15:29:05.000000000 +0000 @@ -1053,6 +1053,11 @@ self.assertEqual(len(devices), 107) self.assertEqual(self.count(devices, "CDROM"), 0) + def test_CRYPTO_FDE_UC20(self): + devices = self.parse("CRYPTO_FDE", with_partitions=True) + self.assertEqual(len(devices), 93) + self.assertEqual(self.count(devices, "PARTITION"), 1) + def verify_devices(self, devices, expected_device_list): """ Verify we have the expected quantity of each device given in the list, diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/parsers/tests/udevadm_data/CRYPTO_FDE.lsblk checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/parsers/tests/udevadm_data/CRYPTO_FDE.lsblk --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/parsers/tests/udevadm_data/CRYPTO_FDE.lsblk 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/parsers/tests/udevadm_data/CRYPTO_FDE.lsblk 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,44 @@ +KNAME="loop0" TYPE="loop" MOUNTPOINT="/snap/core20/975" +KNAME="loop1" TYPE="loop" MOUNTPOINT="/snap/pc-kernel/761" +KNAME="loop2" TYPE="loop" MOUNTPOINT="/snap/bluez/258" +KNAME="loop3" TYPE="loop" MOUNTPOINT="/snap/core/10958" +KNAME="loop4" TYPE="loop" MOUNTPOINT="/snap/core/11081" +KNAME="loop5" TYPE="loop" MOUNTPOINT="/snap/everactive-apex-gadget/57" +KNAME="loop6" TYPE="loop" MOUNTPOINT="/snap/everactive-evernet/14" +KNAME="loop7" TYPE="loop" MOUNTPOINT="/snap/core18/1997" +KNAME="loop8" TYPE="loop" MOUNTPOINT="/snap/everactive-cloud-connector/11" +KNAME="loop9" TYPE="loop" MOUNTPOINT="/snap/everactive-iot-agent/4" +KNAME="loop10" TYPE="loop" MOUNTPOINT="/snap/everactive-gateway-controller/52" +KNAME="loop11" TYPE="loop" MOUNTPOINT="/snap/everactive-firmware-sensor-radio/11" +KNAME="loop12" TYPE="loop" MOUNTPOINT="/snap/everactive-evernet/41" +KNAME="loop13" TYPE="loop" MOUNTPOINT="/snap/everactive-ufw/6" +KNAME="loop14" TYPE="loop" MOUNTPOINT="/snap/everactive-firmware-mc/9" +KNAME="loop15" TYPE="loop" MOUNTPOINT="/snap/network-manager/645" +KNAME="loop16" TYPE="loop" MOUNTPOINT="/snap/everactive-gateway-services/18" +KNAME="loop17" TYPE="loop" MOUNTPOINT="/snap/everactive-psiclone/15" +KNAME="loop18" TYPE="loop" MOUNTPOINT="/snap/everactive-dnsmasq/13" +KNAME="loop19" TYPE="loop" MOUNTPOINT="/snap/everactive-gateway-essentials/47" +KNAME="loop20" TYPE="loop" MOUNTPOINT="/snap/everactive-gateway-services/42" +KNAME="loop21" TYPE="loop" MOUNTPOINT="/snap/everactive-gateway-base/20" +KNAME="loop22" TYPE="loop" MOUNTPOINT="/snap/everactive-psiclone/54" +KNAME="loop23" TYPE="loop" MOUNTPOINT="/snap/checkbox-staunton/9" +KNAME="loop24" TYPE="loop" MOUNTPOINT="/snap/modem-manager/454" +KNAME="loop25" TYPE="loop" MOUNTPOINT="/snap/everactive-chrony/6" +KNAME="loop26" TYPE="loop" MOUNTPOINT="/snap/network-manager/660" +KNAME="loop27" TYPE="loop" MOUNTPOINT="/snap/everactive-nats/4" +KNAME="loop28" TYPE="loop" MOUNTPOINT="/snap/everactive-firmware-utilities/11" +KNAME="loop29" TYPE="loop" MOUNTPOINT="/snap/snapd/11588" +KNAME="loop30" TYPE="loop" MOUNTPOINT="/snap/snapd/11841" +KNAME="loop31" TYPE="loop" MOUNTPOINT="/snap/checkbox20/497" +KNAME="mmcblk0" TYPE="disk" MOUNTPOINT="" +KNAME="mmcblk0p1" TYPE="part" MOUNTPOINT="" +KNAME="mmcblk0p2" TYPE="part" MOUNTPOINT="/run/mnt/ubuntu-seed" +KNAME="mmcblk0p3" TYPE="part" MOUNTPOINT="/run/mnt/ubuntu-boot" +KNAME="mmcblk0p4" TYPE="part" MOUNTPOINT="" +KNAME="mmcblk0p5" TYPE="part" MOUNTPOINT="" +KNAME="mmcblk0boot0" TYPE="disk" MOUNTPOINT="" +KNAME="mmcblk0boot1" TYPE="disk" MOUNTPOINT="" +KNAME="mmcblk1" TYPE="disk" MOUNTPOINT="" +KNAME="mmcblk1p1" TYPE="part" MOUNTPOINT="" +KNAME="dm-0" TYPE="crypt" MOUNTPOINT="/run/mnt/base/writable" +KNAME="dm-1" TYPE="crypt" MOUNTPOINT="/run/mnt/ubuntu-save" diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/parsers/tests/udevadm_data/CRYPTO_FDE.txt checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/parsers/tests/udevadm_data/CRYPTO_FDE.txt --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/parsers/tests/udevadm_data/CRYPTO_FDE.txt 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/parsers/tests/udevadm_data/CRYPTO_FDE.txt 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,7101 @@ +P: /devices/LNXSYSTM:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:LNXSYSTM: +E: USEC_INITIALIZED=13907495 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXCPU:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXCPU:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:LNXCPU: +E: USEC_INITIALIZED=13912191 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXCPU:01 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXCPU:01 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:LNXCPU: +E: USEC_INITIALIZED=13913654 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXCPU:02 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXCPU:02 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:LNXCPU: +E: USEC_INITIALIZED=13917138 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXCPU:03 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXCPU:03 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:LNXCPU: +E: USEC_INITIALIZED=13915716 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:LNXSYBUS: +E: USEC_INITIALIZED=13912184 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00 +E: SUBSYSTEM=acpi +E: DRIVER=ac +E: MODALIAS=acpi:ACPI0003: +E: USEC_INITIALIZED=13943047 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/ADP1 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/ADP1 +E: SUBSYSTEM=power_supply +E: POWER_SUPPLY_NAME=ADP1 +E: POWER_SUPPLY_ONLINE=1 + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/ADP1/hwmon0 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/ADP1/hwmon0 +E: SUBSYSTEM=hwmon + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/ADP1/wakeup22 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/ADP1/wakeup22 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/INT33A1:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/INT33A1:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:INT33A1:PNP0D80: +E: USEC_INITIALIZED=13939965 +E: ID_VENDOR_FROM_DATABASE=Interphase Corporation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:INT3452:INT3452: +E: USEC_INITIALIZED=13935718 +E: ID_VENDOR_FROM_DATABASE=Interphase Corporation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:00/wakeup/wakeup31 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:00/wakeup/wakeup31 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:01 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:01 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:INT3452:INT3452: +E: USEC_INITIALIZED=13941105 +E: ID_VENDOR_FROM_DATABASE=Interphase Corporation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:01/wakeup/wakeup32 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:01/wakeup/wakeup32 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:02 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:02 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:INT3452:INT3452: +E: USEC_INITIALIZED=13938474 +E: ID_VENDOR_FROM_DATABASE=Interphase Corporation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:02/wakeup/wakeup33 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:02/wakeup/wakeup33 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:03 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:03 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:INT3452:INT3452: +E: USEC_INITIALIZED=13936119 +E: ID_VENDOR_FROM_DATABASE=Interphase Corporation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:03/wakeup/wakeup34 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/INT3452:03/wakeup/wakeup34 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/INT34D7:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/INT34D7:00 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/MSFT0101:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/MSFT0101:00 +E: SUBSYSTEM=acpi +E: DRIVER=tpm_crb +E: MODALIAS=acpi:MSFT0101: +E: USEC_INITIALIZED=13937307 +E: ID_VENDOR_FROM_DATABASE=M-Systems Flash Disk Pioneers + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/MSFT0101:00/tpm/tpm0 +N: tpm0 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/MSFT0101:00/tpm/tpm0 +E: SUBSYSTEM=tpm +E: DEVNAME=/dev/tpm0 +E: MAJOR=10 +E: MINOR=224 + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/MSFT0101:00/tpmrm/tpmrm0 +N: tpmrm0 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/MSFT0101:00/tpmrm/tpmrm0 +E: SUBSYSTEM=tpmrm +E: DEVNAME=/dev/tpmrm0 +E: MAJOR=253 +E: MINOR=65536 + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0103:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0103:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0103: +E: USEC_INITIALIZED=13923023 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0A08:PNP0A03: +E: USEC_INITIALIZED=13924606 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00 +E: SUBSYSTEM=acpi +E: DRIVER=video +E: MODALIAS=acpi:LNXVIDEO: +E: USEC_INITIALIZED=13945588 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:01 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:01 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:02 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:02 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:03 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:03 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:04 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:04 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:05 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:05 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:06 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:06 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:07 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:07 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:08 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:08 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:09 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:09 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:0a +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:0a +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:0b +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:0b +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:0c +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:0c +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:0d +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:0d +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:0e +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:0e +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:0f +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:0f +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:10 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:10 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:11 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/device:11 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/input/input6 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/input/input6 +E: SUBSYSTEM=input +E: PRODUCT=19/0/6/0 +E: NAME="Video Bus" +E: PHYS="LNXVIDEO/video/input0" +E: PROP=0 +E: EV=3 +E: KEY=3e000b00000000 0 0 0 +E: MODALIAS=input:b0019v0000p0006e0000-e0,1,kE0,E1,E3,F1,F2,F3,F4,F5,ramlsfw +E: USEC_INITIALIZED=16950258 +E: ID_INPUT=1 +E: ID_INPUT_KEY=1 +E: ID_PATH=acpi-LNXVIDEO:00 +E: ID_PATH_TAG=acpi-LNXVIDEO_00 +E: ID_FOR_SEAT=input-acpi-LNXVIDEO_00 +E: TAGS=:seat: + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/input/input6/event6 +N: input/event6 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/input/input6/event6 +E: SUBSYSTEM=input +E: DEVNAME=/dev/input/event6 +E: MAJOR=13 +E: MINOR=70 +E: USEC_INITIALIZED=17047810 +E: ID_INPUT=1 +E: ID_INPUT_KEY=1 +E: ID_PATH=acpi-LNXVIDEO:00 +E: ID_PATH_TAG=acpi-LNXVIDEO_00 +E: TAGS=:power-switch: + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/wakeup/wakeup1 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/wakeup/wakeup1 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/PNP0C02:01 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/PNP0C02:01 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0C02: +E: USEC_INITIALIZED=13955447 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/PNP0C0D:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/PNP0C0D:00 +E: SUBSYSTEM=acpi +E: DRIVER=button +E: MODALIAS=acpi:PNP0C0D: +E: USEC_INITIALIZED=13955170 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/PNP0C0D:00/input/input0 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/PNP0C0D:00/input/input0 +E: SUBSYSTEM=input +E: PRODUCT=19/0/5/0 +E: NAME="Lid Switch" +E: PHYS="PNP0C0D/button/input0" +E: PROP=0 +E: EV=21 +E: SW=1 +E: MODALIAS=input:b0019v0000p0005e0000-e0,5,kramlsfw0, +E: USEC_INITIALIZED=13988567 +E: ID_INPUT=1 +E: ID_INPUT_SWITCH=1 +E: ID_PATH=acpi-PNP0C0D:00 +E: ID_PATH_TAG=acpi-PNP0C0D_00 +E: ID_FOR_SEAT=input-acpi-PNP0C0D_00 +E: TAGS=:seat: + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/PNP0C0D:00/input/input0/event0 +N: input/event0 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/PNP0C0D:00/input/input0/event0 +E: SUBSYSTEM=input +E: DEVNAME=/dev/input/event0 +E: MAJOR=13 +E: MINOR=64 +E: USEC_INITIALIZED=14075657 +E: ID_INPUT=1 +E: ID_INPUT_SWITCH=1 +E: ID_PATH=acpi-PNP0C0D:00 +E: ID_PATH_TAG=acpi-PNP0C0D_00 +E: TAGS=:power-switch: + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/PNP0C0D:00/wakeup/wakeup23 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/PNP0C0D:00/wakeup/wakeup23 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/wakeup/wakeup0 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/wakeup/wakeup0 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:12 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:12 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/CGT0501:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/CGT0501:00 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/CGT0502:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/CGT0502:00 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/PNP0000:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/PNP0000:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0000: +E: USEC_INITIALIZED=13979962 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/PNP0100:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/PNP0100:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0100: +E: USEC_INITIALIZED=13976672 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/PNP0C02:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/PNP0C02:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0C02: +E: USEC_INITIALIZED=13982705 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/PNP0C09:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/PNP0C09:00 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/PNP0C09:00/PNP0C0A:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/PNP0C09:00/PNP0C0A:00 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/PNP0C09:00/PNP0C0A:01 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/PNP0C09:00/PNP0C0A:01 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/wakeup/wakeup17 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:13/wakeup/wakeup17 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:14 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:14 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:15 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:15 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:16 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:16 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:17 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:17 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:17/wakeup/wakeup2 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:17/wakeup/wakeup2 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:18 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:18 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:18/wakeup/wakeup3 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:18/wakeup/wakeup3 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:19 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:19 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1a +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1a +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1a/device:1b +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1a/device:1b +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1a/device:1c +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1a/device:1c +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1a/wakeup/wakeup4 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1a/wakeup/wakeup4 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:1f +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:1f +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:20 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:20 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:21 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:21 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:22 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:22 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:23 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:23 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:24 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:24 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:25 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:25 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:26 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:26 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:27 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:27 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:28 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:28 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:29 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:29 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:2a +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:2a +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:2b +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:2b +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:2c +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:2c +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:2d +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/device:1e/device:2d +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/wakeup/wakeup11 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1d/wakeup/wakeup11 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2e +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2e +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2f +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2f +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2f/INT343A:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2f/INT343A:00 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:30 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:30 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:30/INT34C1:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:30/INT34C1:00 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:30/NXP1001:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:30/NXP1001:00 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:31 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:31 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:32 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:32 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:32/ELAN221D:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:32/ELAN221D:00 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:33 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:33 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:34 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:34 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:35 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:35 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:36 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:36 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:36/IMPJ0003:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:36/IMPJ0003:00 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:37 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:37 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:37/BCM2EA8:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:37/BCM2EA8:00 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:37/wakeup/wakeup12 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:37/wakeup/wakeup12 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:38 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:38 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:38/BCM4752:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:38/BCM4752:00 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:38/INT3511:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:38/INT3511:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:INT3511: +E: USEC_INITIALIZED=14055949 +E: ID_VENDOR_FROM_DATABASE=Interphase Corporation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:38/wakeup/wakeup13 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:38/wakeup/wakeup13 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:39 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:39 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:39/INT3512:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:39/INT3512:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:INT3512: +E: USEC_INITIALIZED=14057285 +E: ID_VENDOR_FROM_DATABASE=Interphase Corporation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:39/wakeup/wakeup14 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:39/wakeup/wakeup14 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3a +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3a +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3b +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3b +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3b/FPNT_DIS:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3b/FPNT_DIS:00 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3c +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3c +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3d +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3d +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3e +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3e +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3e/wakeup/wakeup15 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3e/wakeup/wakeup15 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3f +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3f +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3f/device:40 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3f/device:40 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3f/wakeup/wakeup16 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3f/wakeup/wakeup16 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:41 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:41 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:41/device:42 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:41/device:42 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:43 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:43 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:43/device:44 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:43/device:44 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:43/device:45 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:43/device:45 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:46 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:46 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:46/device:47 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:46/device:47 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:46/device:47/wakeup/wakeup19 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:46/device:47/wakeup/wakeup19 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:46/device:48 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:46/device:48 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:46/wakeup/wakeup7 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:46/wakeup/wakeup7 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:49 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:49 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:49/device:4a +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:49/device:4a +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:49/device:4a/wakeup/wakeup20 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:49/device:4a/wakeup/wakeup20 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:49/device:4b +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:49/device:4b +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:49/wakeup/wakeup9 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:49/wakeup/wakeup9 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d/wakeup/wakeup18 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d/wakeup/wakeup18 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/wakeup/wakeup5 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/wakeup/wakeup5 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e/device:4f +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e/device:4f +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:50 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:50 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:50/device:51 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:50/device:51 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:52 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:52 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:52/device:53 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:52/device:53 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:54 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:54 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/wakeup/wakeup21 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/wakeup/wakeup21 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0B00:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0B00:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0B00: +E: USEC_INITIALIZED=13932186 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0A:02 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0A:02 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0A:03 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0A:03 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0A:04 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0A:04 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0A:05 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0A:05 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00 +E: SUBSYSTEM=acpi +E: DRIVER=button +E: MODALIAS=acpi:PNP0C0C: +E: USEC_INITIALIZED=13941362 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/input/input1 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/input/input1 +E: SUBSYSTEM=input +E: PRODUCT=19/0/1/0 +E: NAME="Power Button" +E: PHYS="PNP0C0C/button/input0" +E: PROP=0 +E: EV=3 +E: KEY=10000000000000 0 +E: MODALIAS=input:b0019v0000p0001e0000-e0,1,k74,ramlsfw +E: USEC_INITIALIZED=14076908 +E: ID_INPUT=1 +E: ID_INPUT_KEY=1 +E: ID_PATH=acpi-PNP0C0C:00 +E: ID_PATH_TAG=acpi-PNP0C0C_00 +E: ID_FOR_SEAT=input-acpi-PNP0C0C_00 +E: TAGS=:seat: + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/input/input1/event1 +N: input/event1 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/input/input1/event1 +E: SUBSYSTEM=input +E: DEVNAME=/dev/input/event1 +E: MAJOR=13 +E: MINOR=65 +E: USEC_INITIALIZED=14172189 +E: ID_INPUT=1 +E: ID_INPUT_KEY=1 +E: ID_PATH=acpi-PNP0C0C:00 +E: ID_PATH_TAG=acpi-PNP0C0C_00 +E: TAGS=:power-switch: + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/wakeup/wakeup24 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/wakeup/wakeup24 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00 +E: SUBSYSTEM=acpi +E: DRIVER=button +E: MODALIAS=acpi:PNP0C0E: +E: USEC_INITIALIZED=14079924 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00/input/input2 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00/input/input2 +E: SUBSYSTEM=input +E: PRODUCT=19/0/3/0 +E: NAME="Sleep Button" +E: PHYS="PNP0C0E/button/input0" +E: PROP=0 +E: EV=3 +E: KEY=4000 0 0 +E: MODALIAS=input:b0019v0000p0003e0000-e0,1,k8E,ramlsfw +E: USEC_INITIALIZED=14093445 +E: ID_INPUT=1 +E: ID_INPUT_KEY=1 +E: ID_PATH=acpi-PNP0C0E:00 +E: ID_PATH_TAG=acpi-PNP0C0E_00 +E: ID_FOR_SEAT=input-acpi-PNP0C0E_00 +E: TAGS=:seat: + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00/input/input2/event2 +N: input/event2 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00/input/input2/event2 +E: SUBSYSTEM=input +E: DEVNAME=/dev/input/event2 +E: MAJOR=13 +E: MINOR=66 +E: USEC_INITIALIZED=14171406 +E: ID_INPUT=1 +E: ID_INPUT_KEY=1 +E: ID_PATH=acpi-PNP0C0E:00 +E: ID_PATH_TAG=acpi-PNP0C0E_00 +E: TAGS=:power-switch: + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00/wakeup/wakeup25 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00/wakeup/wakeup25 +E: SUBSYSTEM=wakeup + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0C0F: +E: USEC_INITIALIZED=14081512 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:01 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:01 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0C0F: +E: USEC_INITIALIZED=14082344 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:02 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:02 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0C0F: +E: USEC_INITIALIZED=14081507 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:03 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:03 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0C0F: +E: USEC_INITIALIZED=14084400 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:04 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:04 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0C0F: +E: USEC_INITIALIZED=14088047 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:05 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:05 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0C0F: +E: USEC_INITIALIZED=14090425 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:06 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:06 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0C0F: +E: USEC_INITIALIZED=14090336 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:07 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:07 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0C0F: +E: USEC_INITIALIZED=14095122 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/USBC000:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/USBC000:00 +E: SUBSYSTEM=acpi +E: MODALIAS= + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/USBC000:00/device:55 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/USBC000:00/device:55 +E: SUBSYSTEM=acpi + +P: /devices/LNXSYSTM:00/LNXSYBUS:01 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:01 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:LNXSYBUS: +E: USEC_INITIALIZED=13915691 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:01/LNXPOWER:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:01/LNXPOWER:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:LNXPOWER: +E: USEC_INITIALIZED=14096658 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:01/LNXTHERM:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:01/LNXTHERM:00 +E: SUBSYSTEM=acpi +E: DRIVER=thermal +E: MODALIAS=acpi:LNXTHERM: +E: USEC_INITIALIZED=14100519 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/LNXSYSTM:00/LNXSYBUS:01/PNP0C0B:00 +L: 0 +E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:01/PNP0C0B:00 +E: SUBSYSTEM=acpi +E: MODALIAS=acpi:PNP0C0B: +E: USEC_INITIALIZED=14096621 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation + +P: /devices/breakpoint +L: 0 +E: DEVPATH=/devices/breakpoint +E: SUBSYSTEM=event_source + +P: /devices/cpu +L: 0 +E: DEVPATH=/devices/cpu +E: SUBSYSTEM=event_source + +P: /devices/cstate_core +L: 0 +E: DEVPATH=/devices/cstate_core +E: SUBSYSTEM=event_source + +P: /devices/cstate_pkg +L: 0 +E: DEVPATH=/devices/cstate_pkg +E: SUBSYSTEM=event_source + +P: /devices/i915 +L: 0 +E: DEVPATH=/devices/i915 +E: SUBSYSTEM=event_source + +P: /devices/intel_bts +L: 0 +E: DEVPATH=/devices/intel_bts +E: SUBSYSTEM=event_source + +P: /devices/intel_pt +L: 0 +E: DEVPATH=/devices/intel_pt +E: SUBSYSTEM=event_source + +P: /devices/kprobe +L: 0 +E: DEVPATH=/devices/kprobe +E: SUBSYSTEM=event_source + +P: /devices/msr +L: 0 +E: DEVPATH=/devices/msr +E: SUBSYSTEM=event_source + +P: /devices/pci0000:00/0000:00:00.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:00.0 +E: SUBSYSTEM=pci +E: PCI_CLASS=60000 +E: PCI_ID=8086:5AF0 +E: PCI_SUBSYS_ID=8086:7270 +E: PCI_SLOT_NAME=0000:00:00.0 +E: MODALIAS=pci:v00008086d00005AF0sv00008086sd00007270bc06sc00i00 +E: USEC_INITIALIZED=14005080 +E: ID_PCI_CLASS_FROM_DATABASE=Bridge +E: ID_PCI_SUBCLASS_FROM_DATABASE=Host bridge +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series Host Bridge + +P: /devices/pci0000:00/0000:00:02.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0 +E: SUBSYSTEM=pci +E: DRIVER=i915 +E: PCI_CLASS=30000 +E: PCI_ID=8086:5A85 +E: PCI_SUBSYS_ID=8086:2212 +E: PCI_SLOT_NAME=0000:00:02.0 +E: MODALIAS=pci:v00008086d00005A85sv00008086sd00002212bc03sc00i00 +E: USEC_INITIALIZED=13994813 +E: ID_PCI_CLASS_FROM_DATABASE=Display controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=VGA compatible controller +E: ID_PCI_INTERFACE_FROM_DATABASE=VGA controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=HD Graphics 500 + +P: /devices/pci0000:00/0000:00:02.0/backlight/acpi_video0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/backlight/acpi_video0 +E: SUBSYSTEM=backlight +E: USEC_INITIALIZED=16943546 +E: ID_PATH=pci-0000:00:02.0 +E: ID_PATH_TAG=pci-0000_00_02_0 +E: ID_FOR_SEAT=backlight-pci-0000_00_02_0 +E: SYSTEMD_WANTS=systemd-backlight@backlight:acpi_video0.service +E: TAGS=:systemd:seat: + +P: /devices/pci0000:00/0000:00:02.0/drm/card0 +N: dri/card0 +L: 0 +S: dri/by-path/pci-0000:00:02.0-card +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0 +E: SUBSYSTEM=drm +E: DEVNAME=/dev/dri/card0 +E: DEVTYPE=drm_minor +E: MAJOR=226 +E: MINOR=0 +E: USEC_INITIALIZED=16869549 +E: ID_PATH=pci-0000:00:02.0 +E: ID_PATH_TAG=pci-0000_00_02_0 +E: ID_FOR_SEAT=drm-pci-0000_00_02_0 +E: DEVLINKS=/dev/dri/by-path/pci-0000:00:02.0-card +E: TAGS=:seat:uaccess:master-of-seat: + +P: /devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-1 +E: SUBSYSTEM=drm +E: USEC_INITIALIZED=16890221 +E: ID_PATH=pci-0000:00:02.0 +E: ID_PATH_TAG=pci-0000_00_02_0 +E: ID_FOR_SEAT=drm-pci-0000_00_02_0 +E: TAGS=:seat:master-of-seat: + +P: /devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-1/drm_dp_aux0 +N: drm_dp_aux0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-1/drm_dp_aux0 +E: SUBSYSTEM=drm_dp_aux_dev +E: DEVNAME=/dev/drm_dp_aux0 +E: MAJOR=236 +E: MINOR=0 + +P: /devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-1/i2c-4 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-1/i2c-4 +E: SUBSYSTEM=i2c + +P: /devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-1/i2c-4/i2c-dev/i2c-4 +N: i2c-4 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-1/i2c-4/i2c-dev/i2c-4 +E: SUBSYSTEM=i2c-dev +E: DEVNAME=/dev/i2c-4 +E: MAJOR=89 +E: MINOR=4 + +P: /devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-2 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-2 +E: SUBSYSTEM=drm +E: USEC_INITIALIZED=17082448 +E: ID_PATH=pci-0000:00:02.0 +E: ID_PATH_TAG=pci-0000_00_02_0 +E: ID_FOR_SEAT=drm-pci-0000_00_02_0 +E: TAGS=:seat:master-of-seat: + +P: /devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-2/drm_dp_aux1 +N: drm_dp_aux1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-2/drm_dp_aux1 +E: SUBSYSTEM=drm_dp_aux_dev +E: DEVNAME=/dev/drm_dp_aux1 +E: MAJOR=236 +E: MINOR=1 + +P: /devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-2/i2c-5 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-2/i2c-5 +E: SUBSYSTEM=i2c + +P: /devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-2/i2c-5/i2c-dev/i2c-5 +N: i2c-5 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-2/i2c-5/i2c-dev/i2c-5 +E: SUBSYSTEM=i2c-dev +E: DEVNAME=/dev/i2c-5 +E: MAJOR=89 +E: MINOR=5 + +P: /devices/pci0000:00/0000:00:02.0/drm/card0/card0-HDMI-A-1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0/card0-HDMI-A-1 +E: SUBSYSTEM=drm +E: USEC_INITIALIZED=17024879 +E: ID_PATH=pci-0000:00:02.0 +E: ID_PATH_TAG=pci-0000_00_02_0 +E: ID_FOR_SEAT=drm-pci-0000_00_02_0 +E: TAGS=:seat:master-of-seat: + +P: /devices/pci0000:00/0000:00:02.0/drm/card0/card0-HDMI-A-2 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0/card0-HDMI-A-2 +E: SUBSYSTEM=drm +E: USEC_INITIALIZED=17277609 +E: ID_PATH=pci-0000:00:02.0 +E: ID_PATH_TAG=pci-0000_00_02_0 +E: ID_FOR_SEAT=drm-pci-0000_00_02_0 +E: TAGS=:seat:master-of-seat: + +P: /devices/pci0000:00/0000:00:02.0/drm/renderD128 +N: dri/renderD128 +L: 0 +S: dri/by-path/pci-0000:00:02.0-render +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/renderD128 +E: SUBSYSTEM=drm +E: DEVNAME=/dev/dri/renderD128 +E: DEVTYPE=drm_minor +E: MAJOR=226 +E: MINOR=128 +E: USEC_INITIALIZED=16870222 +E: ID_PATH=pci-0000:00:02.0 +E: ID_PATH_TAG=pci-0000_00_02_0 +E: ID_FOR_SEAT=drm-pci-0000_00_02_0 +E: DEVLINKS=/dev/dri/by-path/pci-0000:00:02.0-render +E: TAGS=:uaccess:seat: + +P: /devices/pci0000:00/0000:00:02.0/graphics/fb0 +N: fb0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/graphics/fb0 +E: SUBSYSTEM=graphics +E: DEVNAME=/dev/fb0 +E: MAJOR=29 +E: MINOR=0 +E: USEC_INITIALIZED=18241110 +E: ID_PATH=pci-0000:00:02.0 +E: ID_PATH_TAG=pci-0000_00_02_0 +E: ID_FOR_SEAT=graphics-pci-0000_00_02_0 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:02.0/i2c-1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/i2c-1 +E: SUBSYSTEM=i2c + +P: /devices/pci0000:00/0000:00:02.0/i2c-1/i2c-dev/i2c-1 +N: i2c-1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/i2c-1/i2c-dev/i2c-1 +E: SUBSYSTEM=i2c-dev +E: DEVNAME=/dev/i2c-1 +E: MAJOR=89 +E: MINOR=1 + +P: /devices/pci0000:00/0000:00:02.0/i2c-2 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/i2c-2 +E: SUBSYSTEM=i2c + +P: /devices/pci0000:00/0000:00:02.0/i2c-2/i2c-dev/i2c-2 +N: i2c-2 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/i2c-2/i2c-dev/i2c-2 +E: SUBSYSTEM=i2c-dev +E: DEVNAME=/dev/i2c-2 +E: MAJOR=89 +E: MINOR=2 + +P: /devices/pci0000:00/0000:00:02.0/i2c-3 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/i2c-3 +E: SUBSYSTEM=i2c + +P: /devices/pci0000:00/0000:00:02.0/i2c-3/i2c-dev/i2c-3 +N: i2c-3 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:02.0/i2c-3/i2c-dev/i2c-3 +E: SUBSYSTEM=i2c-dev +E: DEVNAME=/dev/i2c-3 +E: MAJOR=89 +E: MINOR=3 + +P: /devices/pci0000:00/0000:00:0e.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0 +E: SUBSYSTEM=pci +E: DRIVER=snd_hda_intel +E: PCI_CLASS=40300 +E: PCI_ID=8086:5A98 +E: PCI_SUBSYS_ID=8086:7270 +E: PCI_SLOT_NAME=0000:00:0e.0 +E: MODALIAS=pci:v00008086d00005A98sv00008086sd00007270bc04sc03i00 +E: USEC_INITIALIZED=13997096 +E: ID_PCI_CLASS_FROM_DATABASE=Multimedia controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Audio device +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series Audio Cluster + +P: /devices/pci0000:00/0000:00:0e.0/hdaudioC0D2 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/hdaudioC0D2 +E: SUBSYSTEM=hdaudio +E: DRIVER=snd_hda_codec_hdmi +E: MODALIAS=hdaudio:v8086280Ar00100000a01 + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0 +E: SUBSYSTEM=sound +E: USEC_INITIALIZED=18296116 +E: ID_PATH=pci-0000:00:0e.0 +E: ID_PATH_TAG=pci-0000_00_0e_0 +E: ID_FOR_SEAT=sound-pci-0000_00_0e_0 +E: SOUND_INITIALIZED=1 +E: ID_PCI_CLASS_FROM_DATABASE=Multimedia controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Audio device +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series Audio Cluster +E: ID_BUS=pci +E: ID_VENDOR_ID=0x8086 +E: ID_MODEL_ID=0x5a98 +E: SOUND_FORM_FACTOR=internal +E: SYSTEMD_WANTS=sound.target +E: SYSTEMD_USER_WANTS=sound.target +E: TAGS=:systemd:seat: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/hwC0D2 +N: snd/hwC0D2 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/hwC0D2 +E: SUBSYSTEM=sound +E: DEVNAME=/dev/snd/hwC0D2 +E: MAJOR=116 +E: MINOR=7 +E: USEC_INITIALIZED=18309219 +E: TAGS=:uaccess: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/input10 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/input10 +E: SUBSYSTEM=input +E: PRODUCT=0/0/0/0 +E: NAME="HDA Intel PCH HDMI/DP,pcm=9" +E: PHYS="ALSA" +E: PROP=0 +E: EV=21 +E: SW=140 +E: MODALIAS=input:b0000v0000p0000e0000-e0,5,kramlsfw6,8, +E: USEC_INITIALIZED=18317971 +E: ID_INPUT=1 +E: ID_INPUT_SWITCH=1 +E: ID_PATH=pci-0000:00:0e.0 +E: ID_PATH_TAG=pci-0000_00_0e_0 +E: ID_FOR_SEAT=input-pci-0000_00_0e_0 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/input10/event10 +N: input/event10 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/input10/event10 +E: SUBSYSTEM=input +E: DEVNAME=/dev/input/event10 +E: MAJOR=13 +E: MINOR=74 +E: USEC_INITIALIZED=18439437 +E: ID_INPUT=1 +E: ID_INPUT_SWITCH=1 +E: ID_PATH=pci-0000:00:0e.0 +E: ID_PATH_TAG=pci-0000_00_0e_0 +E: TAGS=:power-switch: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/input11 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/input11 +E: SUBSYSTEM=input +E: PRODUCT=0/0/0/0 +E: NAME="HDA Intel PCH HDMI/DP,pcm=10" +E: PHYS="ALSA" +E: PROP=0 +E: EV=21 +E: SW=140 +E: MODALIAS=input:b0000v0000p0000e0000-e0,5,kramlsfw6,8, +E: USEC_INITIALIZED=18320248 +E: ID_INPUT=1 +E: ID_INPUT_SWITCH=1 +E: ID_PATH=pci-0000:00:0e.0 +E: ID_PATH_TAG=pci-0000_00_0e_0 +E: ID_FOR_SEAT=input-pci-0000_00_0e_0 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/input11/event11 +N: input/event11 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/input11/event11 +E: SUBSYSTEM=input +E: DEVNAME=/dev/input/event11 +E: MAJOR=13 +E: MINOR=75 +E: USEC_INITIALIZED=18449528 +E: ID_INPUT=1 +E: ID_INPUT_SWITCH=1 +E: ID_PATH=pci-0000:00:0e.0 +E: ID_PATH_TAG=pci-0000_00_0e_0 +E: TAGS=:power-switch: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/input7 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/input7 +E: SUBSYSTEM=input +E: PRODUCT=0/0/0/0 +E: NAME="HDA Intel PCH HDMI/DP,pcm=3" +E: PHYS="ALSA" +E: PROP=0 +E: EV=21 +E: SW=140 +E: MODALIAS=input:b0000v0000p0000e0000-e0,5,kramlsfw6,8, +E: USEC_INITIALIZED=18307379 +E: ID_INPUT=1 +E: ID_INPUT_SWITCH=1 +E: ID_PATH=pci-0000:00:0e.0 +E: ID_PATH_TAG=pci-0000_00_0e_0 +E: ID_FOR_SEAT=input-pci-0000_00_0e_0 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/input7/event7 +N: input/event7 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/input7/event7 +E: SUBSYSTEM=input +E: DEVNAME=/dev/input/event7 +E: MAJOR=13 +E: MINOR=71 +E: USEC_INITIALIZED=18403217 +E: ID_INPUT=1 +E: ID_INPUT_SWITCH=1 +E: ID_PATH=pci-0000:00:0e.0 +E: ID_PATH_TAG=pci-0000_00_0e_0 +E: TAGS=:power-switch: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/input8 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/input8 +E: SUBSYSTEM=input +E: PRODUCT=0/0/0/0 +E: NAME="HDA Intel PCH HDMI/DP,pcm=7" +E: PHYS="ALSA" +E: PROP=0 +E: EV=21 +E: SW=140 +E: MODALIAS=input:b0000v0000p0000e0000-e0,5,kramlsfw6,8, +E: USEC_INITIALIZED=18356974 +E: ID_INPUT=1 +E: ID_INPUT_SWITCH=1 +E: ID_PATH=pci-0000:00:0e.0 +E: ID_PATH_TAG=pci-0000_00_0e_0 +E: ID_FOR_SEAT=input-pci-0000_00_0e_0 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/input8/event8 +N: input/event8 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/input8/event8 +E: SUBSYSTEM=input +E: DEVNAME=/dev/input/event8 +E: MAJOR=13 +E: MINOR=72 +E: USEC_INITIALIZED=18482946 +E: ID_INPUT=1 +E: ID_INPUT_SWITCH=1 +E: ID_PATH=pci-0000:00:0e.0 +E: ID_PATH_TAG=pci-0000_00_0e_0 +E: TAGS=:power-switch: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/input9 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/input9 +E: SUBSYSTEM=input +E: PRODUCT=0/0/0/0 +E: NAME="HDA Intel PCH HDMI/DP,pcm=8" +E: PHYS="ALSA" +E: PROP=0 +E: EV=21 +E: SW=140 +E: MODALIAS=input:b0000v0000p0000e0000-e0,5,kramlsfw6,8, +E: USEC_INITIALIZED=18312481 +E: ID_INPUT=1 +E: ID_INPUT_SWITCH=1 +E: ID_PATH=pci-0000:00:0e.0 +E: ID_PATH_TAG=pci-0000_00_0e_0 +E: ID_FOR_SEAT=input-pci-0000_00_0e_0 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/input9/event9 +N: input/event9 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/input9/event9 +E: SUBSYSTEM=input +E: DEVNAME=/dev/input/event9 +E: MAJOR=13 +E: MINOR=73 +E: USEC_INITIALIZED=18395750 +E: ID_INPUT=1 +E: ID_INPUT_SWITCH=1 +E: ID_PATH=pci-0000:00:0e.0 +E: ID_PATH_TAG=pci-0000_00_0e_0 +E: TAGS=:power-switch: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/pcmC0D10p +N: snd/pcmC0D10p +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/pcmC0D10p +E: SUBSYSTEM=sound +E: DEVNAME=/dev/snd/pcmC0D10p +E: DEVTYPE=pcm +E: MAJOR=116 +E: MINOR=6 +E: USEC_INITIALIZED=18306882 +E: TAGS=:uaccess: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/pcmC0D3p +N: snd/pcmC0D3p +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/pcmC0D3p +E: SUBSYSTEM=sound +E: DEVNAME=/dev/snd/pcmC0D3p +E: DEVTYPE=pcm +E: MAJOR=116 +E: MINOR=2 +E: USEC_INITIALIZED=18298015 +E: TAGS=:uaccess: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/pcmC0D7p +N: snd/pcmC0D7p +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/pcmC0D7p +E: SUBSYSTEM=sound +E: DEVNAME=/dev/snd/pcmC0D7p +E: DEVTYPE=pcm +E: MAJOR=116 +E: MINOR=3 +E: USEC_INITIALIZED=18300830 +E: TAGS=:uaccess: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/pcmC0D8p +N: snd/pcmC0D8p +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/pcmC0D8p +E: SUBSYSTEM=sound +E: DEVNAME=/dev/snd/pcmC0D8p +E: DEVTYPE=pcm +E: MAJOR=116 +E: MINOR=4 +E: USEC_INITIALIZED=18304666 +E: TAGS=:uaccess: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/pcmC0D9p +N: snd/pcmC0D9p +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/pcmC0D9p +E: SUBSYSTEM=sound +E: DEVNAME=/dev/snd/pcmC0D9p +E: DEVTYPE=pcm +E: MAJOR=116 +E: MINOR=5 +E: USEC_INITIALIZED=18302872 +E: TAGS=:uaccess: + +P: /devices/pci0000:00/0000:00:0e.0/sound/card0/controlC0 +N: snd/controlC0 +L: 0 +S: snd/by-path/pci-0000:00:0e.0 +E: DEVPATH=/devices/pci0000:00/0000:00:0e.0/sound/card0/controlC0 +E: SUBSYSTEM=sound +E: DEVNAME=/dev/snd/controlC0 +E: MAJOR=116 +E: MINOR=8 +E: USEC_INITIALIZED=18313726 +E: ID_PATH=pci-0000:00:0e.0 +E: ID_PATH_TAG=pci-0000_00_0e_0 +E: DEVLINKS=/dev/snd/by-path/pci-0000:00:0e.0 +E: TAGS=:uaccess: + +P: /devices/pci0000:00/0000:00:0f.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0f.0 +E: SUBSYSTEM=pci +E: DRIVER=mei_me +E: PCI_CLASS=78000 +E: PCI_ID=8086:5A9A +E: PCI_SUBSYS_ID=8086:7270 +E: PCI_SLOT_NAME=0000:00:0f.0 +E: MODALIAS=pci:v00008086d00005A9Asv00008086sd00007270bc07sc80i00 +E: USEC_INITIALIZED=13971502 +E: ID_PCI_CLASS_FROM_DATABASE=Communication controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Communication controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series Trusted Execution Engine + +P: /devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-082ee5a7-7c25-470a-9643-0c06f0466ea1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-082ee5a7-7c25-470a-9643-0c06f0466ea1 +E: SUBSYSTEM=mei +E: MEI_CL_VERSION=0 +E: MEI_CL_UUID=082ee5a7-7c25-470a-9643-0c06f0466ea1 +E: MEI_CL_NAME= +E: MODALIAS=mei::082ee5a7-7c25-470a-9643-0c06f0466ea1:00: + +P: /devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-3c4852d6-d47b-4f46-b05e-b5edc1aa440e +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-3c4852d6-d47b-4f46-b05e-b5edc1aa440e +E: SUBSYSTEM=mei +E: MEI_CL_VERSION=1 +E: MEI_CL_UUID=3c4852d6-d47b-4f46-b05e-b5edc1aa440e +E: MEI_CL_NAME= +E: MODALIAS=mei::3c4852d6-d47b-4f46-b05e-b5edc1aa440e:01: + +P: /devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-55213584-9a29-4916-badf-0fb7ed682aeb +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-55213584-9a29-4916-badf-0fb7ed682aeb +E: SUBSYSTEM=mei +E: MEI_CL_VERSION=1 +E: MEI_CL_UUID=55213584-9a29-4916-badf-0fb7ed682aeb +E: MEI_CL_NAME= +E: MODALIAS=mei::55213584-9a29-4916-badf-0fb7ed682aeb:01: + +P: /devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-5565a099-7fe2-45c1-a22b-d7e9dfea9a2e +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-5565a099-7fe2-45c1-a22b-d7e9dfea9a2e +E: SUBSYSTEM=mei +E: MEI_CL_VERSION=1 +E: MEI_CL_UUID=5565a099-7fe2-45c1-a22b-d7e9dfea9a2e +E: MEI_CL_NAME= +E: MODALIAS=mei::5565a099-7fe2-45c1-a22b-d7e9dfea9a2e:01: + +P: /devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-8e6a6715-9abc-4043-88ef-9e39c6f63e0f +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-8e6a6715-9abc-4043-88ef-9e39c6f63e0f +E: SUBSYSTEM=mei +E: MEI_CL_VERSION=1 +E: MEI_CL_UUID=8e6a6715-9abc-4043-88ef-9e39c6f63e0f +E: MEI_CL_NAME= +E: MODALIAS=mei::8e6a6715-9abc-4043-88ef-9e39c6f63e0f:01: + +P: /devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-b638ab7e-94e2-4ea2-a552-d1c54b627f04 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-b638ab7e-94e2-4ea2-a552-d1c54b627f04 +E: SUBSYSTEM=mei +E: DRIVER=mei_hdcp +E: MEI_CL_VERSION=1 +E: MEI_CL_UUID=b638ab7e-94e2-4ea2-a552-d1c54b627f04 +E: MEI_CL_NAME= +E: MODALIAS=mei::b638ab7e-94e2-4ea2-a552-d1c54b627f04:01: + +P: /devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-dba4d603-d7ed-4931-8823-17ad585705d5 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-dba4d603-d7ed-4931-8823-17ad585705d5 +E: SUBSYSTEM=mei +E: MEI_CL_VERSION=1 +E: MEI_CL_UUID=dba4d603-d7ed-4931-8823-17ad585705d5 +E: MEI_CL_NAME= +E: MODALIAS=mei::dba4d603-d7ed-4931-8823-17ad585705d5:01: + +P: /devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-f908627d-13bf-4a04-b91f-a64e9245323d +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0f.0/0000:00:0f.0-f908627d-13bf-4a04-b91f-a64e9245323d +E: SUBSYSTEM=mei +E: MEI_CL_VERSION=1 +E: MEI_CL_UUID=f908627d-13bf-4a04-b91f-a64e9245323d +E: MEI_CL_NAME= +E: MODALIAS=mei::f908627d-13bf-4a04-b91f-a64e9245323d:01: + +P: /devices/pci0000:00/0000:00:0f.0/mei/mei0 +N: mei0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:0f.0/mei/mei0 +E: SUBSYSTEM=mei +E: DEVNAME=/dev/mei0 +E: MAJOR=237 +E: MINOR=0 + +P: /devices/pci0000:00/0000:00:12.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:12.0 +E: SUBSYSTEM=pci +E: DRIVER=ahci +E: PCI_CLASS=10601 +E: PCI_ID=8086:5AE3 +E: PCI_SUBSYS_ID=8086:7270 +E: PCI_SLOT_NAME=0000:00:12.0 +E: MODALIAS=pci:v00008086d00005AE3sv00008086sd00007270bc01sc06i01 +E: USEC_INITIALIZED=13966200 +E: ID_PCI_CLASS_FROM_DATABASE=Mass storage controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=SATA controller +E: ID_PCI_INTERFACE_FROM_DATABASE=AHCI 1.0 +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series SATA AHCI Controller + +P: /devices/pci0000:00/0000:00:12.0/ata1/ata_port/ata1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:12.0/ata1/ata_port/ata1 +E: SUBSYSTEM=ata_port + +P: /devices/pci0000:00/0000:00:12.0/ata1/host0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:12.0/ata1/host0 +E: SUBSYSTEM=scsi +E: DEVTYPE=scsi_host + +P: /devices/pci0000:00/0000:00:12.0/ata1/host0/scsi_host/host0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:12.0/ata1/host0/scsi_host/host0 +E: SUBSYSTEM=scsi_host + +P: /devices/pci0000:00/0000:00:12.0/ata1/link1/ata_link/link1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:12.0/ata1/link1/ata_link/link1 +E: SUBSYSTEM=ata_link + +P: /devices/pci0000:00/0000:00:12.0/ata1/link1/dev1.0/ata_device/dev1.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:12.0/ata1/link1/dev1.0/ata_device/dev1.0 +E: SUBSYSTEM=ata_device + +P: /devices/pci0000:00/0000:00:13.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:13.0 +E: SUBSYSTEM=pci +E: DRIVER=pcieport +E: PCI_CLASS=60400 +E: PCI_ID=8086:5AD8 +E: PCI_SUBSYS_ID=0000:0000 +E: PCI_SLOT_NAME=0000:00:13.0 +E: MODALIAS=pci:v00008086d00005AD8sv00000000sd00000000bc06sc04i00 +E: USEC_INITIALIZED=13981119 +E: ID_PCI_CLASS_FROM_DATABASE=Bridge +E: ID_PCI_SUBCLASS_FROM_DATABASE=PCI bridge +E: ID_PCI_INTERFACE_FROM_DATABASE=Normal decode +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port A + +P: /devices/pci0000:00/0000:00:13.0/0000:00:13.0:pcie001 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:13.0/0000:00:13.0:pcie001 +E: SUBSYSTEM=pci_express +E: DRIVER=pcie_pme + +P: /devices/pci0000:00/0000:00:13.0/0000:00:13.0:pcie010 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:13.0/0000:00:13.0:pcie010 +E: SUBSYSTEM=pci_express + +P: /devices/pci0000:00/0000:00:13.0/0000:01:00.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:13.0/0000:01:00.0 +E: SUBSYSTEM=pci +E: DRIVER=iwlwifi +E: PCI_CLASS=28000 +E: PCI_ID=8086:2526 +E: PCI_SUBSYS_ID=8086:E014 +E: PCI_SLOT_NAME=0000:01:00.0 +E: MODALIAS=pci:v00008086d00002526sv00008086sd0000E014bc02sc80i00 +E: USEC_INITIALIZED=14106588 +E: ID_PCI_CLASS_FROM_DATABASE=Network controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Network controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Wireless-AC 9260 + +P: /devices/pci0000:00/0000:00:13.0/0000:01:00.0/ieee80211/phy0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:13.0/0000:01:00.0/ieee80211/phy0 +E: SUBSYSTEM=ieee80211 + +P: /devices/pci0000:00/0000:00:13.0/0000:01:00.0/ieee80211/phy0/rfkill0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:13.0/0000:01:00.0/ieee80211/phy0/rfkill0 +E: SUBSYSTEM=rfkill +E: RFKILL_NAME=phy0 +E: RFKILL_TYPE=wlan +E: RFKILL_STATE=1 +E: USEC_INITIALIZED=18112965 +E: SYSTEMD_RFKILL=1 +E: ID_PATH=pci-0000:01:00.0 +E: ID_PATH_TAG=pci-0000_01_00_0 + +P: /devices/pci0000:00/0000:00:13.0/0000:01:00.0/leds/phy0-led +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:13.0/0000:01:00.0/leds/phy0-led +E: SUBSYSTEM=leds +E: USEC_INITIALIZED=18108514 +E: ID_PATH=pci-0000:01:00.0 +E: ID_PATH_TAG=pci-0000_01_00_0 +E: ID_FOR_SEAT=leds-pci-0000_01_00_0 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:13.0/0000:01:00.0/net/wlp1s0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:13.0/0000:01:00.0/net/wlp1s0 +E: SUBSYSTEM=net +E: DEVTYPE=wlan +E: INTERFACE=wlp1s0 +E: IFINDEX=5 +E: USEC_INITIALIZED=18215180 +E: ID_MM_CANDIDATE=1 +E: ID_NET_NAMING_SCHEME=v245 +E: ID_NET_NAME_MAC=wlxdc1ba114014f +E: ID_NET_NAME_PATH=wlp1s0 +E: ID_BUS=pci +E: ID_VENDOR_ID=0x8086 +E: ID_MODEL_ID=0x2526 +E: ID_PCI_CLASS_FROM_DATABASE=Network controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Network controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Wireless-AC 9260 +E: ID_PATH=pci-0000:01:00.0 +E: ID_PATH_TAG=pci-0000_01_00_0 +E: ID_NET_DRIVER=iwlwifi +E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link +E: ID_NET_NAME=wlp1s0 +E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/wlp1s0 /sys/subsystem/net/devices/wlp1s0 +E: TAGS=:systemd: + +P: /devices/pci0000:00/0000:00:13.0/pci_bus/0000:01 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:13.0/pci_bus/0000:01 +E: SUBSYSTEM=pci_bus + +P: /devices/pci0000:00/0000:00:13.0/wakeup/wakeup6 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:13.0/wakeup/wakeup6 +E: SUBSYSTEM=wakeup + +P: /devices/pci0000:00/0000:00:14.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.0 +E: SUBSYSTEM=pci +E: DRIVER=pcieport +E: PCI_CLASS=60400 +E: PCI_ID=8086:5AD6 +E: PCI_SUBSYS_ID=0000:0000 +E: PCI_SLOT_NAME=0000:00:14.0 +E: MODALIAS=pci:v00008086d00005AD6sv00000000sd00000000bc06sc04i00 +E: USEC_INITIALIZED=13995601 +E: ID_PCI_CLASS_FROM_DATABASE=Bridge +E: ID_PCI_SUBCLASS_FROM_DATABASE=PCI bridge +E: ID_PCI_INTERFACE_FROM_DATABASE=Normal decode +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port B + +P: /devices/pci0000:00/0000:00:14.0/0000:00:14.0:pcie001 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.0/0000:00:14.0:pcie001 +E: SUBSYSTEM=pci_express +E: DRIVER=pcie_pme + +P: /devices/pci0000:00/0000:00:14.0/0000:00:14.0:pcie010 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.0/0000:00:14.0:pcie010 +E: SUBSYSTEM=pci_express + +P: /devices/pci0000:00/0000:00:14.0/0000:02:00.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.0/0000:02:00.0 +E: SUBSYSTEM=pci +E: DRIVER=igb +E: PCI_CLASS=20000 +E: PCI_ID=8086:1539 +E: PCI_SUBSYS_ID=8086:0000 +E: PCI_SLOT_NAME=0000:02:00.0 +E: MODALIAS=pci:v00008086d00001539sv00008086sd00000000bc02sc00i00 +E: USEC_INITIALIZED=14127613 +E: ID_PCI_CLASS_FROM_DATABASE=Network controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Ethernet controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=I211 Gigabit Network Connection + +P: /devices/pci0000:00/0000:00:14.0/0000:02:00.0/net/enp2s0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.0/0000:02:00.0/net/enp2s0 +E: SUBSYSTEM=net +E: INTERFACE=enp2s0 +E: IFINDEX=2 +E: USEC_INITIALIZED=16898866 +E: ID_MM_CANDIDATE=1 +E: ID_NET_NAMING_SCHEME=v245 +E: ID_NET_NAME_MAC=enx0013953a09c3 +E: ID_OUI_FROM_DATABASE=congatec AG +E: ID_NET_NAME_PATH=enp2s0 +E: ID_BUS=pci +E: ID_VENDOR_ID=0x8086 +E: ID_MODEL_ID=0x1539 +E: ID_PCI_CLASS_FROM_DATABASE=Network controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Ethernet controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=I211 Gigabit Network Connection +E: ID_PATH=pci-0000:02:00.0 +E: ID_PATH_TAG=pci-0000_02_00_0 +E: ID_NET_DRIVER=igb +E: ID_NET_LINK_FILE=/run/systemd/network/10-netplan-enp2s0.link +E: ID_NET_NAME=enp2s0 +E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/enp2s0 /sys/subsystem/net/devices/enp2s0 +E: TAGS=:systemd: + +P: /devices/pci0000:00/0000:00:14.0/0000:02:00.0/ptp/ptp0 +N: ptp0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.0/0000:02:00.0/ptp/ptp0 +E: SUBSYSTEM=ptp +E: DEVNAME=/dev/ptp0 +E: MAJOR=246 +E: MINOR=0 + +P: /devices/pci0000:00/0000:00:14.0/pci_bus/0000:02 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.0/pci_bus/0000:02 +E: SUBSYSTEM=pci_bus + +P: /devices/pci0000:00/0000:00:14.0/wakeup/wakeup8 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.0/wakeup/wakeup8 +E: SUBSYSTEM=wakeup + +P: /devices/pci0000:00/0000:00:14.1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.1 +E: SUBSYSTEM=pci +E: DRIVER=pcieport +E: PCI_CLASS=60400 +E: PCI_ID=8086:5AD7 +E: PCI_SUBSYS_ID=0000:0000 +E: PCI_SLOT_NAME=0000:00:14.1 +E: MODALIAS=pci:v00008086d00005AD7sv00000000sd00000000bc06sc04i00 +E: USEC_INITIALIZED=14114016 +E: ID_PCI_CLASS_FROM_DATABASE=Bridge +E: ID_PCI_SUBCLASS_FROM_DATABASE=PCI bridge +E: ID_PCI_INTERFACE_FROM_DATABASE=Normal decode +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port B + +P: /devices/pci0000:00/0000:00:14.1/0000:00:14.1:pcie001 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.1/0000:00:14.1:pcie001 +E: SUBSYSTEM=pci_express +E: DRIVER=pcie_pme + +P: /devices/pci0000:00/0000:00:14.1/0000:00:14.1:pcie010 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.1/0000:00:14.1:pcie010 +E: SUBSYSTEM=pci_express + +P: /devices/pci0000:00/0000:00:14.1/0000:03:00.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.1/0000:03:00.0 +E: SUBSYSTEM=pci +E: DRIVER=igb +E: PCI_CLASS=20000 +E: PCI_ID=8086:1539 +E: PCI_SUBSYS_ID=8086:0000 +E: PCI_SLOT_NAME=0000:03:00.0 +E: MODALIAS=pci:v00008086d00001539sv00008086sd00000000bc02sc00i00 +E: USEC_INITIALIZED=14120412 +E: ID_PCI_CLASS_FROM_DATABASE=Network controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Ethernet controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=I211 Gigabit Network Connection + +P: /devices/pci0000:00/0000:00:14.1/0000:03:00.0/net/eth1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.1/0000:03:00.0/net/eth1 +E: SUBSYSTEM=net +E: INTERFACE=eth1 +E: IFINDEX=3 +E: USEC_INITIALIZED=16901738 +E: ID_MM_CANDIDATE=1 +E: ID_NET_NAMING_SCHEME=v245 +E: ID_NET_NAME_MAC=enx0013953a09c4 +E: ID_OUI_FROM_DATABASE=congatec AG +E: ID_NET_NAME_PATH=enp3s0 +E: ID_BUS=pci +E: ID_VENDOR_ID=0x8086 +E: ID_MODEL_ID=0x1539 +E: ID_PCI_CLASS_FROM_DATABASE=Network controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Ethernet controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=I211 Gigabit Network Connection +E: ID_PATH=pci-0000:03:00.0 +E: ID_PATH_TAG=pci-0000_03_00_0 +E: ID_NET_DRIVER=igb +E: ID_NET_LINK_FILE=/run/systemd/network/10-netplan-eth1.link +E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/eth1 +E: TAGS=:systemd: + +P: /devices/pci0000:00/0000:00:14.1/0000:03:00.0/ptp/ptp1 +N: ptp1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.1/0000:03:00.0/ptp/ptp1 +E: SUBSYSTEM=ptp +E: DEVNAME=/dev/ptp1 +E: MAJOR=246 +E: MINOR=1 + +P: /devices/pci0000:00/0000:00:14.1/0000:03:00.0/wakeup/wakeup36 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.1/0000:03:00.0/wakeup/wakeup36 +E: SUBSYSTEM=wakeup + +P: /devices/pci0000:00/0000:00:14.1/pci_bus/0000:03 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.1/pci_bus/0000:03 +E: SUBSYSTEM=pci_bus + +P: /devices/pci0000:00/0000:00:14.1/wakeup/wakeup10 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:14.1/wakeup/wakeup10 +E: SUBSYSTEM=wakeup + +P: /devices/pci0000:00/0000:00:15.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0 +E: SUBSYSTEM=pci +E: DRIVER=xhci_hcd +E: PCI_CLASS=C0330 +E: PCI_ID=8086:5AA8 +E: PCI_SUBSYS_ID=8086:7270 +E: PCI_SLOT_NAME=0000:00:15.0 +E: MODALIAS=pci:v00008086d00005AA8sv00008086sd00007270bc0Csc03i30 +E: USEC_INITIALIZED=14118705 +E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller +E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series USB xHCI + +P: /devices/pci0000:00/0000:00:15.0/intel_xhci_usb_sw +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/intel_xhci_usb_sw +E: SUBSYSTEM=platform +E: DRIVER=intel_xhci_usb_sw +E: MODALIAS=platform:intel_xhci_usb_sw +E: USEC_INITIALIZED=14121186 +E: ID_PATH=pci-0000:00:15.0-platform-intel_xhci_usb_sw +E: ID_PATH_TAG=pci-0000_00_15_0-platform-intel_xhci_usb_sw + +P: /devices/pci0000:00/0000:00:15.0/intel_xhci_usb_sw/usb_role/intel_xhci_usb_sw-role-switch +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/intel_xhci_usb_sw/usb_role/intel_xhci_usb_sw-role-switch +E: SUBSYSTEM=usb_role +E: DEVTYPE=usb_role_switch +E: USB_ROLE_SWITCH=intel_xhci_usb_sw-role-switch + +P: /devices/pci0000:00/0000:00:15.0/usb1 +N: bus/usb/001/001 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1 +E: SUBSYSTEM=usb +E: DEVNAME=/dev/bus/usb/001/001 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: PRODUCT=1d6b/2/504 +E: TYPE=9/0/1 +E: BUSNUM=001 +E: DEVNUM=001 +E: MAJOR=189 +E: MINOR=0 +E: USEC_INITIALIZED=14128812 +E: ID_VENDOR=Linux_5.4.0-72-generic_xhci-hcd +E: ID_VENDOR_ENC=Linux\x205.4.0-72-generic\x20xhci-hcd +E: ID_VENDOR_ID=1d6b +E: ID_MODEL=xHCI_Host_Controller +E: ID_MODEL_ENC=xHCI\x20Host\x20Controller +E: ID_MODEL_ID=0002 +E: ID_REVISION=0504 +E: ID_SERIAL=Linux_5.4.0-72-generic_xhci-hcd_xHCI_Host_Controller_0000:00:15.0 +E: ID_SERIAL_SHORT=0000:00:15.0 +E: ID_BUS=usb +E: ID_USB_INTERFACES=:090000: +E: ID_VENDOR_FROM_DATABASE=Linux Foundation +E: ID_MODEL_FROM_DATABASE=2.0 root hub +E: ID_PATH=pci-0000:00:15.0 +E: ID_PATH_TAG=pci-0000_00_15_0 +E: ID_FOR_SEAT=usb-pci-0000_00_15_0 +E: TAGS=:snap_everactive-firmware-utilities_hook_install:seat:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_sensor-radio-version: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-0:1.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-0:1.0 +E: SUBSYSTEM=usb +E: DEVTYPE=usb_interface +E: DRIVER=hub +E: PRODUCT=1d6b/2/504 +E: TYPE=9/0/1 +E: INTERFACE=9/0/0 +E: MODALIAS=usb:v1D6Bp0002d0504dc09dsc00dp01ic09isc00ip00in00 +E: USEC_INITIALIZED=14351531 +E: ID_USB_CLASS_FROM_DATABASE=Hub +E: ID_USB_PROTOCOL_FROM_DATABASE=Single TT +E: ID_VENDOR_FROM_DATABASE=Linux Foundation +E: ID_MODEL_FROM_DATABASE=2.0 root hub +E: ID_PATH=pci-0000:00:15.0-usb-0:0:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_0_1_0 +E: TAGS=:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_sensor-radio-version: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-1 +N: bus/usb/001/002 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-1 +E: SUBSYSTEM=usb +E: DEVNAME=/dev/bus/usb/001/002 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: PRODUCT=3342/1/200 +E: TYPE=2/2/0 +E: BUSNUM=001 +E: DEVNUM=002 +E: MAJOR=189 +E: MINOR=1 +E: USEC_INITIALIZED=14356747 +E: ID_VENDOR=Everactive +E: ID_VENDOR_ENC=Everactive +E: ID_VENDOR_ID=3342 +E: ID_MODEL=apex-management-controller +E: ID_MODEL_ENC=apex-management-controller +E: ID_MODEL_ID=0001 +E: ID_REVISION=0200 +E: ID_SERIAL=Everactive_apex-management-controller_207134A24E46 +E: ID_SERIAL_SHORT=207134A24E46 +E: ID_BUS=usb +E: ID_USB_INTERFACES=:020201:0a0000: +E: ID_PATH=pci-0000:00:15.0-usb-0:1 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_1 +E: TAGS=:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_sensor-radio-update-no-reload: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-1/1-1:1.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-1/1-1:1.0 +E: SUBSYSTEM=usb +E: DEVTYPE=usb_interface +E: DRIVER=cdc_acm +E: PRODUCT=3342/1/200 +E: TYPE=2/2/0 +E: INTERFACE=2/2/1 +E: MODALIAS=usb:v3342p0001d0200dc02dsc02dp00ic02isc02ip01in00 +E: USEC_INITIALIZED=14525331 +E: ID_USB_CLASS_FROM_DATABASE=Communications +E: ID_USB_SUBCLASS_FROM_DATABASE=Abstract (modem) +E: ID_PATH=pci-0000:00:15.0-usb-0:1:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_1_1_0 +E: TAGS=:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_sensor-radio-update-no-reload: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-1/1-1:1.0/tty/ttyACM0 +N: ttyACM0 +L: 0 +S: serial/by-path/pci-0000:00:15.0-usb-0:1:1.0 +S: serial/by-id/usb-Everactive_apex-management-controller_207134A24E46-if00 +S: serial-port-apexmanagementcontroller +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-1/1-1:1.0/tty/ttyACM0 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyACM0 +E: MAJOR=166 +E: MINOR=0 +E: USEC_INITIALIZED=16987561 +E: ID_BUS=usb +E: ID_VENDOR_ID=3342 +E: ID_MODEL_ID=0001 +E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller +E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series USB xHCI +E: ID_VENDOR=Everactive +E: ID_VENDOR_ENC=Everactive +E: ID_MODEL=apex-management-controller +E: ID_MODEL_ENC=apex-management-controller +E: ID_REVISION=0200 +E: ID_SERIAL=Everactive_apex-management-controller_207134A24E46 +E: ID_SERIAL_SHORT=207134A24E46 +E: ID_TYPE=generic +E: ID_USB_INTERFACES=:020201:0a0000: +E: ID_USB_INTERFACE_NUM=00 +E: ID_USB_DRIVER=cdc_acm +E: ID_USB_CLASS_FROM_DATABASE=Communications +E: ID_USB_SUBCLASS_FROM_DATABASE=Abstract (modem) +E: ID_PATH=pci-0000:00:15.0-usb-0:1:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_1_1_0 +E: ID_MM_CANDIDATE=1 +E: DEVLINKS=/dev/serial/by-path/pci-0000:00:15.0-usb-0:1:1.0 /dev/serial/by-id/usb-Everactive_apex-management-controller_207134A24E46-if00 /dev/serial-port-apexmanagementcontroller +E: TAGS=:snap_network-manager_networkmanager:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_mc-update:snap_modem-manager_mbimcli:snap_modem-manager_mbim-network:snap_modem-manager_qmi-network:snap_modem-manager_modemmanager:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_sensor-radio-version:snap_modem-manager_qmicli:systemd:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_sensor-radio-update: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-1/1-1:1.1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-1/1-1:1.1 +E: SUBSYSTEM=usb +E: DEVTYPE=usb_interface +E: DRIVER=cdc_acm +E: PRODUCT=3342/1/200 +E: TYPE=2/2/0 +E: INTERFACE=10/0/0 +E: MODALIAS=usb:v3342p0001d0200dc02dsc02dp00ic0Aisc00ip00in01 +E: USEC_INITIALIZED=14532958 +E: ID_USB_CLASS_FROM_DATABASE=Communications +E: ID_USB_SUBCLASS_FROM_DATABASE=Abstract (modem) +E: ID_PATH=pci-0000:00:15.0-usb-0:1:1.1 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_1_1_1 +E: TAGS=:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_sensor-radio-update-no-reload: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-2 +N: bus/usb/001/003 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-2 +E: SUBSYSTEM=usb +E: DEVNAME=/dev/bus/usb/001/003 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: PRODUCT=8087/25/2 +E: TYPE=224/1/1 +E: BUSNUM=001 +E: DEVNUM=003 +E: MAJOR=189 +E: MINOR=2 +E: USEC_INITIALIZED=14359071 +E: ID_VENDOR=8087 +E: ID_VENDOR_ENC=8087 +E: ID_VENDOR_ID=8087 +E: ID_MODEL=0025 +E: ID_MODEL_ENC=0025 +E: ID_MODEL_ID=0025 +E: ID_REVISION=0002 +E: ID_SERIAL=8087_0025 +E: ID_BUS=usb +E: ID_USB_INTERFACES=:e00101: +E: ID_VENDOR_FROM_DATABASE=Intel Corp. +E: ID_PATH=pci-0000:00:15.0-usb-0:2 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_2 +E: TAGS=:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_sensor-radio-update: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.0 +E: SUBSYSTEM=usb +E: DEVTYPE=usb_interface +E: DRIVER=btusb +E: PRODUCT=8087/25/2 +E: TYPE=224/1/1 +E: INTERFACE=224/1/1 +E: MODALIAS=usb:v8087p0025d0002dcE0dsc01dp01icE0isc01ip01in00 +E: USEC_INITIALIZED=14534424 +E: ID_USB_CLASS_FROM_DATABASE=Wireless +E: ID_USB_SUBCLASS_FROM_DATABASE=Radio Frequency +E: ID_USB_PROTOCOL_FROM_DATABASE=Bluetooth +E: ID_VENDOR_FROM_DATABASE=Intel Corp. +E: ID_PATH=pci-0000:00:15.0-usb-0:2:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_2_1_0 +E: TAGS=:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_sensor-radio-update-no-reload: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.0/bluetooth/hci0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.0/bluetooth/hci0 +E: SUBSYSTEM=bluetooth +E: DEVTYPE=host +E: USEC_INITIALIZED=18233223 +E: ID_VENDOR=8087 +E: ID_VENDOR_ENC=8087 +E: ID_VENDOR_ID=8087 +E: ID_MODEL=0025 +E: ID_MODEL_ENC=0025 +E: ID_MODEL_ID=0025 +E: ID_REVISION=0002 +E: ID_SERIAL=8087_0025 +E: ID_TYPE=generic +E: ID_BUS=usb +E: ID_USB_INTERFACES=:e00101: +E: ID_USB_INTERFACE_NUM=00 +E: ID_USB_DRIVER=btusb +E: SYSTEMD_ALIAS=/sys/subsystem/bluetooth/devices/hci0 +E: SYSTEMD_WANTS=bluetooth.target +E: SYSTEMD_USER_WANTS=bluetooth.target +E: TAGS=:systemd:snap_everactive-gateway-services_receiver: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.0/bluetooth/hci0/rfkill1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.0/bluetooth/hci0/rfkill1 +E: SUBSYSTEM=rfkill +E: RFKILL_NAME=hci0 +E: RFKILL_TYPE=bluetooth +E: RFKILL_STATE=1 +E: USEC_INITIALIZED=18285043 +E: ID_VENDOR=8087 +E: ID_VENDOR_ENC=8087 +E: ID_VENDOR_ID=8087 +E: ID_MODEL=0025 +E: ID_MODEL_ENC=0025 +E: ID_MODEL_ID=0025 +E: ID_REVISION=0002 +E: ID_SERIAL=8087_0025 +E: ID_TYPE=generic +E: ID_BUS=usb +E: ID_USB_INTERFACES=:e00101: +E: ID_USB_INTERFACE_NUM=00 +E: ID_USB_DRIVER=btusb +E: SYSTEMD_RFKILL=1 +E: ID_PATH=pci-0000:00:15.0-usb-0:2:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_2_1_0 + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.1 +E: SUBSYSTEM=usb +E: DEVTYPE=usb_interface +E: DRIVER=btusb +E: PRODUCT=8087/25/2 +E: TYPE=224/1/1 +E: INTERFACE=224/1/1 +E: MODALIAS=usb:v8087p0025d0002dcE0dsc01dp01icE0isc01ip01in01 +E: USEC_INITIALIZED=14538459 +E: ID_USB_CLASS_FROM_DATABASE=Wireless +E: ID_USB_SUBCLASS_FROM_DATABASE=Radio Frequency +E: ID_USB_PROTOCOL_FROM_DATABASE=Bluetooth +E: ID_VENDOR_FROM_DATABASE=Intel Corp. +E: ID_PATH=pci-0000:00:15.0-usb-0:2:1.1 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_2_1_1 +E: TAGS=:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_sensor-radio-update: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8 +N: bus/usb/001/004 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8 +E: SUBSYSTEM=usb +E: DEVNAME=/dev/bus/usb/001/004 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: PRODUCT=424/2514/bb3 +E: TYPE=9/0/2 +E: BUSNUM=001 +E: DEVNUM=004 +E: MAJOR=189 +E: MINOR=3 +E: USEC_INITIALIZED=14465597 +E: ID_VENDOR=0424 +E: ID_VENDOR_ENC=0424 +E: ID_VENDOR_ID=0424 +E: ID_MODEL=2514 +E: ID_MODEL_ENC=2514 +E: ID_MODEL_ID=2514 +E: ID_REVISION=0bb3 +E: ID_SERIAL=0424_2514 +E: ID_BUS=usb +E: ID_USB_INTERFACES=:090001:090002: +E: ID_VENDOR_FROM_DATABASE=Microchip Technology, Inc. (formerly SMSC) +E: ID_MODEL_FROM_DATABASE=USB 2.0 Hub +E: ID_PATH=pci-0000:00:15.0-usb-0:8 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8 +E: ID_FOR_SEAT=usb-pci-0000_00_15_0-usb-0_8 +E: TAGS=:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_mc-activate:seat:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_mc-update: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.3 +N: bus/usb/001/005 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.3 +E: SUBSYSTEM=usb +E: DEVNAME=/dev/bus/usb/001/005 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: PRODUCT=483/df11/2200 +E: TYPE=0/0/0 +E: BUSNUM=001 +E: DEVNUM=005 +E: MAJOR=189 +E: MINOR=4 +E: USEC_INITIALIZED=14685620 +E: ID_VENDOR=STMicroelectronics +E: ID_VENDOR_ENC=STMicroelectronics +E: ID_VENDOR_ID=0483 +E: ID_MODEL=STM32_BOOTLOADER +E: ID_MODEL_ENC=STM32\x20\x20BOOTLOADER +E: ID_MODEL_ID=df11 +E: ID_REVISION=2200 +E: ID_SERIAL=STMicroelectronics_STM32_BOOTLOADER_2043338B5252 +E: ID_SERIAL_SHORT=2043338B5252 +E: ID_BUS=usb +E: ID_USB_INTERFACES=:fe0102: +E: ID_VENDOR_FROM_DATABASE=STMicroelectronics +E: ID_MODEL_FROM_DATABASE=STM Device in DFU Mode +E: ID_PATH=pci-0000:00:15.0-usb-0:8.3 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_3 +E: TAGS=:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_sensor-radio-version: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.3/1-8.3:1.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.3/1-8.3:1.0 +E: SUBSYSTEM=usb +E: DEVTYPE=usb_interface +E: PRODUCT=483/df11/2200 +E: TYPE=0/0/0 +E: INTERFACE=254/1/2 +E: MODALIAS=usb:v0483pDF11d2200dc00dsc00dp00icFEisc01ip02in00 +E: USEC_INITIALIZED=14855457 +E: ID_VENDOR_FROM_DATABASE=STMicroelectronics +E: ID_MODEL_FROM_DATABASE=STM Device in DFU Mode +E: ID_PATH=pci-0000:00:15.0-usb-0:8.3:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_3_1_0 +E: TAGS=:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_hook_install: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4 +N: bus/usb/001/006 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4 +E: SUBSYSTEM=usb +E: DEVNAME=/dev/bus/usb/001/006 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: PRODUCT=413c/2113/110 +E: TYPE=0/0/0 +E: BUSNUM=001 +E: DEVNUM=006 +E: MAJOR=189 +E: MINOR=5 +E: USEC_INITIALIZED=14702119 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_VENDOR_FROM_DATABASE=Dell Computer Corp. +E: ID_PATH=pci-0000:00:15.0-usb-0:8.4 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_4 +E: TAGS=:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_utilities-daemon: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0 +E: SUBSYSTEM=usb +E: DEVTYPE=usb_interface +E: DRIVER=usbhid +E: PRODUCT=413c/2113/110 +E: TYPE=0/0/0 +E: INTERFACE=3/1/1 +E: MODALIAS=usb:v413Cp2113d0110dc00dsc00dp00ic03isc01ip01in00 +E: USEC_INITIALIZED=14865181 +E: ID_VENDOR_FROM_DATABASE=Dell Computer Corp. +E: ID_PATH=pci-0000:00:15.0-usb-0:8.4:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_4_1_0 +E: TAGS=:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_mc-activate: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001 +E: SUBSYSTEM=hid +E: DRIVER=hid-generic +E: HID_ID=0003:0000413C:00002113 +E: HID_NAME=Dell KB216 Wired Keyboard +E: HID_PHYS=usb-0000:00:15.0-8.4/input0 +E: HID_UNIQ= +E: MODALIAS=hid:b0003g0001v0000413Cp00002113 +E: USEC_INITIALIZED=15012963 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=00 +E: ID_USB_DRIVER=usbhid + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/hidraw/hidraw0 +N: hidraw0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/hidraw/hidraw0 +E: SUBSYSTEM=hidraw +E: DEVNAME=/dev/hidraw0 +E: MAJOR=240 +E: MINOR=0 +E: USEC_INITIALIZED=15121190 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=00 +E: ID_USB_DRIVER=usbhid + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/input/input3 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/input/input3 +E: SUBSYSTEM=input +E: PRODUCT=3/413c/2113/111 +E: NAME="Dell KB216 Wired Keyboard" +E: PHYS="usb-0000:00:15.0-8.4/input0" +E: UNIQ="" +E: PROP=0 +E: EV=120013 +E: KEY=1000000000007 ff9f207ac14057ff febeffdfffefffff fffffffffffffffe +E: MSC=10 +E: LED=1f +E: MODALIAS=input:b0003v413Cp2113e0111-e0,1,4,11,14,k71,72,73,74,75,77,79,7A,7B,7C,7D,7E,7F,80,81,82,83,84,85,86,87,88,89,8A,8C,8E,96,98,9E,9F,A1,A3,A4,A5,A6,AD,B0,B1,B2,B3,B4,B7,B8,B9,BA,BB,BC,BD,BE,BF,C0,C1,C2,F0,ram4,l0,1,2,3,4,sfw +E: USEC_INITIALIZED=15069619 +E: ID_INPUT=1 +E: ID_INPUT_KEY=1 +E: ID_INPUT_KEYBOARD=1 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=00 +E: ID_USB_DRIVER=usbhid +E: ID_PATH=pci-0000:00:15.0-usb-0:8.4:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_4_1_0 +E: ID_FOR_SEAT=input-pci-0000_00_15_0-usb-0_8_4_1_0 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/input/input3/event3 +N: input/event3 +L: 0 +S: input/by-path/pci-0000:00:15.0-usb-0:8.4:1.0-event-kbd +S: input/by-id/usb-413c_Dell_KB216_Wired_Keyboard-event-kbd +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/input/input3/event3 +E: SUBSYSTEM=input +E: DEVNAME=/dev/input/event3 +E: MAJOR=13 +E: MINOR=67 +E: USEC_INITIALIZED=15174734 +E: ID_INPUT=1 +E: ID_INPUT_KEY=1 +E: ID_INPUT_KEYBOARD=1 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=00 +E: ID_USB_DRIVER=usbhid +E: ID_PATH=pci-0000:00:15.0-usb-0:8.4:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_4_1_0 +E: DEVLINKS=/dev/input/by-path/pci-0000:00:15.0-usb-0:8.4:1.0-event-kbd /dev/input/by-id/usb-413c_Dell_KB216_Wired_Keyboard-event-kbd +E: TAGS=:power-switch: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/input/input3/input3::capslock +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/input/input3/input3::capslock +E: SUBSYSTEM=leds +E: USEC_INITIALIZED=17549661 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=00 +E: ID_USB_DRIVER=usbhid +E: ID_PATH=pci-0000:00:15.0-usb-0:8.4:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_4_1_0 +E: ID_FOR_SEAT=leds-pci-0000_00_15_0-usb-0_8_4_1_0 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/input/input3/input3::compose +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/input/input3/input3::compose +E: SUBSYSTEM=leds +E: USEC_INITIALIZED=17580993 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=00 +E: ID_USB_DRIVER=usbhid +E: ID_PATH=pci-0000:00:15.0-usb-0:8.4:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_4_1_0 +E: ID_FOR_SEAT=leds-pci-0000_00_15_0-usb-0_8_4_1_0 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/input/input3/input3::kana +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/input/input3/input3::kana +E: SUBSYSTEM=leds +E: USEC_INITIALIZED=17572244 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=00 +E: ID_USB_DRIVER=usbhid +E: ID_PATH=pci-0000:00:15.0-usb-0:8.4:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_4_1_0 +E: ID_FOR_SEAT=leds-pci-0000_00_15_0-usb-0_8_4_1_0 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/input/input3/input3::numlock +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/input/input3/input3::numlock +E: SUBSYSTEM=leds +E: USEC_INITIALIZED=17537375 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=00 +E: ID_USB_DRIVER=usbhid +E: ID_PATH=pci-0000:00:15.0-usb-0:8.4:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_4_1_0 +E: ID_FOR_SEAT=leds-pci-0000_00_15_0-usb-0_8_4_1_0 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/input/input3/input3::scrolllock +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.0/0003:413C:2113.0001/input/input3/input3::scrolllock +E: SUBSYSTEM=leds +E: USEC_INITIALIZED=17574230 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=00 +E: ID_USB_DRIVER=usbhid +E: ID_PATH=pci-0000:00:15.0-usb-0:8.4:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_4_1_0 +E: ID_FOR_SEAT=leds-pci-0000_00_15_0-usb-0_8_4_1_0 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.1 +E: SUBSYSTEM=usb +E: DEVTYPE=usb_interface +E: DRIVER=usbhid +E: PRODUCT=413c/2113/110 +E: TYPE=0/0/0 +E: INTERFACE=3/0/0 +E: MODALIAS=usb:v413Cp2113d0110dc00dsc00dp00ic03isc00ip00in01 +E: USEC_INITIALIZED=14863323 +E: ID_VENDOR_FROM_DATABASE=Dell Computer Corp. +E: ID_PATH=pci-0000:00:15.0-usb-0:8.4:1.1 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_4_1_1 +E: TAGS=:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_hook_install: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.1/0003:413C:2113.0002 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.1/0003:413C:2113.0002 +E: SUBSYSTEM=hid +E: DRIVER=hid-generic +E: HID_ID=0003:0000413C:00002113 +E: HID_NAME=Dell KB216 Wired Keyboard +E: HID_PHYS=usb-0000:00:15.0-8.4/input1 +E: HID_UNIQ= +E: MODALIAS=hid:b0003g0001v0000413Cp00002113 +E: USEC_INITIALIZED=14987216 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=01 +E: ID_USB_DRIVER=usbhid + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.1/0003:413C:2113.0002/hidraw/hidraw1 +N: hidraw1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.1/0003:413C:2113.0002/hidraw/hidraw1 +E: SUBSYSTEM=hidraw +E: DEVNAME=/dev/hidraw1 +E: MAJOR=240 +E: MINOR=1 +E: USEC_INITIALIZED=15050973 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=01 +E: ID_USB_DRIVER=usbhid + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.1/0003:413C:2113.0002/input/input4 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.1/0003:413C:2113.0002/input/input4 +E: SUBSYSTEM=input +E: PRODUCT=3/413c/2113/111 +E: NAME="Dell KB216 Wired Keyboard Consumer Control" +E: PHYS="usb-0000:00:15.0-8.4/input1" +E: UNIQ="" +E: PROP=0 +E: EV=1f +E: KEY=300ff 0 0 483ffff17aff32d bfd4444600000000 1 130c730b17c000 267bfad9415fed 9e168000004400 10000002 +E: REL=1040 +E: ABS=100000000 +E: MSC=10 +E: MODALIAS=input:b0003v413Cp2113e0111-e0,1,2,3,4,k71,72,73,74,77,80,82,83,85,86,87,88,89,8A,8B,8C,8E,90,96,98,9B,9C,9E,9F,A1,A3,A4,A5,A6,A7,A8,A9,AB,AC,AD,AE,B1,B2,B5,CE,CF,D0,D1,D2,D4,D8,D9,DB,E0,E1,E4,E5,E6,EA,EB,F0,F1,F4,100,161,162,166,16A,16E,172,174,176,177,178,179,17A,17B,17C,17D,17F,180,182,183,185,188,189,18C,18D,18E,18F,190,191,192,193,195,197,198,199,19A,19C,1A0,1A1,1A2,1A3,1A4,1A5,1A6,1A7,1A8,1A9,1AA,1AB,1AC,1AD,1AE,1AF,1B0,1B1,1B7,1BA,240,241,242,243,244,245,246,247,250,251,r6,C,a20,m4,lsfw +E: USEC_INITIALIZED=15014063 +E: ID_INPUT=1 +E: ID_INPUT_KEY=1 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=01 +E: ID_USB_DRIVER=usbhid +E: ID_PATH=pci-0000:00:15.0-usb-0:8.4:1.1 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_4_1_1 +E: ID_FOR_SEAT=input-pci-0000_00_15_0-usb-0_8_4_1_1 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.1/0003:413C:2113.0002/input/input4/event4 +N: input/event4 +L: 0 +S: input/by-id/usb-413c_Dell_KB216_Wired_Keyboard-event-if01 +S: input/by-path/pci-0000:00:15.0-usb-0:8.4:1.1-event +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.1/0003:413C:2113.0002/input/input4/event4 +E: SUBSYSTEM=input +E: DEVNAME=/dev/input/event4 +E: MAJOR=13 +E: MINOR=68 +E: USEC_INITIALIZED=15145501 +E: ID_INPUT=1 +E: ID_INPUT_KEY=1 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=01 +E: ID_USB_DRIVER=usbhid +E: ID_PATH=pci-0000:00:15.0-usb-0:8.4:1.1 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_4_1_1 +E: DEVLINKS=/dev/input/by-id/usb-413c_Dell_KB216_Wired_Keyboard-event-if01 /dev/input/by-path/pci-0000:00:15.0-usb-0:8.4:1.1-event +E: TAGS=:power-switch: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.1/0003:413C:2113.0002/input/input5 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.1/0003:413C:2113.0002/input/input5 +E: SUBSYSTEM=input +E: PRODUCT=3/413c/2113/111 +E: NAME="Dell KB216 Wired Keyboard System Control" +E: PHYS="usb-0000:00:15.0-8.4/input1" +E: UNIQ="" +E: PROP=0 +E: EV=13 +E: KEY=c000 10000000000000 0 +E: MSC=10 +E: MODALIAS=input:b0003v413Cp2113e0111-e0,1,4,k74,8E,8F,ram4,lsfw +E: USEC_INITIALIZED=15020944 +E: ID_INPUT=1 +E: ID_INPUT_KEY=1 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=01 +E: ID_USB_DRIVER=usbhid +E: ID_PATH=pci-0000:00:15.0-usb-0:8.4:1.1 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_4_1_1 +E: ID_FOR_SEAT=input-pci-0000_00_15_0-usb-0_8_4_1_1 +E: TAGS=:seat: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.1/0003:413C:2113.0002/input/input5/event5 +N: input/event5 +L: 0 +S: input/by-id/usb-413c_Dell_KB216_Wired_Keyboard-event-if01 +S: input/by-path/pci-0000:00:15.0-usb-0:8.4:1.1-event +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/1-8.4:1.1/0003:413C:2113.0002/input/input5/event5 +E: SUBSYSTEM=input +E: DEVNAME=/dev/input/event5 +E: MAJOR=13 +E: MINOR=69 +E: USEC_INITIALIZED=15088105 +E: ID_INPUT=1 +E: ID_INPUT_KEY=1 +E: ID_VENDOR=413c +E: ID_VENDOR_ENC=413c +E: ID_VENDOR_ID=413c +E: ID_MODEL=Dell_KB216_Wired_Keyboard +E: ID_MODEL_ENC=Dell\x20KB216\x20Wired\x20Keyboard +E: ID_MODEL_ID=2113 +E: ID_REVISION=0110 +E: ID_SERIAL=413c_Dell_KB216_Wired_Keyboard +E: ID_TYPE=hid +E: ID_BUS=usb +E: ID_USB_INTERFACES=:030101:030000: +E: ID_USB_INTERFACE_NUM=01 +E: ID_USB_DRIVER=usbhid +E: ID_PATH=pci-0000:00:15.0-usb-0:8.4:1.1 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_4_1_1 +E: DEVLINKS=/dev/input/by-id/usb-413c_Dell_KB216_Wired_Keyboard-event-if01 /dev/input/by-path/pci-0000:00:15.0-usb-0:8.4:1.1-event +E: TAGS=:power-switch: + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/wakeup/wakeup30 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8.4/wakeup/wakeup30 +E: SUBSYSTEM=wakeup + +P: /devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8:1.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb1/1-8/1-8:1.0 +E: SUBSYSTEM=usb +E: DEVTYPE=usb_interface +E: DRIVER=hub +E: PRODUCT=424/2514/bb3 +E: TYPE=9/0/2 +E: INTERFACE=9/0/2 +E: MODALIAS=usb:v0424p2514d0BB3dc09dsc00dp02ic09isc00ip02in00 +E: USEC_INITIALIZED=14677237 +E: ID_USB_CLASS_FROM_DATABASE=Hub +E: ID_USB_PROTOCOL_FROM_DATABASE=TT per port +E: ID_VENDOR_FROM_DATABASE=Microchip Technology, Inc. (formerly SMSC) +E: ID_MODEL_FROM_DATABASE=USB 2.0 Hub +E: ID_PATH=pci-0000:00:15.0-usb-0:8:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_8_1_0 +E: TAGS=:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_sensor-radio-version: + +P: /devices/pci0000:00/0000:00:15.0/usb2 +N: bus/usb/002/001 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2 +E: SUBSYSTEM=usb +E: DEVNAME=/dev/bus/usb/002/001 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: PRODUCT=1d6b/3/504 +E: TYPE=9/0/3 +E: BUSNUM=002 +E: DEVNUM=001 +E: MAJOR=189 +E: MINOR=128 +E: USEC_INITIALIZED=14141874 +E: ID_VENDOR=Linux_5.4.0-72-generic_xhci-hcd +E: ID_VENDOR_ENC=Linux\x205.4.0-72-generic\x20xhci-hcd +E: ID_VENDOR_ID=1d6b +E: ID_MODEL=xHCI_Host_Controller +E: ID_MODEL_ENC=xHCI\x20Host\x20Controller +E: ID_MODEL_ID=0003 +E: ID_REVISION=0504 +E: ID_SERIAL=Linux_5.4.0-72-generic_xhci-hcd_xHCI_Host_Controller_0000:00:15.0 +E: ID_SERIAL_SHORT=0000:00:15.0 +E: ID_BUS=usb +E: ID_USB_INTERFACES=:090000: +E: ID_VENDOR_FROM_DATABASE=Linux Foundation +E: ID_MODEL_FROM_DATABASE=3.0 root hub +E: ID_PATH=pci-0000:00:15.0 +E: ID_PATH_TAG=pci-0000_00_15_0 +E: ID_FOR_SEAT=usb-pci-0000_00_15_0 +E: TAGS=:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:seat:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_mc-update: + +P: /devices/pci0000:00/0000:00:15.0/usb2/2-0:1.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2/2-0:1.0 +E: SUBSYSTEM=usb +E: DEVTYPE=usb_interface +E: DRIVER=hub +E: PRODUCT=1d6b/3/504 +E: TYPE=9/0/3 +E: INTERFACE=9/0/0 +E: MODALIAS=usb:v1D6Bp0003d0504dc09dsc00dp03ic09isc00ip00in00 +E: USEC_INITIALIZED=14312878 +E: ID_USB_CLASS_FROM_DATABASE=Hub +E: ID_VENDOR_FROM_DATABASE=Linux Foundation +E: ID_MODEL_FROM_DATABASE=3.0 root hub +E: ID_PATH=pci-0000:00:15.0-usb-0:0:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_0_1_0 +E: TAGS=:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_mc-activate: + +P: /devices/pci0000:00/0000:00:15.0/usb2/2-6 +N: bus/usb/002/002 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2/2-6 +E: SUBSYSTEM=usb +E: DEVNAME=/dev/bus/usb/002/002 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: PRODUCT=1199/9091/6 +E: TYPE=0/0/0 +E: BUSNUM=002 +E: DEVNUM=002 +E: MAJOR=189 +E: MINOR=129 +E: USEC_INITIALIZED=14435016 +E: ID_VENDOR=Sierra_Wireless__Incorporated +E: ID_VENDOR_ENC=Sierra\x20Wireless\x2c\x20Incorporated +E: ID_VENDOR_ID=1199 +E: ID_MODEL=Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A +E: ID_MODEL_ENC=Sierra\x20Wireless\x20EM7411\x20Qualcomm®\x20Snapdragon™\x20X16\x20LTE-A +E: ID_MODEL_ID=9091 +E: ID_REVISION=0006 +E: ID_SERIAL=Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06 +E: ID_SERIAL_SHORT=8F0224006904AB06 +E: ID_BUS=usb +E: ID_USB_INTERFACES=:ffffff:ff0000: +E: ID_VENDOR_FROM_DATABASE=Sierra Wireless, Inc. +E: ID_PATH=pci-0000:00:15.0-usb-0:6 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_6 +E: TAGS=:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_hook_install: + +P: /devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.0 +E: SUBSYSTEM=usb +E: DEVTYPE=usb_interface +E: DRIVER=qcserial +E: PRODUCT=1199/9091/6 +E: TYPE=0/0/0 +E: INTERFACE=255/255/255 +E: MODALIAS=usb:v1199p9091d0006dc00dsc00dp00icFFiscFFipFFin00 +E: USEC_INITIALIZED=14637679 +E: ID_VENDOR_FROM_DATABASE=Sierra Wireless, Inc. +E: ID_PATH=pci-0000:00:15.0-usb-0:6:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_6_1_0 +E: TAGS=:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_mc-activate: + +P: /devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.0/ttyUSB0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.0/ttyUSB0 +E: SUBSYSTEM=usb-serial +E: DRIVER=qcserial +E: USEC_INITIALIZED=17170075 +E: ID_VENDOR=Sierra_Wireless__Incorporated +E: ID_VENDOR_ENC=Sierra\x20Wireless\x2c\x20Incorporated +E: ID_VENDOR_ID=1199 +E: ID_MODEL=Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A +E: ID_MODEL_ENC=Sierra\x20Wireless\x20EM7411\x20Qualcomm®\x20Snapdragon™\x20X16\x20LTE-A +E: ID_MODEL_ID=9091 +E: ID_REVISION=0006 +E: ID_SERIAL=Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06 +E: ID_SERIAL_SHORT=8F0224006904AB06 +E: ID_TYPE=generic +E: ID_BUS=usb +E: ID_USB_INTERFACES=:ffffff:ff0000: +E: ID_USB_INTERFACE_NUM=00 +E: ID_USB_DRIVER=qcserial +E: TAGS=:snap_modem-manager_modemmanager:snap_network-manager_networkmanager:snap_modem-manager_mbim-network:snap_modem-manager_mbimcli:snap_modem-manager_qmicli:snap_modem-manager_qmi-network: + +P: /devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.0/ttyUSB0/tty/ttyUSB0 +N: ttyUSB0 +L: 0 +S: serial/by-id/usb-Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06-if00-port0 +S: serial/by-path/pci-0000:00:15.0-usb-0:6:1.0-port0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.0/ttyUSB0/tty/ttyUSB0 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyUSB0 +E: MAJOR=188 +E: MINOR=0 +E: USEC_INITIALIZED=17951537 +E: ID_BUS=usb +E: ID_VENDOR_ID=1199 +E: ID_MODEL_ID=9091 +E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller +E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI +E: ID_VENDOR_FROM_DATABASE=Sierra Wireless, Inc. +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series USB xHCI +E: ID_VENDOR=Sierra_Wireless__Incorporated +E: ID_VENDOR_ENC=Sierra\x20Wireless\x2c\x20Incorporated +E: ID_MODEL=Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A +E: ID_MODEL_ENC=Sierra\x20Wireless\x20EM7411\x20Qualcomm®\x20Snapdragon™\x20X16\x20LTE-A +E: ID_REVISION=0006 +E: ID_SERIAL=Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06 +E: ID_SERIAL_SHORT=8F0224006904AB06 +E: ID_TYPE=generic +E: ID_USB_INTERFACES=:ffffff:ff0000: +E: ID_USB_INTERFACE_NUM=00 +E: ID_USB_DRIVER=qcserial +E: ID_PATH=pci-0000:00:15.0-usb-0:6:1.0 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_6_1_0 +E: ID_MM_CANDIDATE=1 +E: DEVLINKS=/dev/serial/by-id/usb-Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06-if00-port0 /dev/serial/by-path/pci-0000:00:15.0-usb-0:6:1.0-port0 +E: TAGS=:snap_everactive-firmware-utilities_sensor-radio-update:systemd:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_modem-manager_qmicli:snap_everactive-firmware-utilities_sensor-radio-version:snap_modem-manager_modemmanager:snap_modem-manager_qmi-network:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_mc-update:snap_modem-manager_mbim-network:snap_everactive-firmware-utilities_utilities-daemon:snap_network-manager_networkmanager:snap_modem-manager_mbimcli:snap_everactive-firmware-utilities_mc-status: + +P: /devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.2 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.2 +E: SUBSYSTEM=usb +E: DEVTYPE=usb_interface +E: DRIVER=qcserial +E: PRODUCT=1199/9091/6 +E: TYPE=0/0/0 +E: INTERFACE=255/0/0 +E: MODALIAS=usb:v1199p9091d0006dc00dsc00dp00icFFisc00ip00in02 +E: USEC_INITIALIZED=14601220 +E: ID_VENDOR_FROM_DATABASE=Sierra Wireless, Inc. +E: ID_PATH=pci-0000:00:15.0-usb-0:6:1.2 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_6_1_2 +E: TAGS=:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_mc-update: + +P: /devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.2/ttyUSB1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.2/ttyUSB1 +E: SUBSYSTEM=usb-serial +E: DRIVER=qcserial +E: USEC_INITIALIZED=17084468 +E: ID_VENDOR=Sierra_Wireless__Incorporated +E: ID_VENDOR_ENC=Sierra\x20Wireless\x2c\x20Incorporated +E: ID_VENDOR_ID=1199 +E: ID_MODEL=Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A +E: ID_MODEL_ENC=Sierra\x20Wireless\x20EM7411\x20Qualcomm®\x20Snapdragon™\x20X16\x20LTE-A +E: ID_MODEL_ID=9091 +E: ID_REVISION=0006 +E: ID_SERIAL=Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06 +E: ID_SERIAL_SHORT=8F0224006904AB06 +E: ID_TYPE=generic +E: ID_BUS=usb +E: ID_USB_INTERFACES=:ffffff:ff0000: +E: ID_USB_INTERFACE_NUM=02 +E: ID_USB_DRIVER=qcserial +E: TAGS=:snap_modem-manager_qmi-network:snap_modem-manager_mbim-network:snap_network-manager_networkmanager:snap_modem-manager_mbimcli:snap_modem-manager_modemmanager:snap_modem-manager_qmicli: + +P: /devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.2/ttyUSB1/tty/ttyUSB1 +N: ttyUSB1 +L: 0 +S: serial/by-id/usb-Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06-if02-port0 +S: serial/by-path/pci-0000:00:15.0-usb-0:6:1.2-port0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.2/ttyUSB1/tty/ttyUSB1 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyUSB1 +E: MAJOR=188 +E: MINOR=1 +E: USEC_INITIALIZED=17448606 +E: ID_BUS=usb +E: ID_VENDOR_ID=1199 +E: ID_MODEL_ID=9091 +E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller +E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI +E: ID_VENDOR_FROM_DATABASE=Sierra Wireless, Inc. +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series USB xHCI +E: ID_VENDOR=Sierra_Wireless__Incorporated +E: ID_VENDOR_ENC=Sierra\x20Wireless\x2c\x20Incorporated +E: ID_MODEL=Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A +E: ID_MODEL_ENC=Sierra\x20Wireless\x20EM7411\x20Qualcomm®\x20Snapdragon™\x20X16\x20LTE-A +E: ID_REVISION=0006 +E: ID_SERIAL=Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06 +E: ID_SERIAL_SHORT=8F0224006904AB06 +E: ID_TYPE=generic +E: ID_USB_INTERFACES=:ffffff:ff0000: +E: ID_USB_INTERFACE_NUM=02 +E: ID_USB_DRIVER=qcserial +E: ID_PATH=pci-0000:00:15.0-usb-0:6:1.2 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_6_1_2 +E: ID_MM_CANDIDATE=1 +E: DEVLINKS=/dev/serial/by-id/usb-Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06-if02-port0 /dev/serial/by-path/pci-0000:00:15.0-usb-0:6:1.2-port0 +E: TAGS=:snap_everactive-firmware-utilities_mc-status:snap_network-manager_networkmanager:snap_modem-manager_modemmanager:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_hook_install:snap_modem-manager_mbim-network:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_mc-activate:snap_modem-manager_qmi-network:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:systemd:snap_everactive-firmware-utilities_sensor-radio-update:snap_modem-manager_qmicli:snap_everactive-firmware-utilities_sensor-radio-version:snap_modem-manager_mbimcli: + +P: /devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.3 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.3 +E: SUBSYSTEM=usb +E: DEVTYPE=usb_interface +E: DRIVER=qcserial +E: PRODUCT=1199/9091/6 +E: TYPE=0/0/0 +E: INTERFACE=255/0/0 +E: MODALIAS=usb:v1199p9091d0006dc00dsc00dp00icFFisc00ip00in03 +E: USEC_INITIALIZED=14583250 +E: ID_VENDOR_FROM_DATABASE=Sierra Wireless, Inc. +E: ID_PATH=pci-0000:00:15.0-usb-0:6:1.3 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_6_1_3 +E: TAGS=:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_sensor-radio-version: + +P: /devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.3/ttyUSB2 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.3/ttyUSB2 +E: SUBSYSTEM=usb-serial +E: DRIVER=qcserial +E: USEC_INITIALIZED=17080268 +E: ID_VENDOR=Sierra_Wireless__Incorporated +E: ID_VENDOR_ENC=Sierra\x20Wireless\x2c\x20Incorporated +E: ID_VENDOR_ID=1199 +E: ID_MODEL=Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A +E: ID_MODEL_ENC=Sierra\x20Wireless\x20EM7411\x20Qualcomm®\x20Snapdragon™\x20X16\x20LTE-A +E: ID_MODEL_ID=9091 +E: ID_REVISION=0006 +E: ID_SERIAL=Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06 +E: ID_SERIAL_SHORT=8F0224006904AB06 +E: ID_TYPE=generic +E: ID_BUS=usb +E: ID_USB_INTERFACES=:ffffff:ff0000: +E: ID_USB_INTERFACE_NUM=03 +E: ID_USB_DRIVER=qcserial +E: TAGS=:snap_modem-manager_mbim-network:snap_network-manager_networkmanager:snap_modem-manager_qmi-network:snap_modem-manager_modemmanager:snap_modem-manager_qmicli:snap_modem-manager_mbimcli: + +P: /devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.3/ttyUSB2/tty/ttyUSB2 +N: ttyUSB2 +L: 0 +S: serial/by-path/pci-0000:00:15.0-usb-0:6:1.3-port0 +S: serial/by-id/usb-Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06-if03-port0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.3/ttyUSB2/tty/ttyUSB2 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyUSB2 +E: MAJOR=188 +E: MINOR=2 +E: USEC_INITIALIZED=17583131 +E: ID_BUS=usb +E: ID_VENDOR_ID=1199 +E: ID_MODEL_ID=9091 +E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller +E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI +E: ID_VENDOR_FROM_DATABASE=Sierra Wireless, Inc. +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series USB xHCI +E: ID_VENDOR=Sierra_Wireless__Incorporated +E: ID_VENDOR_ENC=Sierra\x20Wireless\x2c\x20Incorporated +E: ID_MODEL=Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A +E: ID_MODEL_ENC=Sierra\x20Wireless\x20EM7411\x20Qualcomm®\x20Snapdragon™\x20X16\x20LTE-A +E: ID_REVISION=0006 +E: ID_SERIAL=Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06 +E: ID_SERIAL_SHORT=8F0224006904AB06 +E: ID_TYPE=generic +E: ID_USB_INTERFACES=:ffffff:ff0000: +E: ID_USB_INTERFACE_NUM=03 +E: ID_USB_DRIVER=qcserial +E: ID_PATH=pci-0000:00:15.0-usb-0:6:1.3 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_6_1_3 +E: ID_MM_CANDIDATE=1 +E: DEVLINKS=/dev/serial/by-path/pci-0000:00:15.0-usb-0:6:1.3-port0 /dev/serial/by-id/usb-Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06-if03-port0 +E: TAGS=:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_mc-activate:snap_modem-manager_modemmanager:snap_modem-manager_mbim-network:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_modem-manager_mbimcli:systemd:snap_everactive-firmware-utilities_utilities-daemon:snap_modem-manager_qmicli:snap_everactive-firmware-utilities_mc-update:snap_network-manager_networkmanager:snap_everactive-firmware-utilities_sensor-radio-update:snap_modem-manager_qmi-network:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_sensor-radio-version: + +P: /devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.8 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.8 +E: SUBSYSTEM=usb +E: DEVTYPE=usb_interface +E: DRIVER=qmi_wwan +E: PRODUCT=1199/9091/6 +E: TYPE=0/0/0 +E: INTERFACE=255/255/255 +E: MODALIAS=usb:v1199p9091d0006dc00dsc00dp00icFFiscFFipFFin08 +E: USEC_INITIALIZED=14621910 +E: ID_VENDOR_FROM_DATABASE=Sierra Wireless, Inc. +E: ID_PATH=pci-0000:00:15.0-usb-0:6:1.8 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_6_1_8 +E: TAGS=:snap_everactive-firmware-utilities_mc-status:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_mc-update: + +P: /devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.8/net/wwan0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.8/net/wwan0 +E: SUBSYSTEM=net +E: DEVTYPE=wwan +E: INTERFACE=wwan0 +E: IFINDEX=4 +E: USEC_INITIALIZED=17514284 +E: ID_VENDOR=Sierra_Wireless__Incorporated +E: ID_VENDOR_ENC=Sierra\x20Wireless\x2c\x20Incorporated +E: ID_VENDOR_ID=1199 +E: ID_MODEL=Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A +E: ID_MODEL_ENC=Sierra\x20Wireless\x20EM7411\x20Qualcomm®\x20Snapdragon™\x20X16\x20LTE-A +E: ID_MODEL_ID=9091 +E: ID_REVISION=0006 +E: ID_SERIAL=Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06 +E: ID_SERIAL_SHORT=8F0224006904AB06 +E: ID_TYPE=generic +E: ID_BUS=usb +E: ID_USB_INTERFACES=:ffffff:ff0000: +E: ID_USB_INTERFACE_NUM=08 +E: ID_USB_DRIVER=qmi_wwan +E: ID_MM_CANDIDATE=1 +E: ID_NET_NAMING_SCHEME=v245 +E: ID_NET_NAME_PATH=wwp0s21f0u6i8 +E: ID_VENDOR_FROM_DATABASE=Sierra Wireless, Inc. +E: ID_PATH=pci-0000:00:15.0-usb-0:6:1.8 +E: ID_PATH_TAG=pci-0000_00_15_0-usb-0_6_1_8 +E: ID_NET_DRIVER=qmi_wwan +E: ID_NET_LINK_FILE=/usr/lib/systemd/network/73-usb-net-by-mac.link +E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/wwan0 +E: TAGS=:systemd: + +P: /devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.8/usbmisc/cdc-wdm0 +N: cdc-wdm0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/usb2/2-6/2-6:1.8/usbmisc/cdc-wdm0 +E: SUBSYSTEM=usbmisc +E: DEVNAME=/dev/cdc-wdm0 +E: MAJOR=180 +E: MINOR=0 +E: USEC_INITIALIZED=17544054 +E: ID_VENDOR=Sierra_Wireless__Incorporated +E: ID_VENDOR_ENC=Sierra\x20Wireless\x2c\x20Incorporated +E: ID_VENDOR_ID=1199 +E: ID_MODEL=Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A +E: ID_MODEL_ENC=Sierra\x20Wireless\x20EM7411\x20Qualcomm®\x20Snapdragon™\x20X16\x20LTE-A +E: ID_MODEL_ID=9091 +E: ID_REVISION=0006 +E: ID_SERIAL=Sierra_Wireless__Incorporated_Sierra_Wireless_EM7411_Qualcomm®_Snapdragon™_X16_LTE-A_8F0224006904AB06 +E: ID_SERIAL_SHORT=8F0224006904AB06 +E: ID_TYPE=generic +E: ID_BUS=usb +E: ID_USB_INTERFACES=:ffffff:ff0000: +E: ID_USB_INTERFACE_NUM=08 +E: ID_USB_DRIVER=qmi_wwan +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_mbim-network:snap_modem-manager_qmicli:snap_modem-manager_mbimcli:snap_everactive-firmware-utilities_mc-update:snap_modem-manager_modemmanager:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_utilities-daemon:snap_modem-manager_qmi-network:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_mc-status: + +P: /devices/pci0000:00/0000:00:15.0/wakeup/wakeup26 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:15.0/wakeup/wakeup26 +E: SUBSYSTEM=wakeup + +P: /devices/pci0000:00/0000:00:18.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.0 +E: SUBSYSTEM=pci +E: DRIVER=intel-lpss +E: PCI_CLASS=118000 +E: PCI_ID=8086:5ABC +E: PCI_SUBSYS_ID=8086:7270 +E: PCI_SLOT_NAME=0000:00:18.0 +E: MODALIAS=pci:v00008086d00005ABCsv00008086sd00007270bc11sc80i00 +E: USEC_INITIALIZED=14142446 +E: ID_PCI_CLASS_FROM_DATABASE=Signal processing controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Signal processing controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series HSUART Controller + +P: /devices/pci0000:00/0000:00:18.0/dma/dma0chan0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.0/dma/dma0chan0 +E: SUBSYSTEM=dma + +P: /devices/pci0000:00/0000:00:18.0/dma/dma0chan1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.0/dma/dma0chan1 +E: SUBSYSTEM=dma + +P: /devices/pci0000:00/0000:00:18.0/dw-apb-uart.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.0/dw-apb-uart.0 +E: SUBSYSTEM=platform +E: DEVTYPE=mfd_device +E: DRIVER=dw-apb-uart +E: MODALIAS=platform:dw-apb-uart +E: USEC_INITIALIZED=16708510 +E: ID_PATH=pci-0000:00:18.0-platform-dw-apb-uart.0 +E: ID_PATH_TAG=pci-0000_00_18_0-platform-dw-apb-uart_0 + +P: /devices/pci0000:00/0000:00:18.0/dw-apb-uart.0/tty/ttyS4 +N: ttyS4 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.0/dw-apb-uart.0/tty/ttyS4 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS4 +E: MAJOR=4 +E: MINOR=68 +E: USEC_INITIALIZED=19423704 +E: ID_BUS=pci +E: ID_VENDOR_ID=0x8086 +E: ID_MODEL_ID=0x5abc +E: ID_PCI_CLASS_FROM_DATABASE=Signal processing controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Signal processing controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series HSUART Controller +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_network-manager_networkmanager:snap_modem-manager_qmi-network:snap_modem-manager_qmicli:snap_modem-manager_mbim-network:snap_modem-manager_modemmanager:systemd:snap_modem-manager_mbimcli: + +P: /devices/pci0000:00/0000:00:18.0/idma64.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.0/idma64.0 +E: SUBSYSTEM=platform +E: DEVTYPE=mfd_device +E: DRIVER=idma64 +E: MODALIAS=platform:idma64 +E: USEC_INITIALIZED=16711657 +E: ID_PATH=pci-0000:00:18.0-platform-idma64.0 +E: ID_PATH_TAG=pci-0000_00_18_0-platform-idma64_0 + +P: /devices/pci0000:00/0000:00:18.1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.1 +E: SUBSYSTEM=pci +E: DRIVER=intel-lpss +E: PCI_CLASS=118000 +E: PCI_ID=8086:5ABE +E: PCI_SUBSYS_ID=8086:7270 +E: PCI_SLOT_NAME=0000:00:18.1 +E: MODALIAS=pci:v00008086d00005ABEsv00008086sd00007270bc11sc80i00 +E: USEC_INITIALIZED=14148216 +E: ID_PCI_CLASS_FROM_DATABASE=Signal processing controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Signal processing controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series HSUART Controller + +P: /devices/pci0000:00/0000:00:18.1/dma/dma1chan0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.1/dma/dma1chan0 +E: SUBSYSTEM=dma + +P: /devices/pci0000:00/0000:00:18.1/dma/dma1chan1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.1/dma/dma1chan1 +E: SUBSYSTEM=dma + +P: /devices/pci0000:00/0000:00:18.1/dw-apb-uart.1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.1/dw-apb-uart.1 +E: SUBSYSTEM=platform +E: DEVTYPE=mfd_device +E: DRIVER=dw-apb-uart +E: MODALIAS=platform:dw-apb-uart +E: USEC_INITIALIZED=16740928 +E: ID_PATH=pci-0000:00:18.1-platform-dw-apb-uart.1 +E: ID_PATH_TAG=pci-0000_00_18_1-platform-dw-apb-uart_1 + +P: /devices/pci0000:00/0000:00:18.1/dw-apb-uart.1/tty/ttyS5 +N: ttyS5 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.1/dw-apb-uart.1/tty/ttyS5 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS5 +E: MAJOR=4 +E: MINOR=69 +E: USEC_INITIALIZED=19347128 +E: ID_BUS=pci +E: ID_VENDOR_ID=0x8086 +E: ID_MODEL_ID=0x5abe +E: ID_PCI_CLASS_FROM_DATABASE=Signal processing controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Signal processing controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series HSUART Controller +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_qmi-network:snap_modem-manager_modemmanager:snap_modem-manager_qmicli:snap_network-manager_networkmanager:systemd:snap_modem-manager_mbimcli:snap_modem-manager_mbim-network: + +P: /devices/pci0000:00/0000:00:18.1/idma64.1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.1/idma64.1 +E: SUBSYSTEM=platform +E: DEVTYPE=mfd_device +E: DRIVER=idma64 +E: MODALIAS=platform:idma64 +E: USEC_INITIALIZED=16719199 +E: ID_PATH=pci-0000:00:18.1-platform-idma64.1 +E: ID_PATH_TAG=pci-0000_00_18_1-platform-idma64_1 + +P: /devices/pci0000:00/0000:00:18.2 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.2 +E: SUBSYSTEM=pci +E: DRIVER=intel-lpss +E: PCI_CLASS=118000 +E: PCI_ID=8086:5AC0 +E: PCI_SUBSYS_ID=8086:7270 +E: PCI_SLOT_NAME=0000:00:18.2 +E: MODALIAS=pci:v00008086d00005AC0sv00008086sd00007270bc11sc80i00 +E: USEC_INITIALIZED=14151191 +E: ID_PCI_CLASS_FROM_DATABASE=Signal processing controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Signal processing controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series HSUART Controller + +P: /devices/pci0000:00/0000:00:18.2/dw-apb-uart.2 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.2/dw-apb-uart.2 +E: SUBSYSTEM=platform +E: DEVTYPE=mfd_device +E: DRIVER=dw-apb-uart +E: MODALIAS=platform:dw-apb-uart +E: USEC_INITIALIZED=16767232 +E: ID_PATH=pci-0000:00:18.2-platform-dw-apb-uart.2 +E: ID_PATH_TAG=pci-0000_00_18_2-platform-dw-apb-uart_2 + +P: /devices/pci0000:00/0000:00:18.2/dw-apb-uart.2/tty/ttyS6 +N: ttyS6 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:18.2/dw-apb-uart.2/tty/ttyS6 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS6 +E: MAJOR=4 +E: MINOR=70 +E: USEC_INITIALIZED=19709048 +E: ID_BUS=pci +E: ID_VENDOR_ID=0x8086 +E: ID_MODEL_ID=0x5ac0 +E: ID_PCI_CLASS_FROM_DATABASE=Signal processing controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=Signal processing controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series HSUART Controller +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_modemmanager:systemd:snap_modem-manager_qmicli:snap_modem-manager_qmi-network:snap_network-manager_networkmanager:snap_modem-manager_mbimcli:snap_modem-manager_mbim-network: + +P: /devices/pci0000:00/0000:00:1b.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1b.0 +E: SUBSYSTEM=pci +E: DRIVER=sdhci-pci +E: PCI_CLASS=80501 +E: PCI_ID=8086:5ACA +E: PCI_SUBSYS_ID=8086:7270 +E: PCI_SLOT_NAME=0000:00:1b.0 +E: MODALIAS=pci:v00008086d00005ACAsv00008086sd00007270bc08sc05i01 +E: USEC_INITIALIZED=14154346 +E: ID_PCI_CLASS_FROM_DATABASE=Generic system peripheral +E: ID_PCI_SUBCLASS_FROM_DATABASE=SD Host controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series SDXC/MMC Host Controller + +P: /devices/pci0000:00/0000:00:1b.0/mmc_host/mmc1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1b.0/mmc_host/mmc1 +E: SUBSYSTEM=mmc_host + +P: /devices/pci0000:00/0000:00:1b.0/mmc_host/mmc1/mmc1:1234 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1b.0/mmc_host/mmc1/mmc1:1234 +E: SUBSYSTEM=mmc +E: DRIVER=mmcblk +E: MMC_TYPE=SD +E: MMC_NAME=SA08G +E: MODALIAS=mmc:block + +P: /devices/pci0000:00/0000:00:1b.0/mmc_host/mmc1/mmc1:1234/block/mmcblk1 +N: mmcblk1 +L: 0 +S: disk/by-id/mmc-SA08G_0x21a90bc6 +E: DEVPATH=/devices/pci0000:00/0000:00:1b.0/mmc_host/mmc1/mmc1:1234/block/mmcblk1 +E: SUBSYSTEM=block +E: DEVNAME=/dev/mmcblk1 +E: DEVTYPE=disk +E: MAJOR=179 +E: MINOR=24 +E: USEC_INITIALIZED=401078475 +E: ID_NAME=SA08G +E: ID_SERIAL=0x21a90bc6 +E: ID_PART_TABLE_UUID=074e3f47-3d11-40b9-8ab5-d7c1b338de58 +E: ID_PART_TABLE_TYPE=gpt +E: DEVLINKS=/dev/disk/by-id/mmc-SA08G_0x21a90bc6 +E: TAGS=:systemd: + +P: /devices/pci0000:00/0000:00:1b.0/mmc_host/mmc1/mmc1:1234/block/mmcblk1/mmcblk1p1 +N: mmcblk1p1 +L: 0 +S: disk/by-uuid/0a09f63d-0721-474b-8072-56d37ce0a509 +S: disk/by-partuuid/867a3d12-e7b7-47dc-afe1-121409772a78 +S: disk/by-label/ubuntu-rootfs +S: disk/by-partlabel/p1 +S: disk/by-id/mmc-SA08G_0x21a90bc6-part1 +E: DEVPATH=/devices/pci0000:00/0000:00:1b.0/mmc_host/mmc1/mmc1:1234/block/mmcblk1/mmcblk1p1 +E: SUBSYSTEM=block +E: DEVNAME=/dev/mmcblk1p1 +E: DEVTYPE=partition +E: PARTN=1 +E: PARTNAME=p1 +E: MAJOR=179 +E: MINOR=25 +E: USEC_INITIALIZED=401211782 +E: ID_NAME=SA08G +E: ID_SERIAL=0x21a90bc6 +E: ID_PART_TABLE_UUID=074e3f47-3d11-40b9-8ab5-d7c1b338de58 +E: ID_PART_TABLE_TYPE=gpt +E: ID_FS_LABEL=ubuntu-rootfs +E: ID_FS_LABEL_ENC=ubuntu-rootfs +E: ID_FS_UUID=0a09f63d-0721-474b-8072-56d37ce0a509 +E: ID_FS_UUID_ENC=0a09f63d-0721-474b-8072-56d37ce0a509 +E: ID_FS_VERSION=1.0 +E: ID_FS_TYPE=ext4 +E: ID_FS_USAGE=filesystem +E: ID_PART_ENTRY_SCHEME=gpt +E: ID_PART_ENTRY_NAME=p1 +E: ID_PART_ENTRY_UUID=867a3d12-e7b7-47dc-afe1-121409772a78 +E: ID_PART_ENTRY_TYPE=0fc63daf-8483-4772-8e79-3d69d8477de4 +E: ID_PART_ENTRY_NUMBER=1 +E: ID_PART_ENTRY_OFFSET=128 +E: ID_PART_ENTRY_SIZE=8388353 +E: ID_PART_ENTRY_DISK=179:24 +E: DEVLINKS=/dev/disk/by-uuid/0a09f63d-0721-474b-8072-56d37ce0a509 /dev/disk/by-partuuid/867a3d12-e7b7-47dc-afe1-121409772a78 /dev/disk/by-label/ubuntu-rootfs /dev/disk/by-partlabel/p1 /dev/disk/by-id/mmc-SA08G_0x21a90bc6-part1 +E: TAGS=:systemd: + +P: /devices/pci0000:00/0000:00:1b.0/wakeup/wakeup29 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1b.0/wakeup/wakeup29 +E: SUBSYSTEM=wakeup + +P: /devices/pci0000:00/0000:00:1c.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1c.0 +E: SUBSYSTEM=pci +E: DRIVER=sdhci-pci +E: PCI_CLASS=80501 +E: PCI_ID=8086:5ACC +E: PCI_SUBSYS_ID=8086:7270 +E: PCI_SLOT_NAME=0000:00:1c.0 +E: MODALIAS=pci:v00008086d00005ACCsv00008086sd00007270bc08sc05i01 +E: USEC_INITIALIZED=14162932 +E: ID_PCI_CLASS_FROM_DATABASE=Generic system peripheral +E: ID_PCI_SUBCLASS_FROM_DATABASE=SD Host controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series eMMC Controller + +P: /devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0 +E: SUBSYSTEM=mmc_host + +P: /devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001 +E: SUBSYSTEM=mmc +E: DRIVER=mmcblk +E: MMC_TYPE=MMC +E: MMC_NAME=M52532 +E: MODALIAS=mmc:block + +P: /devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0 +N: mmcblk0 +L: 0 +S: disk/by-id/mmc-M52532_0x1223d15c +E: DEVPATH=/devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0 +E: SUBSYSTEM=block +E: DEVNAME=/dev/mmcblk0 +E: DEVTYPE=disk +E: MAJOR=179 +E: MINOR=0 +E: USEC_INITIALIZED=14242418 +E: ID_NAME=M52532 +E: ID_SERIAL=0x1223d15c +E: ID_PART_TABLE_UUID=ea493d5a-473b-4db3-a67d-434d6758e9d3 +E: ID_PART_TABLE_TYPE=gpt +E: DEVLINKS=/dev/disk/by-id/mmc-M52532_0x1223d15c +E: TAGS=:systemd: + +P: /devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0boot0 +N: mmcblk0boot0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0boot0 +E: SUBSYSTEM=block +E: DEVNAME=/dev/mmcblk0boot0 +E: DEVTYPE=disk +E: MAJOR=179 +E: MINOR=8 +E: USEC_INITIALIZED=14380341 +E: TAGS=:systemd: + +P: /devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0boot1 +N: mmcblk0boot1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0boot1 +E: SUBSYSTEM=block +E: DEVNAME=/dev/mmcblk0boot1 +E: DEVTYPE=disk +E: MAJOR=179 +E: MINOR=16 +E: USEC_INITIALIZED=14499196 +E: TAGS=:systemd: + +P: /devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p1 +N: mmcblk0p1 +L: 0 +S: disk/by-partuuid/e3c5976d-ef69-4134-ab5a-95cc91a85e58 +S: disk/by-id/mmc-M52532_0x1223d15c-part1 +S: disk/by-partlabel/BIOS_Boot +S: disk/by-partlabel/BIOS\x20Boot +E: DEVPATH=/devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p1 +E: SUBSYSTEM=block +E: DEVNAME=/dev/mmcblk0p1 +E: DEVTYPE=partition +E: PARTN=1 +E: PARTNAME=BIOS Boot +E: MAJOR=179 +E: MINOR=1 +E: USEC_INITIALIZED=14431856 +E: ID_NAME=M52532 +E: ID_SERIAL=0x1223d15c +E: ID_PART_TABLE_UUID=ea493d5a-473b-4db3-a67d-434d6758e9d3 +E: ID_PART_TABLE_TYPE=gpt +E: ID_PART_ENTRY_SCHEME=gpt +E: ID_PART_ENTRY_NAME=BIOS\x20Boot +E: ID_PART_ENTRY_UUID=e3c5976d-ef69-4134-ab5a-95cc91a85e58 +E: ID_PART_ENTRY_TYPE=21686148-6449-6e6f-744e-656564454649 +E: ID_PART_ENTRY_NUMBER=1 +E: ID_PART_ENTRY_OFFSET=2048 +E: ID_PART_ENTRY_SIZE=2048 +E: ID_PART_ENTRY_DISK=179:0 +E: DEVLINKS=/dev/disk/by-partuuid/e3c5976d-ef69-4134-ab5a-95cc91a85e58 /dev/disk/by-id/mmc-M52532_0x1223d15c-part1 /dev/disk/by-partlabel/BIOS_Boot /dev/disk/by-partlabel/BIOS\x20Boot +E: TAGS=:systemd: + +P: /devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p2 +N: mmcblk0p2 +L: 0 +S: disk/by-id/mmc-M52532_0x1223d15c-part2 +S: disk/by-label/ubuntu-seed +S: disk/by-partlabel/ubuntu-seed +S: disk/by-partuuid/0d1fa057-1d65-4d2e-8fcb-12ebcfd4c5b6 +S: disk/by-uuid/9BC0-64C8 +E: DEVPATH=/devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p2 +E: SUBSYSTEM=block +E: DEVNAME=/dev/mmcblk0p2 +E: DEVTYPE=partition +E: PARTN=2 +E: PARTNAME=ubuntu-seed +E: MAJOR=179 +E: MINOR=2 +E: USEC_INITIALIZED=14478356 +E: ID_NAME=M52532 +E: ID_SERIAL=0x1223d15c +E: ID_PART_TABLE_UUID=ea493d5a-473b-4db3-a67d-434d6758e9d3 +E: ID_PART_TABLE_TYPE=gpt +E: ID_FS_LABEL=ubuntu-seed +E: ID_FS_LABEL_ENC=ubuntu-seed +E: ID_FS_UUID=9BC0-64C8 +E: ID_FS_UUID_ENC=9BC0-64C8 +E: ID_FS_VERSION=FAT32 +E: ID_FS_TYPE=vfat +E: ID_FS_USAGE=filesystem +E: ID_PART_ENTRY_SCHEME=gpt +E: ID_PART_ENTRY_NAME=ubuntu-seed +E: ID_PART_ENTRY_UUID=0d1fa057-1d65-4d2e-8fcb-12ebcfd4c5b6 +E: ID_PART_ENTRY_TYPE=c12a7328-f81f-11d2-ba4b-00a0c93ec93b +E: ID_PART_ENTRY_NUMBER=2 +E: ID_PART_ENTRY_OFFSET=4096 +E: ID_PART_ENTRY_SIZE=3072000 +E: ID_PART_ENTRY_DISK=179:0 +E: DEVLINKS=/dev/disk/by-id/mmc-M52532_0x1223d15c-part2 /dev/disk/by-label/ubuntu-seed /dev/disk/by-partlabel/ubuntu-seed /dev/disk/by-partuuid/0d1fa057-1d65-4d2e-8fcb-12ebcfd4c5b6 /dev/disk/by-uuid/9BC0-64C8 +E: TAGS=:systemd: + +P: /devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p3 +N: mmcblk0p3 +L: 0 +S: disk/by-partlabel/ubuntu-boot +S: disk/by-uuid/842db623-49a3-4721-96e9-4cdc4c8cf4ad +S: disk/by-id/mmc-M52532_0x1223d15c-part3 +S: disk/by-partuuid/f0014561-8409-4544-b800-c9a8e029af77 +S: disk/by-label/ubuntu-boot +E: DEVPATH=/devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p3 +E: SUBSYSTEM=block +E: DEVNAME=/dev/mmcblk0p3 +E: DEVTYPE=partition +E: PARTN=3 +E: PARTNAME=ubuntu-boot +E: MAJOR=179 +E: MINOR=3 +E: USEC_INITIALIZED=14474432 +E: ID_NAME=M52532 +E: ID_SERIAL=0x1223d15c +E: ID_PART_TABLE_UUID=ea493d5a-473b-4db3-a67d-434d6758e9d3 +E: ID_PART_TABLE_TYPE=gpt +E: ID_FS_LABEL=ubuntu-boot +E: ID_FS_LABEL_ENC=ubuntu-boot +E: ID_FS_UUID=842db623-49a3-4721-96e9-4cdc4c8cf4ad +E: ID_FS_UUID_ENC=842db623-49a3-4721-96e9-4cdc4c8cf4ad +E: ID_FS_VERSION=1.0 +E: ID_FS_TYPE=ext4 +E: ID_FS_USAGE=filesystem +E: ID_PART_ENTRY_SCHEME=gpt +E: ID_PART_ENTRY_NAME=ubuntu-boot +E: ID_PART_ENTRY_UUID=f0014561-8409-4544-b800-c9a8e029af77 +E: ID_PART_ENTRY_TYPE=0fc63daf-8483-4772-8e79-3d69d8477de4 +E: ID_PART_ENTRY_NUMBER=3 +E: ID_PART_ENTRY_OFFSET=3076096 +E: ID_PART_ENTRY_SIZE=1536000 +E: ID_PART_ENTRY_DISK=179:0 +E: DEVLINKS=/dev/disk/by-partlabel/ubuntu-boot /dev/disk/by-uuid/842db623-49a3-4721-96e9-4cdc4c8cf4ad /dev/disk/by-id/mmc-M52532_0x1223d15c-part3 /dev/disk/by-partuuid/f0014561-8409-4544-b800-c9a8e029af77 /dev/disk/by-label/ubuntu-boot +E: TAGS=:systemd: + +P: /devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p4 +N: mmcblk0p4 +L: 0 +S: disk/by-partlabel/ubuntu-save +S: disk/by-uuid/b04a0cd7-ee0e-4eff-90f0-2517089c587d +S: disk/by-partuuid/ae577d7f-7e76-c74c-8321-9ac771258171 +S: disk/by-label/ubuntu-save-enc +S: disk/by-id/mmc-M52532_0x1223d15c-part4 +E: DEVPATH=/devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p4 +E: SUBSYSTEM=block +E: DEVNAME=/dev/mmcblk0p4 +E: DEVTYPE=partition +E: PARTN=4 +E: PARTNAME=ubuntu-save +E: MAJOR=179 +E: MINOR=4 +E: USEC_INITIALIZED=14411010 +E: ID_NAME=M52532 +E: ID_SERIAL=0x1223d15c +E: ID_PART_TABLE_UUID=ea493d5a-473b-4db3-a67d-434d6758e9d3 +E: ID_PART_TABLE_TYPE=gpt +E: ID_FS_VERSION=2 +E: ID_FS_UUID=b04a0cd7-ee0e-4eff-90f0-2517089c587d +E: ID_FS_UUID_ENC=b04a0cd7-ee0e-4eff-90f0-2517089c587d +E: ID_FS_LABEL=ubuntu-save-enc +E: ID_FS_LABEL_ENC=ubuntu-save-enc +E: ID_FS_TYPE=crypto_LUKS +E: ID_FS_USAGE=crypto +E: ID_PART_ENTRY_SCHEME=gpt +E: ID_PART_ENTRY_NAME=ubuntu-save +E: ID_PART_ENTRY_UUID=ae577d7f-7e76-c74c-8321-9ac771258171 +E: ID_PART_ENTRY_TYPE=0fc63daf-8483-4772-8e79-3d69d8477de4 +E: ID_PART_ENTRY_NUMBER=4 +E: ID_PART_ENTRY_OFFSET=4612096 +E: ID_PART_ENTRY_SIZE=32768 +E: ID_PART_ENTRY_DISK=179:0 +E: DEVLINKS=/dev/disk/by-partlabel/ubuntu-save /dev/disk/by-uuid/b04a0cd7-ee0e-4eff-90f0-2517089c587d /dev/disk/by-partuuid/ae577d7f-7e76-c74c-8321-9ac771258171 /dev/disk/by-label/ubuntu-save-enc /dev/disk/by-id/mmc-M52532_0x1223d15c-part4 +E: TAGS=:systemd: + +P: /devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p5 +N: mmcblk0p5 +L: 0 +S: disk/by-partlabel/ubuntu-data +S: disk/by-partuuid/e420240b-80fc-a141-961a-233b727ed3f6 +S: disk/by-uuid/9bac7b2a-845f-4c59-ae00-bfdb89b1c378 +S: disk/by-id/mmc-M52532_0x1223d15c-part5 +S: disk/by-label/ubuntu-data-enc +E: DEVPATH=/devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p5 +E: SUBSYSTEM=block +E: DEVNAME=/dev/mmcblk0p5 +E: DEVTYPE=partition +E: PARTN=5 +E: PARTNAME=ubuntu-data +E: MAJOR=179 +E: MINOR=5 +E: USEC_INITIALIZED=14412233 +E: ID_NAME=M52532 +E: ID_SERIAL=0x1223d15c +E: ID_PART_TABLE_UUID=ea493d5a-473b-4db3-a67d-434d6758e9d3 +E: ID_PART_TABLE_TYPE=gpt +E: ID_FS_VERSION=2 +E: ID_FS_UUID=9bac7b2a-845f-4c59-ae00-bfdb89b1c378 +E: ID_FS_UUID_ENC=9bac7b2a-845f-4c59-ae00-bfdb89b1c378 +E: ID_FS_LABEL=ubuntu-data-enc +E: ID_FS_LABEL_ENC=ubuntu-data-enc +E: ID_FS_TYPE=crypto_LUKS +E: ID_FS_USAGE=crypto +E: ID_PART_ENTRY_SCHEME=gpt +E: ID_PART_ENTRY_NAME=ubuntu-data +E: ID_PART_ENTRY_UUID=e420240b-80fc-a141-961a-233b727ed3f6 +E: ID_PART_ENTRY_TYPE=0fc63daf-8483-4772-8e79-3d69d8477de4 +E: ID_PART_ENTRY_NUMBER=5 +E: ID_PART_ENTRY_OFFSET=4644864 +E: ID_PART_ENTRY_SIZE=55123935 +E: ID_PART_ENTRY_DISK=179:0 +E: DEVLINKS=/dev/disk/by-partlabel/ubuntu-data /dev/disk/by-partuuid/e420240b-80fc-a141-961a-233b727ed3f6 /dev/disk/by-uuid/9bac7b2a-845f-4c59-ae00-bfdb89b1c378 /dev/disk/by-id/mmc-M52532_0x1223d15c-part5 /dev/disk/by-label/ubuntu-data-enc +E: TAGS=:systemd: + +P: /devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/mmcblk0rpmb +N: mmcblk0rpmb +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/mmcblk0rpmb +E: SUBSYSTEM=mmc_rpmb +E: DEVNAME=/dev/mmcblk0rpmb +E: MAJOR=239 +E: MINOR=0 + +P: /devices/pci0000:00/0000:00:1f.0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1f.0 +E: SUBSYSTEM=pci +E: DRIVER=lpc_ich +E: PCI_CLASS=60100 +E: PCI_ID=8086:5AE8 +E: PCI_SUBSYS_ID=8086:7270 +E: PCI_SLOT_NAME=0000:00:1f.0 +E: MODALIAS=pci:v00008086d00005AE8sv00008086sd00007270bc06sc01i00 +E: USEC_INITIALIZED=14159543 +E: ID_PCI_CLASS_FROM_DATABASE=Bridge +E: ID_PCI_SUBCLASS_FROM_DATABASE=ISA bridge +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series Low Pin Count Interface + +P: /devices/pci0000:00/0000:00:1f.0/intel-spi +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1f.0/intel-spi +E: SUBSYSTEM=platform +E: DEVTYPE=mfd_device +E: MODALIAS=platform:intel-spi +E: USEC_INITIALIZED=16596624 +E: ID_PATH=pci-0000:00:1f.0-platform-intel-spi +E: ID_PATH_TAG=pci-0000_00_1f_0-platform-intel-spi + +P: /devices/pci0000:00/0000:00:1f.1 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1f.1 +E: SUBSYSTEM=pci +E: DRIVER=i801_smbus +E: PCI_CLASS=C0500 +E: PCI_ID=8086:5AD4 +E: PCI_SUBSYS_ID=8086:7270 +E: PCI_SLOT_NAME=0000:00:1f.1 +E: MODALIAS=pci:v00008086d00005AD4sv00008086sd00007270bc0Csc05i00 +E: USEC_INITIALIZED=14159484 +E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller +E: ID_PCI_SUBCLASS_FROM_DATABASE=SMBus +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series SMBus Controller + +P: /devices/pci0000:00/0000:00:1f.1/i2c-0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1f.1/i2c-0 +E: SUBSYSTEM=i2c + +P: /devices/pci0000:00/0000:00:1f.1/i2c-0/i2c-dev/i2c-0 +N: i2c-0 +L: 0 +E: DEVPATH=/devices/pci0000:00/0000:00:1f.1/i2c-0/i2c-dev/i2c-0 +E: SUBSYSTEM=i2c-dev +E: DEVNAME=/dev/i2c-0 +E: MAJOR=89 +E: MINOR=0 + +P: /devices/pci0000:00/PNP0C0D:00 +L: 0 +E: DEVPATH=/devices/pci0000:00/PNP0C0D:00 +E: SUBSYSTEM=platform +E: MODALIAS=acpi:PNP0C0D: +E: USEC_INITIALIZED=14181993 +E: ID_PATH=platform-PNP0C0D:00 +E: ID_PATH_TAG=platform-PNP0C0D_00 + +P: /devices/pci0000:00/pci_bus/0000:00 +L: 0 +E: DEVPATH=/devices/pci0000:00/pci_bus/0000:00 +E: SUBSYSTEM=pci_bus + +P: /devices/platform/ACPI0003:00 +L: 0 +E: DEVPATH=/devices/platform/ACPI0003:00 +E: SUBSYSTEM=platform +E: MODALIAS=acpi:ACPI0003: +E: USEC_INITIALIZED=14180425 +E: ID_PATH=platform-ACPI0003:00 +E: ID_PATH_TAG=platform-ACPI0003_00 + +P: /devices/platform/Fixed MDIO bus.0 +L: 0 +E: DEVPATH=/devices/platform/Fixed MDIO bus.0 +E: SUBSYSTEM=platform +E: MODALIAS=platform:Fixed MDIO bus +E: USEC_INITIALIZED=14175554 +E: ID_PATH=platform-Fixed MDIO bus.0 +E: ID_PATH_TAG=platform-Fixed_MDIO_bus_0 + +P: /devices/platform/Fixed MDIO bus.0/mdio_bus/fixed-0 +L: 0 +E: DEVPATH=/devices/platform/Fixed MDIO bus.0/mdio_bus/fixed-0 +E: SUBSYSTEM=mdio_bus + +P: /devices/platform/INT33A1:00 +L: 0 +E: DEVPATH=/devices/platform/INT33A1:00 +E: SUBSYSTEM=platform +E: MODALIAS=acpi:INT33A1:PNP0D80: +E: USEC_INITIALIZED=14184807 +E: ID_VENDOR_FROM_DATABASE=Interphase Corporation +E: ID_PATH=platform-INT33A1:00 +E: ID_PATH_TAG=platform-INT33A1_00 + +P: /devices/platform/INT3452:00 +L: 0 +E: DEVPATH=/devices/platform/INT3452:00 +E: SUBSYSTEM=platform +E: DRIVER=broxton-pinctrl +E: MODALIAS=acpi:INT3452:INT3452: +E: USEC_INITIALIZED=14176802 +E: ID_VENDOR_FROM_DATABASE=Interphase Corporation +E: ID_PATH=platform-INT3452:00 +E: ID_PATH_TAG=platform-INT3452_00 + +P: /devices/platform/INT3452:00/gpio/gpiochip434 +L: 0 +E: DEVPATH=/devices/platform/INT3452:00/gpio/gpiochip434 +E: SUBSYSTEM=gpio + +P: /devices/platform/INT3452:00/gpiochip0 +N: gpiochip0 +L: 0 +E: DEVPATH=/devices/platform/INT3452:00/gpiochip0 +E: SUBSYSTEM=gpio +E: DEVNAME=/dev/gpiochip0 +E: MAJOR=254 +E: MINOR=0 + +P: /devices/platform/INT3452:01 +L: 0 +E: DEVPATH=/devices/platform/INT3452:01 +E: SUBSYSTEM=platform +E: DRIVER=broxton-pinctrl +E: MODALIAS=acpi:INT3452:INT3452: +E: USEC_INITIALIZED=14178461 +E: ID_VENDOR_FROM_DATABASE=Interphase Corporation +E: ID_PATH=platform-INT3452:01 +E: ID_PATH_TAG=platform-INT3452_01 + +P: /devices/platform/INT3452:01/gpio/gpiochip357 +L: 0 +E: DEVPATH=/devices/platform/INT3452:01/gpio/gpiochip357 +E: SUBSYSTEM=gpio + +P: /devices/platform/INT3452:01/gpiochip1 +N: gpiochip1 +L: 0 +E: DEVPATH=/devices/platform/INT3452:01/gpiochip1 +E: SUBSYSTEM=gpio +E: DEVNAME=/dev/gpiochip1 +E: MAJOR=254 +E: MINOR=1 + +P: /devices/platform/INT3452:02 +L: 0 +E: DEVPATH=/devices/platform/INT3452:02 +E: SUBSYSTEM=platform +E: DRIVER=broxton-pinctrl +E: MODALIAS=acpi:INT3452:INT3452: +E: USEC_INITIALIZED=14174838 +E: ID_VENDOR_FROM_DATABASE=Interphase Corporation +E: ID_PATH=platform-INT3452:02 +E: ID_PATH_TAG=platform-INT3452_02 + +P: /devices/platform/INT3452:02/gpio/gpiochip310 +L: 0 +E: DEVPATH=/devices/platform/INT3452:02/gpio/gpiochip310 +E: SUBSYSTEM=gpio + +P: /devices/platform/INT3452:02/gpiochip2 +N: gpiochip2 +L: 0 +E: DEVPATH=/devices/platform/INT3452:02/gpiochip2 +E: SUBSYSTEM=gpio +E: DEVNAME=/dev/gpiochip2 +E: MAJOR=254 +E: MINOR=2 + +P: /devices/platform/INT3452:03 +L: 0 +E: DEVPATH=/devices/platform/INT3452:03 +E: SUBSYSTEM=platform +E: DRIVER=broxton-pinctrl +E: MODALIAS=acpi:INT3452:INT3452: +E: USEC_INITIALIZED=14186121 +E: ID_VENDOR_FROM_DATABASE=Interphase Corporation +E: ID_PATH=platform-INT3452:03 +E: ID_PATH_TAG=platform-INT3452_03 + +P: /devices/platform/INT3452:03/gpio/gpiochip267 +L: 0 +E: DEVPATH=/devices/platform/INT3452:03/gpio/gpiochip267 +E: SUBSYSTEM=gpio + +P: /devices/platform/INT3452:03/gpiochip3 +N: gpiochip3 +L: 0 +E: DEVPATH=/devices/platform/INT3452:03/gpiochip3 +E: SUBSYSTEM=gpio +E: DEVNAME=/dev/gpiochip3 +E: MAJOR=254 +E: MINOR=3 + +P: /devices/platform/MSFT0101:00 +L: 0 +E: DEVPATH=/devices/platform/MSFT0101:00 +E: SUBSYSTEM=platform +E: MODALIAS=acpi:MSFT0101: +E: USEC_INITIALIZED=14199168 +E: ID_VENDOR_FROM_DATABASE=M-Systems Flash Disk Pioneers +E: ID_PATH=platform-MSFT0101:00 +E: ID_PATH_TAG=platform-MSFT0101_00 + +P: /devices/platform/PNP0103:00 +L: 0 +E: DEVPATH=/devices/platform/PNP0103:00 +E: SUBSYSTEM=platform +E: MODALIAS=acpi:PNP0103: +E: USEC_INITIALIZED=14205398 +E: ID_PATH=platform-PNP0103:00 +E: ID_PATH_TAG=platform-PNP0103_00 + +P: /devices/platform/PNP0C0B:00 +L: 0 +E: DEVPATH=/devices/platform/PNP0C0B:00 +E: SUBSYSTEM=platform +E: DRIVER=acpi-fan +E: MODALIAS=acpi:PNP0C0B: +E: USEC_INITIALIZED=14204419 +E: ID_PATH=platform-PNP0C0B:00 +E: ID_PATH_TAG=platform-PNP0C0B_00 + +P: /devices/platform/PNP0C0C:00 +L: 0 +E: DEVPATH=/devices/platform/PNP0C0C:00 +E: SUBSYSTEM=platform +E: MODALIAS=acpi:PNP0C0C: +E: USEC_INITIALIZED=14206345 +E: ID_PATH=platform-PNP0C0C:00 +E: ID_PATH_TAG=platform-PNP0C0C_00 + +P: /devices/platform/PNP0C0E:00 +L: 0 +E: DEVPATH=/devices/platform/PNP0C0E:00 +E: SUBSYSTEM=platform +E: MODALIAS=acpi:PNP0C0E: +E: USEC_INITIALIZED=14212732 +E: ID_PATH=platform-PNP0C0E:00 +E: ID_PATH_TAG=platform-PNP0C0E_00 + +P: /devices/platform/coretemp.0 +L: 0 +E: DEVPATH=/devices/platform/coretemp.0 +E: SUBSYSTEM=platform +E: DRIVER=coretemp +E: MODALIAS=platform:coretemp +E: USEC_INITIALIZED=17772295 +E: ID_PATH=platform-coretemp.0 +E: ID_PATH_TAG=platform-coretemp_0 + +P: /devices/platform/coretemp.0/hwmon/hwmon2 +L: 0 +E: DEVPATH=/devices/platform/coretemp.0/hwmon/hwmon2 +E: SUBSYSTEM=hwmon + +P: /devices/platform/efi-framebuffer.0 +L: 0 +E: DEVPATH=/devices/platform/efi-framebuffer.0 +E: SUBSYSTEM=platform +E: DRIVER=efi-framebuffer +E: MODALIAS=platform:efi-framebuffer +E: USEC_INITIALIZED=14215264 +E: ID_PATH=platform-efi-framebuffer.0 +E: ID_PATH_TAG=platform-efi-framebuffer_0 + +P: /devices/platform/eisa.0 +L: 0 +E: DEVPATH=/devices/platform/eisa.0 +E: SUBSYSTEM=platform +E: MODALIAS=platform:eisa +E: USEC_INITIALIZED=14210793 +E: ID_PATH=platform-eisa.0 +E: ID_PATH_TAG=platform-eisa_0 + +P: /devices/platform/intel_rapl_msr.0 +L: 0 +E: DEVPATH=/devices/platform/intel_rapl_msr.0 +E: SUBSYSTEM=platform +E: DRIVER=intel_rapl_msr +E: MODALIAS=platform:intel_rapl_msr +E: USEC_INITIALIZED=18402690 +E: ID_PATH=platform-intel_rapl_msr.0 +E: ID_PATH_TAG=platform-intel_rapl_msr_0 + +P: /devices/platform/kgdboc +L: 0 +E: DEVPATH=/devices/platform/kgdboc +E: SUBSYSTEM=platform +E: DRIVER=kgdboc +E: MODALIAS=platform:kgdboc +E: USEC_INITIALIZED=14223063 +E: ID_PATH=platform-kgdboc +E: ID_PATH_TAG=platform-kgdboc + +P: /devices/platform/microcode +L: 0 +E: DEVPATH=/devices/platform/microcode +E: SUBSYSTEM=platform +E: MODALIAS=platform:microcode +E: USEC_INITIALIZED=14214456 +E: ID_PATH=platform-microcode +E: ID_PATH_TAG=platform-microcode + +P: /devices/platform/pcspkr +L: 0 +E: DEVPATH=/devices/platform/pcspkr +E: SUBSYSTEM=platform +E: MODALIAS=platform:pcspkr +E: USEC_INITIALIZED=14221717 +E: ID_PATH=platform-pcspkr +E: ID_PATH_TAG=platform-pcspkr + +P: /devices/platform/reg-dummy +L: 0 +E: DEVPATH=/devices/platform/reg-dummy +E: SUBSYSTEM=platform +E: DRIVER=reg-dummy +E: MODALIAS=platform:reg-dummy +E: USEC_INITIALIZED=14216894 +E: ID_PATH=platform-reg-dummy +E: ID_PATH_TAG=platform-reg-dummy + +P: /devices/platform/reg-dummy/regulator/regulator.0 +L: 0 +E: DEVPATH=/devices/platform/reg-dummy/regulator/regulator.0 +E: SUBSYSTEM=regulator + +P: /devices/platform/regulatory.0 +L: 0 +E: DEVPATH=/devices/platform/regulatory.0 +E: SUBSYSTEM=platform +E: MODALIAS=platform:regulatory +E: USEC_INITIALIZED=16749143 +E: ID_PATH=platform-regulatory.0 +E: ID_PATH_TAG=platform-regulatory_0 + +P: /devices/platform/serial8250 +L: 0 +E: DEVPATH=/devices/platform/serial8250 +E: SUBSYSTEM=platform +E: DRIVER=serial8250 +E: MODALIAS=platform:serial8250 +E: USEC_INITIALIZED=14226931 +E: ID_PATH=platform-serial8250 +E: ID_PATH_TAG=platform-serial8250 + +P: /devices/platform/serial8250/tty/ttyS0 +N: ttyS0 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS0 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS0 +E: MAJOR=4 +E: MINOR=64 +E: USEC_INITIALIZED=14240632 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_mbim-network:snap_modem-manager_qmi-network:snap_modem-manager_mbimcli:systemd:snap_network-manager_networkmanager:snap_modem-manager_modemmanager:snap_modem-manager_qmicli: + +P: /devices/platform/serial8250/tty/ttyS1 +N: ttyS1 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS1 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS1 +E: MAJOR=4 +E: MINOR=65 +E: USEC_INITIALIZED=14230080 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_qmicli:snap_modem-manager_mbim-network:snap_modem-manager_mbimcli:snap_network-manager_networkmanager:systemd:snap_modem-manager_qmi-network:snap_modem-manager_modemmanager: + +P: /devices/platform/serial8250/tty/ttyS10 +N: ttyS10 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS10 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS10 +E: MAJOR=4 +E: MINOR=74 +E: USEC_INITIALIZED=14233311 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_network-manager_networkmanager:snap_modem-manager_mbimcli:snap_modem-manager_qmi-network:snap_modem-manager_mbim-network:snap_modem-manager_modemmanager:systemd:snap_modem-manager_qmicli: + +P: /devices/platform/serial8250/tty/ttyS11 +N: ttyS11 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS11 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS11 +E: MAJOR=4 +E: MINOR=75 +E: USEC_INITIALIZED=14235720 +E: ID_MM_CANDIDATE=1 +E: TAGS=:systemd:snap_modem-manager_qmicli:snap_network-manager_networkmanager:snap_modem-manager_modemmanager:snap_modem-manager_qmi-network:snap_modem-manager_mbim-network:snap_modem-manager_mbimcli: + +P: /devices/platform/serial8250/tty/ttyS12 +N: ttyS12 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS12 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS12 +E: MAJOR=4 +E: MINOR=76 +E: USEC_INITIALIZED=14232666 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_mbimcli:snap_modem-manager_qmicli:snap_modem-manager_mbim-network:snap_modem-manager_modemmanager:snap_modem-manager_qmi-network:systemd:snap_network-manager_networkmanager: + +P: /devices/platform/serial8250/tty/ttyS13 +N: ttyS13 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS13 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS13 +E: MAJOR=4 +E: MINOR=77 +E: USEC_INITIALIZED=14230407 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_mbimcli:snap_modem-manager_qmicli:snap_network-manager_networkmanager:snap_modem-manager_qmi-network:snap_modem-manager_mbim-network:snap_modem-manager_modemmanager:systemd: + +P: /devices/platform/serial8250/tty/ttyS14 +N: ttyS14 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS14 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS14 +E: MAJOR=4 +E: MINOR=78 +E: USEC_INITIALIZED=14238908 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_qmicli:snap_modem-manager_qmi-network:snap_network-manager_networkmanager:systemd:snap_modem-manager_mbim-network:snap_modem-manager_modemmanager:snap_modem-manager_mbimcli: + +P: /devices/platform/serial8250/tty/ttyS15 +N: ttyS15 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS15 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS15 +E: MAJOR=4 +E: MINOR=79 +E: USEC_INITIALIZED=14240591 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_network-manager_networkmanager:snap_modem-manager_qmicli:snap_modem-manager_modemmanager:snap_modem-manager_mbim-network:snap_modem-manager_qmi-network:snap_modem-manager_mbimcli:systemd: + +P: /devices/platform/serial8250/tty/ttyS16 +N: ttyS16 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS16 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS16 +E: MAJOR=4 +E: MINOR=80 +E: USEC_INITIALIZED=14246305 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_mbimcli:snap_modem-manager_qmicli:snap_modem-manager_modemmanager:snap_modem-manager_mbim-network:snap_network-manager_networkmanager:systemd:snap_modem-manager_qmi-network: + +P: /devices/platform/serial8250/tty/ttyS17 +N: ttyS17 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS17 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS17 +E: MAJOR=4 +E: MINOR=81 +E: USEC_INITIALIZED=14248074 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_qmicli:snap_modem-manager_mbimcli:snap_modem-manager_qmi-network:snap_modem-manager_modemmanager:snap_network-manager_networkmanager:systemd:snap_modem-manager_mbim-network: + +P: /devices/platform/serial8250/tty/ttyS18 +N: ttyS18 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS18 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS18 +E: MAJOR=4 +E: MINOR=82 +E: USEC_INITIALIZED=14246191 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_modemmanager:systemd:snap_modem-manager_mbimcli:snap_modem-manager_qmicli:snap_modem-manager_mbim-network:snap_network-manager_networkmanager:snap_modem-manager_qmi-network: + +P: /devices/platform/serial8250/tty/ttyS19 +N: ttyS19 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS19 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS19 +E: MAJOR=4 +E: MINOR=83 +E: USEC_INITIALIZED=14255581 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_qmi-network:snap_modem-manager_mbimcli:snap_network-manager_networkmanager:systemd:snap_modem-manager_mbim-network:snap_modem-manager_qmicli:snap_modem-manager_modemmanager: + +P: /devices/platform/serial8250/tty/ttyS2 +N: ttyS2 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS2 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS2 +E: MAJOR=4 +E: MINOR=66 +E: USEC_INITIALIZED=14248815 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_modemmanager:snap_modem-manager_mbim-network:systemd:snap_modem-manager_qmicli:snap_network-manager_networkmanager:snap_modem-manager_qmi-network:snap_modem-manager_mbimcli: + +P: /devices/platform/serial8250/tty/ttyS20 +N: ttyS20 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS20 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS20 +E: MAJOR=4 +E: MINOR=84 +E: USEC_INITIALIZED=14279124 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_qmi-network:snap_modem-manager_modemmanager:snap_network-manager_networkmanager:snap_modem-manager_mbimcli:snap_modem-manager_qmicli:snap_modem-manager_mbim-network:systemd: + +P: /devices/platform/serial8250/tty/ttyS21 +N: ttyS21 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS21 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS21 +E: MAJOR=4 +E: MINOR=85 +E: USEC_INITIALIZED=14281682 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_qmicli:systemd:snap_network-manager_networkmanager:snap_modem-manager_modemmanager:snap_modem-manager_mbimcli:snap_modem-manager_mbim-network:snap_modem-manager_qmi-network: + +P: /devices/platform/serial8250/tty/ttyS22 +N: ttyS22 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS22 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS22 +E: MAJOR=4 +E: MINOR=86 +E: USEC_INITIALIZED=14298666 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_mbim-network:snap_modem-manager_modemmanager:systemd:snap_modem-manager_mbimcli:snap_modem-manager_qmi-network:snap_modem-manager_qmicli:snap_network-manager_networkmanager: + +P: /devices/platform/serial8250/tty/ttyS23 +N: ttyS23 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS23 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS23 +E: MAJOR=4 +E: MINOR=87 +E: USEC_INITIALIZED=14306058 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_modemmanager:snap_network-manager_networkmanager:snap_modem-manager_mbim-network:systemd:snap_modem-manager_mbimcli:snap_modem-manager_qmicli:snap_modem-manager_qmi-network: + +P: /devices/platform/serial8250/tty/ttyS24 +N: ttyS24 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS24 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS24 +E: MAJOR=4 +E: MINOR=88 +E: USEC_INITIALIZED=14326720 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_network-manager_networkmanager:systemd:snap_modem-manager_mbim-network:snap_modem-manager_qmi-network:snap_modem-manager_qmicli:snap_modem-manager_mbimcli:snap_modem-manager_modemmanager: + +P: /devices/platform/serial8250/tty/ttyS25 +N: ttyS25 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS25 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS25 +E: MAJOR=4 +E: MINOR=89 +E: USEC_INITIALIZED=14397823 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_mbimcli:systemd:snap_modem-manager_mbim-network:snap_modem-manager_qmi-network:snap_network-manager_networkmanager:snap_modem-manager_modemmanager:snap_modem-manager_qmicli: + +P: /devices/platform/serial8250/tty/ttyS26 +N: ttyS26 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS26 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS26 +E: MAJOR=4 +E: MINOR=90 +E: USEC_INITIALIZED=14404869 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_qmicli:snap_modem-manager_mbim-network:snap_modem-manager_mbimcli:systemd:snap_network-manager_networkmanager:snap_modem-manager_qmi-network:snap_modem-manager_modemmanager: + +P: /devices/platform/serial8250/tty/ttyS27 +N: ttyS27 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS27 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS27 +E: MAJOR=4 +E: MINOR=91 +E: USEC_INITIALIZED=14408824 +E: ID_MM_CANDIDATE=1 +E: TAGS=:systemd:snap_modem-manager_qmicli:snap_network-manager_networkmanager:snap_modem-manager_mbim-network:snap_modem-manager_qmi-network:snap_modem-manager_modemmanager:snap_modem-manager_mbimcli: + +P: /devices/platform/serial8250/tty/ttyS28 +N: ttyS28 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS28 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS28 +E: MAJOR=4 +E: MINOR=92 +E: USEC_INITIALIZED=14412141 +E: ID_MM_CANDIDATE=1 +E: TAGS=:systemd:snap_network-manager_networkmanager:snap_modem-manager_mbim-network:snap_modem-manager_modemmanager:snap_modem-manager_qmicli:snap_modem-manager_qmi-network:snap_modem-manager_mbimcli: + +P: /devices/platform/serial8250/tty/ttyS29 +N: ttyS29 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS29 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS29 +E: MAJOR=4 +E: MINOR=93 +E: USEC_INITIALIZED=14416250 +E: ID_MM_CANDIDATE=1 +E: TAGS=:systemd:snap_modem-manager_mbim-network:snap_modem-manager_qmicli:snap_network-manager_networkmanager:snap_modem-manager_qmi-network:snap_modem-manager_modemmanager:snap_modem-manager_mbimcli: + +P: /devices/platform/serial8250/tty/ttyS3 +N: ttyS3 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS3 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS3 +E: MAJOR=4 +E: MINOR=67 +E: USEC_INITIALIZED=14416263 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_qmi-network:snap_modem-manager_modemmanager:snap_modem-manager_mbimcli:snap_modem-manager_qmicli:snap_network-manager_networkmanager:systemd:snap_modem-manager_mbim-network: + +P: /devices/platform/serial8250/tty/ttyS30 +N: ttyS30 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS30 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS30 +E: MAJOR=4 +E: MINOR=94 +E: USEC_INITIALIZED=14433578 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_network-manager_networkmanager:systemd:snap_modem-manager_modemmanager:snap_modem-manager_qmicli:snap_modem-manager_mbim-network:snap_modem-manager_qmi-network:snap_modem-manager_mbimcli: + +P: /devices/platform/serial8250/tty/ttyS31 +N: ttyS31 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS31 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS31 +E: MAJOR=4 +E: MINOR=95 +E: USEC_INITIALIZED=14448437 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_network-manager_networkmanager:systemd:snap_modem-manager_qmi-network:snap_modem-manager_mbim-network:snap_modem-manager_mbimcli:snap_modem-manager_qmicli:snap_modem-manager_modemmanager: + +P: /devices/platform/serial8250/tty/ttyS7 +N: ttyS7 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS7 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS7 +E: MAJOR=4 +E: MINOR=71 +E: USEC_INITIALIZED=14471948 +E: ID_MM_CANDIDATE=1 +E: TAGS=:systemd:snap_modem-manager_mbim-network:snap_modem-manager_modemmanager:snap_modem-manager_qmicli:snap_network-manager_networkmanager:snap_modem-manager_mbimcli:snap_modem-manager_qmi-network: + +P: /devices/platform/serial8250/tty/ttyS8 +N: ttyS8 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS8 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS8 +E: MAJOR=4 +E: MINOR=72 +E: USEC_INITIALIZED=14489080 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_network-manager_networkmanager:snap_modem-manager_qmi-network:snap_modem-manager_mbim-network:snap_modem-manager_mbimcli:systemd:snap_modem-manager_qmicli:snap_modem-manager_modemmanager: + +P: /devices/platform/serial8250/tty/ttyS9 +N: ttyS9 +L: 0 +E: DEVPATH=/devices/platform/serial8250/tty/ttyS9 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyS9 +E: MAJOR=4 +E: MINOR=73 +E: USEC_INITIALIZED=14516588 +E: ID_MM_CANDIDATE=1 +E: TAGS=:snap_modem-manager_mbimcli:snap_modem-manager_mbim-network:systemd:snap_modem-manager_qmicli:snap_network-manager_networkmanager:snap_modem-manager_qmi-network:snap_modem-manager_modemmanager: + +P: /devices/platform/snd-soc-dummy +L: 0 +E: DEVPATH=/devices/platform/snd-soc-dummy +E: SUBSYSTEM=platform +E: DRIVER=snd-soc-dummy +E: MODALIAS=platform:snd-soc-dummy +E: USEC_INITIALIZED=16824231 +E: ID_PATH=platform-snd-soc-dummy +E: ID_PATH_TAG=platform-snd-soc-dummy + +P: /devices/pnp0/00:00 +L: 0 +E: DEVPATH=/devices/pnp0/00:00 +E: SUBSYSTEM=pnp +E: DRIVER=system + +P: /devices/pnp0/00:01 +L: 0 +E: DEVPATH=/devices/pnp0/00:01 +E: SUBSYSTEM=pnp +E: DRIVER=system + +P: /devices/pnp0/00:02 +L: 0 +E: DEVPATH=/devices/pnp0/00:02 +E: SUBSYSTEM=pnp +E: DRIVER=rtc_cmos + +P: /devices/pnp0/00:02/cmos_nvram0 +L: 0 +E: DEVPATH=/devices/pnp0/00:02/cmos_nvram0 +E: SUBSYSTEM=nvmem + +P: /devices/pnp0/00:02/rtc/rtc0 +N: rtc0 +L: -100 +S: rtc +E: DEVPATH=/devices/pnp0/00:02/rtc/rtc0 +E: SUBSYSTEM=rtc +E: DEVNAME=/dev/rtc0 +E: MAJOR=249 +E: MINOR=0 +E: USEC_INITIALIZED=14543696 +E: DEVLINKS=/dev/rtc +E: TAGS=:snap_everactive-chrony_chronyc:snap_everactive-chrony_chronyd:snap_everactive-chrony_chrony-toggler: + +P: /devices/pnp0/00:02/rtc/rtc0/alarmtimer.0.auto +L: 0 +E: DEVPATH=/devices/pnp0/00:02/rtc/rtc0/alarmtimer.0.auto +E: SUBSYSTEM=platform +E: DRIVER=alarmtimer +E: MODALIAS=platform:alarmtimer +E: USEC_INITIALIZED=14608152 +E: ID_PATH=platform-alarmtimer.0.auto +E: ID_PATH_TAG=platform-alarmtimer_0_auto + +P: /devices/pnp0/00:02/rtc/rtc0/wakeup28 +L: 0 +E: DEVPATH=/devices/pnp0/00:02/rtc/rtc0/wakeup28 +E: SUBSYSTEM=wakeup + +P: /devices/pnp0/00:02/wakeup/wakeup27 +L: 0 +E: DEVPATH=/devices/pnp0/00:02/wakeup/wakeup27 +E: SUBSYSTEM=wakeup + +P: /devices/power +L: 0 +E: DEVPATH=/devices/power +E: SUBSYSTEM=event_source + +P: /devices/software +L: 0 +E: DEVPATH=/devices/software +E: SUBSYSTEM=event_source + +P: /devices/system/clockevents/broadcast +L: 0 +E: DEVPATH=/devices/system/clockevents/broadcast +E: SUBSYSTEM=clockevents + +P: /devices/system/clockevents/clockevent0 +L: 0 +E: DEVPATH=/devices/system/clockevents/clockevent0 +E: SUBSYSTEM=clockevents + +P: /devices/system/clockevents/clockevent1 +L: 0 +E: DEVPATH=/devices/system/clockevents/clockevent1 +E: SUBSYSTEM=clockevents + +P: /devices/system/clockevents/clockevent2 +L: 0 +E: DEVPATH=/devices/system/clockevents/clockevent2 +E: SUBSYSTEM=clockevents + +P: /devices/system/clockevents/clockevent3 +L: 0 +E: DEVPATH=/devices/system/clockevents/clockevent3 +E: SUBSYSTEM=clockevents + +P: /devices/system/clocksource/clocksource0 +L: 0 +E: DEVPATH=/devices/system/clocksource/clocksource0 +E: SUBSYSTEM=clocksource + +P: /devices/system/cpu/cpu0 +L: 0 +E: DEVPATH=/devices/system/cpu/cpu0 +E: SUBSYSTEM=cpu +E: DRIVER=processor +E: MODALIAS=cpu:type:x86,ven0000fam0006mod005C:feature:,0000,0001,0002,0003,0004,0005,0006,0007,0008,0009,000B,000C,000D,000E,000F,0010,0011,0013,0015,0016,0017,0018,0019,001A,001B,001C,001D,001F,002B,0034,003A,003B,003D,0068,006A,006B,006C,006D,006F,0070,0072,0074,0075,0076,0077,0078,0079,007C,007F,0080,0081,0082,0083,0084,0085,0087,0088,0089,008B,008D,008E,008F,0093,0094,0095,0096,0097,0098,0099,009A,009B,009E,00C0,00C8,00E1,00E5,00EC,00F0,00F1,00F3,00F5,00F6,00F9,00FA,00FB,0100,0101,0102,0103,0104,0111,0120,0121,0127,0129,012D,012E,012F,0132,0134,0137,0139,013D,0140,0141,0142,0143,01C0,01C1,01C2,01C4,01C6,024A,025A,025B,025D,025F + +P: /devices/system/cpu/cpu1 +L: 0 +E: DEVPATH=/devices/system/cpu/cpu1 +E: SUBSYSTEM=cpu +E: DRIVER=processor +E: MODALIAS=cpu:type:x86,ven0000fam0006mod005C:feature:,0000,0001,0002,0003,0004,0005,0006,0007,0008,0009,000B,000C,000D,000E,000F,0010,0011,0013,0015,0016,0017,0018,0019,001A,001B,001C,001D,001F,002B,0034,003A,003B,003D,0068,006A,006B,006C,006D,006F,0070,0072,0074,0075,0076,0077,0078,0079,007C,007F,0080,0081,0082,0083,0084,0085,0087,0088,0089,008B,008D,008E,008F,0093,0094,0095,0096,0097,0098,0099,009A,009B,009E,00C0,00C8,00E1,00E5,00EC,00F0,00F1,00F3,00F5,00F6,00F9,00FA,00FB,0100,0101,0102,0103,0104,0111,0120,0121,0127,0129,012D,012E,012F,0132,0134,0137,0139,013D,0140,0141,0142,0143,01C0,01C1,01C2,01C4,01C6,024A,025A,025B,025D,025F + +P: /devices/system/cpu/cpu2 +L: 0 +E: DEVPATH=/devices/system/cpu/cpu2 +E: SUBSYSTEM=cpu +E: DRIVER=processor +E: MODALIAS=cpu:type:x86,ven0000fam0006mod005C:feature:,0000,0001,0002,0003,0004,0005,0006,0007,0008,0009,000B,000C,000D,000E,000F,0010,0011,0013,0015,0016,0017,0018,0019,001A,001B,001C,001D,001F,002B,0034,003A,003B,003D,0068,006A,006B,006C,006D,006F,0070,0072,0074,0075,0076,0077,0078,0079,007C,007F,0080,0081,0082,0083,0084,0085,0087,0088,0089,008B,008D,008E,008F,0093,0094,0095,0096,0097,0098,0099,009A,009B,009E,00C0,00C8,00E1,00E5,00EC,00F0,00F1,00F3,00F5,00F6,00F9,00FA,00FB,0100,0101,0102,0103,0104,0111,0120,0121,0127,0129,012D,012E,012F,0132,0134,0137,0139,013D,0140,0141,0142,0143,01C0,01C1,01C2,01C4,01C6,024A,025A,025B,025D,025F + +P: /devices/system/cpu/cpu3 +L: 0 +E: DEVPATH=/devices/system/cpu/cpu3 +E: SUBSYSTEM=cpu +E: DRIVER=processor +E: MODALIAS=cpu:type:x86,ven0000fam0006mod005C:feature:,0000,0001,0002,0003,0004,0005,0006,0007,0008,0009,000B,000C,000D,000E,000F,0010,0011,0013,0015,0016,0017,0018,0019,001A,001B,001C,001D,001F,002B,0034,003A,003B,003D,0068,006A,006B,006C,006D,006F,0070,0072,0074,0075,0076,0077,0078,0079,007C,007F,0080,0081,0082,0083,0084,0085,0087,0088,0089,008B,008D,008E,008F,0093,0094,0095,0096,0097,0098,0099,009A,009B,009E,00C0,00C8,00E1,00E5,00EC,00F0,00F1,00F3,00F5,00F6,00F9,00FA,00FB,0100,0101,0102,0103,0104,0111,0120,0121,0127,0129,012D,012E,012F,0132,0134,0137,0139,013D,0140,0141,0142,0143,01C0,01C1,01C2,01C4,01C6,024A,025A,025B,025D,025F + +P: /devices/system/edac/mc +L: 0 +E: DEVPATH=/devices/system/edac/mc +E: SUBSYSTEM=edac + +P: /devices/system/machinecheck/machinecheck0 +L: 0 +E: DEVPATH=/devices/system/machinecheck/machinecheck0 +E: SUBSYSTEM=machinecheck + +P: /devices/system/machinecheck/machinecheck1 +L: 0 +E: DEVPATH=/devices/system/machinecheck/machinecheck1 +E: SUBSYSTEM=machinecheck + +P: /devices/system/machinecheck/machinecheck2 +L: 0 +E: DEVPATH=/devices/system/machinecheck/machinecheck2 +E: SUBSYSTEM=machinecheck + +P: /devices/system/machinecheck/machinecheck3 +L: 0 +E: DEVPATH=/devices/system/machinecheck/machinecheck3 +E: SUBSYSTEM=machinecheck + +P: /devices/system/memory/memory0 +L: 0 +E: DEVPATH=/devices/system/memory/memory0 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory1 +L: 0 +E: DEVPATH=/devices/system/memory/memory1 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory10 +L: 0 +E: DEVPATH=/devices/system/memory/memory10 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory11 +L: 0 +E: DEVPATH=/devices/system/memory/memory11 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory12 +L: 0 +E: DEVPATH=/devices/system/memory/memory12 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory13 +L: 0 +E: DEVPATH=/devices/system/memory/memory13 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory14 +L: 0 +E: DEVPATH=/devices/system/memory/memory14 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory15 +L: 0 +E: DEVPATH=/devices/system/memory/memory15 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory2 +L: 0 +E: DEVPATH=/devices/system/memory/memory2 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory3 +L: 0 +E: DEVPATH=/devices/system/memory/memory3 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory32 +L: 0 +E: DEVPATH=/devices/system/memory/memory32 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory33 +L: 0 +E: DEVPATH=/devices/system/memory/memory33 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory34 +L: 0 +E: DEVPATH=/devices/system/memory/memory34 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory35 +L: 0 +E: DEVPATH=/devices/system/memory/memory35 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory36 +L: 0 +E: DEVPATH=/devices/system/memory/memory36 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory37 +L: 0 +E: DEVPATH=/devices/system/memory/memory37 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory38 +L: 0 +E: DEVPATH=/devices/system/memory/memory38 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory39 +L: 0 +E: DEVPATH=/devices/system/memory/memory39 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory4 +L: 0 +E: DEVPATH=/devices/system/memory/memory4 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory40 +L: 0 +E: DEVPATH=/devices/system/memory/memory40 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory41 +L: 0 +E: DEVPATH=/devices/system/memory/memory41 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory42 +L: 0 +E: DEVPATH=/devices/system/memory/memory42 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory43 +L: 0 +E: DEVPATH=/devices/system/memory/memory43 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory44 +L: 0 +E: DEVPATH=/devices/system/memory/memory44 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory45 +L: 0 +E: DEVPATH=/devices/system/memory/memory45 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory46 +L: 0 +E: DEVPATH=/devices/system/memory/memory46 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory47 +L: 0 +E: DEVPATH=/devices/system/memory/memory47 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory5 +L: 0 +E: DEVPATH=/devices/system/memory/memory5 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory6 +L: 0 +E: DEVPATH=/devices/system/memory/memory6 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory7 +L: 0 +E: DEVPATH=/devices/system/memory/memory7 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory8 +L: 0 +E: DEVPATH=/devices/system/memory/memory8 +E: SUBSYSTEM=memory + +P: /devices/system/memory/memory9 +L: 0 +E: DEVPATH=/devices/system/memory/memory9 +E: SUBSYSTEM=memory + +P: /devices/system/node/node0 +L: 0 +E: DEVPATH=/devices/system/node/node0 +E: SUBSYSTEM=node + +P: /devices/tracepoint +L: 0 +E: DEVPATH=/devices/tracepoint +E: SUBSYSTEM=event_source + +P: /devices/uprobe +L: 0 +E: DEVPATH=/devices/uprobe +E: SUBSYSTEM=event_source + +P: /devices/virtual/bdi/179:0 +L: 0 +E: DEVPATH=/devices/virtual/bdi/179:0 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/179:16 +L: 0 +E: DEVPATH=/devices/virtual/bdi/179:16 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/179:24 +L: 0 +E: DEVPATH=/devices/virtual/bdi/179:24 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/179:8 +L: 0 +E: DEVPATH=/devices/virtual/bdi/179:8 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/253:0 +L: 0 +E: DEVPATH=/devices/virtual/bdi/253:0 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/253:1 +L: 0 +E: DEVPATH=/devices/virtual/bdi/253:1 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:0 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:0 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:1 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:1 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:10 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:10 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:11 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:11 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:12 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:12 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:13 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:13 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:14 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:14 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:15 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:15 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:16 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:16 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:17 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:17 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:18 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:18 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:19 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:19 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:2 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:2 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:20 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:20 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:21 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:21 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:22 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:22 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:23 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:23 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:24 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:24 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:25 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:25 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:26 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:26 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:27 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:27 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:28 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:28 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:29 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:29 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:3 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:3 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:30 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:30 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:31 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:31 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:4 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:4 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:5 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:5 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:6 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:6 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:7 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:7 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:8 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:8 +E: SUBSYSTEM=bdi + +P: /devices/virtual/bdi/7:9 +L: 0 +E: DEVPATH=/devices/virtual/bdi/7:9 +E: SUBSYSTEM=bdi + +P: /devices/virtual/block/loop0 +N: loop0 +L: 0 +E: DEVPATH=/devices/virtual/block/loop0 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop0 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=0 +E: USEC_INITIALIZED=14848372 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop1 +N: loop1 +L: 0 +E: DEVPATH=/devices/virtual/block/loop1 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop1 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=1 +E: USEC_INITIALIZED=14920091 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop10 +N: loop10 +L: 0 +E: DEVPATH=/devices/virtual/block/loop10 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop10 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=10 +E: USEC_INITIALIZED=16641906 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop11 +N: loop11 +L: 0 +E: DEVPATH=/devices/virtual/block/loop11 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop11 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=11 +E: USEC_INITIALIZED=16544666 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop12 +N: loop12 +L: 0 +E: DEVPATH=/devices/virtual/block/loop12 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop12 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=12 +E: USEC_INITIALIZED=16479302 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop13 +N: loop13 +L: 0 +E: DEVPATH=/devices/virtual/block/loop13 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop13 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=13 +E: USEC_INITIALIZED=16620242 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop14 +N: loop14 +L: 0 +E: DEVPATH=/devices/virtual/block/loop14 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop14 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=14 +E: USEC_INITIALIZED=16554267 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop15 +N: loop15 +L: 0 +E: DEVPATH=/devices/virtual/block/loop15 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop15 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=15 +E: USEC_INITIALIZED=16565870 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop16 +N: loop16 +L: 0 +E: DEVPATH=/devices/virtual/block/loop16 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop16 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=16 +E: USEC_INITIALIZED=16636270 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop17 +N: loop17 +L: 0 +E: DEVPATH=/devices/virtual/block/loop17 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop17 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=17 +E: USEC_INITIALIZED=16561991 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop18 +N: loop18 +L: 0 +E: DEVPATH=/devices/virtual/block/loop18 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop18 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=18 +E: USEC_INITIALIZED=16662615 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop19 +N: loop19 +L: 0 +E: DEVPATH=/devices/virtual/block/loop19 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop19 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=19 +E: USEC_INITIALIZED=16854603 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop2 +N: loop2 +L: 0 +E: DEVPATH=/devices/virtual/block/loop2 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop2 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=2 +E: USEC_INITIALIZED=14942269 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop20 +N: loop20 +L: 0 +E: DEVPATH=/devices/virtual/block/loop20 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop20 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=20 +E: USEC_INITIALIZED=16685017 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop21 +N: loop21 +L: 0 +E: DEVPATH=/devices/virtual/block/loop21 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop21 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=21 +E: USEC_INITIALIZED=16846122 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop22 +N: loop22 +L: 0 +E: DEVPATH=/devices/virtual/block/loop22 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop22 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=22 +E: USEC_INITIALIZED=16851072 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop23 +N: loop23 +L: 0 +E: DEVPATH=/devices/virtual/block/loop23 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop23 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=23 +E: USEC_INITIALIZED=16888175 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop24 +N: loop24 +L: 0 +E: DEVPATH=/devices/virtual/block/loop24 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop24 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=24 +E: USEC_INITIALIZED=16864234 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop25 +N: loop25 +L: 0 +E: DEVPATH=/devices/virtual/block/loop25 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop25 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=25 +E: USEC_INITIALIZED=16937113 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop26 +N: loop26 +L: 0 +E: DEVPATH=/devices/virtual/block/loop26 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop26 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=26 +E: USEC_INITIALIZED=16961883 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop27 +N: loop27 +L: 0 +E: DEVPATH=/devices/virtual/block/loop27 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop27 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=27 +E: USEC_INITIALIZED=16877947 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop28 +N: loop28 +L: 0 +E: DEVPATH=/devices/virtual/block/loop28 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop28 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=28 +E: USEC_INITIALIZED=16894792 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop29 +N: loop29 +L: 0 +E: DEVPATH=/devices/virtual/block/loop29 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop29 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=29 +E: USEC_INITIALIZED=16977522 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop3 +N: loop3 +L: 0 +E: DEVPATH=/devices/virtual/block/loop3 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop3 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=3 +E: USEC_INITIALIZED=15006408 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop30 +N: loop30 +L: 0 +E: DEVPATH=/devices/virtual/block/loop30 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop30 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=30 +E: USEC_INITIALIZED=16993428 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop31 +N: loop31 +L: 0 +E: DEVPATH=/devices/virtual/block/loop31 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop31 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=31 +E: USEC_INITIALIZED=29536460 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop4 +N: loop4 +L: 0 +E: DEVPATH=/devices/virtual/block/loop4 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop4 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=4 +E: USEC_INITIALIZED=15011469 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop5 +N: loop5 +L: 0 +E: DEVPATH=/devices/virtual/block/loop5 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop5 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=5 +E: USEC_INITIALIZED=14922798 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop6 +N: loop6 +L: 0 +E: DEVPATH=/devices/virtual/block/loop6 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop6 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=6 +E: USEC_INITIALIZED=14919075 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop7 +N: loop7 +L: 0 +E: DEVPATH=/devices/virtual/block/loop7 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop7 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=7 +E: USEC_INITIALIZED=14917869 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop8 +N: loop8 +L: 0 +E: DEVPATH=/devices/virtual/block/loop8 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop8 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=8 +E: USEC_INITIALIZED=16169225 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/block/loop9 +N: loop9 +L: 0 +E: DEVPATH=/devices/virtual/block/loop9 +E: SUBSYSTEM=block +E: DEVNAME=/dev/loop9 +E: DEVTYPE=disk +E: MAJOR=7 +E: MINOR=9 +E: USEC_INITIALIZED=16446270 +E: ID_FS_VERSION=4.0 +E: ID_FS_TYPE=squashfs +E: ID_FS_USAGE=filesystem +E: TAGS=:systemd: + +P: /devices/virtual/dmi/id +L: 0 +E: DEVPATH=/devices/virtual/dmi/id +E: SUBSYSTEM=dmi +E: MODALIAS=dmi:bvnAmericanMegatrendsInc.:bvrSA50R151:bd10/09/2019:svnEveractive:pnApex:pvr:rvncongatec:rnconga-SA5:rvrB.3:cvnEveractive:ct2:cvr0.2: + +P: /devices/virtual/graphics/fbcon +L: 0 +E: DEVPATH=/devices/virtual/graphics/fbcon +E: SUBSYSTEM=graphics + +P: /devices/virtual/input/mice +N: input/mice +L: 0 +E: DEVPATH=/devices/virtual/input/mice +E: SUBSYSTEM=input +E: DEVNAME=/dev/input/mice +E: MAJOR=13 +E: MINOR=63 + +P: /devices/virtual/mem/full +N: full +L: 0 +E: DEVPATH=/devices/virtual/mem/full +E: SUBSYSTEM=mem +E: DEVNAME=/dev/full +E: DEVMODE=0666 +E: MAJOR=1 +E: MINOR=7 + +P: /devices/virtual/mem/kmsg +N: kmsg +L: 0 +E: DEVPATH=/devices/virtual/mem/kmsg +E: SUBSYSTEM=mem +E: DEVNAME=/dev/kmsg +E: DEVMODE=0644 +E: MAJOR=1 +E: MINOR=11 + +P: /devices/virtual/mem/mem +N: mem +L: 0 +E: DEVPATH=/devices/virtual/mem/mem +E: SUBSYSTEM=mem +E: DEVNAME=/dev/mem +E: MAJOR=1 +E: MINOR=1 + +P: /devices/virtual/mem/null +N: null +L: 0 +E: DEVPATH=/devices/virtual/mem/null +E: SUBSYSTEM=mem +E: DEVNAME=/dev/null +E: DEVMODE=0666 +E: MAJOR=1 +E: MINOR=3 + +P: /devices/virtual/mem/port +N: port +L: 0 +E: DEVPATH=/devices/virtual/mem/port +E: SUBSYSTEM=mem +E: DEVNAME=/dev/port +E: MAJOR=1 +E: MINOR=4 + +P: /devices/virtual/mem/random +N: random +L: 0 +E: DEVPATH=/devices/virtual/mem/random +E: SUBSYSTEM=mem +E: DEVNAME=/dev/random +E: DEVMODE=0666 +E: MAJOR=1 +E: MINOR=8 + +P: /devices/virtual/mem/urandom +N: urandom +L: 0 +E: DEVPATH=/devices/virtual/mem/urandom +E: SUBSYSTEM=mem +E: DEVNAME=/dev/urandom +E: DEVMODE=0666 +E: MAJOR=1 +E: MINOR=9 + +P: /devices/virtual/mem/zero +N: zero +L: 0 +E: DEVPATH=/devices/virtual/mem/zero +E: SUBSYSTEM=mem +E: DEVNAME=/dev/zero +E: DEVMODE=0666 +E: MAJOR=1 +E: MINOR=5 + +P: /devices/virtual/misc/autofs +N: autofs +L: 0 +E: DEVPATH=/devices/virtual/misc/autofs +E: SUBSYSTEM=misc +E: DEVNAME=/dev/autofs +E: DEVMODE=0644 +E: MAJOR=10 +E: MINOR=235 + +P: /devices/virtual/misc/cpu_dma_latency +N: cpu_dma_latency +L: 0 +E: DEVPATH=/devices/virtual/misc/cpu_dma_latency +E: SUBSYSTEM=misc +E: DEVNAME=/dev/cpu_dma_latency +E: MAJOR=10 +E: MINOR=59 + +P: /devices/virtual/misc/device-mapper +N: mapper/control +L: 0 +E: DEVPATH=/devices/virtual/misc/device-mapper +E: SUBSYSTEM=misc +E: DEVNAME=/dev/mapper/control +E: MAJOR=10 +E: MINOR=236 + +P: /devices/virtual/misc/ecryptfs +N: ecryptfs +L: 0 +E: DEVPATH=/devices/virtual/misc/ecryptfs +E: SUBSYSTEM=misc +E: DEVNAME=/dev/ecryptfs +E: MAJOR=10 +E: MINOR=62 + +P: /devices/virtual/misc/fuse +N: fuse +L: 0 +E: DEVPATH=/devices/virtual/misc/fuse +E: SUBSYSTEM=misc +E: DEVNAME=/dev/fuse +E: MAJOR=10 +E: MINOR=229 + +P: /devices/virtual/misc/hpet +N: hpet +L: 0 +E: DEVPATH=/devices/virtual/misc/hpet +E: SUBSYSTEM=misc +E: DEVNAME=/dev/hpet +E: MAJOR=10 +E: MINOR=228 + +P: /devices/virtual/misc/hw_random +N: hwrng +L: 0 +E: DEVPATH=/devices/virtual/misc/hw_random +E: SUBSYSTEM=misc +E: DEVNAME=/dev/hwrng +E: MAJOR=10 +E: MINOR=183 + +P: /devices/virtual/misc/kvm +N: kvm +L: 0 +E: DEVPATH=/devices/virtual/misc/kvm +E: SUBSYSTEM=misc +E: DEVNAME=/dev/kvm +E: MAJOR=10 +E: MINOR=232 +E: USEC_INITIALIZED=17748341 +E: TAGS=:uaccess:seat: + +P: /devices/virtual/misc/lightnvm +N: lightnvm/control +L: 0 +E: DEVPATH=/devices/virtual/misc/lightnvm +E: SUBSYSTEM=misc +E: DEVNAME=/dev/lightnvm/control +E: MAJOR=10 +E: MINOR=61 + +P: /devices/virtual/misc/loop-control +N: loop-control +L: 0 +E: DEVPATH=/devices/virtual/misc/loop-control +E: SUBSYSTEM=misc +E: DEVNAME=/dev/loop-control +E: MAJOR=10 +E: MINOR=237 + +P: /devices/virtual/misc/mcelog +N: mcelog +L: 0 +E: DEVPATH=/devices/virtual/misc/mcelog +E: SUBSYSTEM=misc +E: DEVNAME=/dev/mcelog +E: MAJOR=10 +E: MINOR=227 + +P: /devices/virtual/misc/microcode +N: cpu/microcode +L: 0 +E: DEVPATH=/devices/virtual/misc/microcode +E: SUBSYSTEM=misc +E: DEVNAME=/dev/cpu/microcode +E: MAJOR=10 +E: MINOR=184 + +P: /devices/virtual/misc/psaux +N: psaux +L: 0 +E: DEVPATH=/devices/virtual/misc/psaux +E: SUBSYSTEM=misc +E: DEVNAME=/dev/psaux +E: MAJOR=10 +E: MINOR=1 + +P: /devices/virtual/misc/rfkill +N: rfkill +L: 0 +E: DEVPATH=/devices/virtual/misc/rfkill +E: SUBSYSTEM=misc +E: DEVNAME=/dev/rfkill +E: MAJOR=10 +E: MINOR=242 +E: USEC_INITIALIZED=15027424 +E: SYSTEMD_WANTS=systemd-rfkill.socket +E: TAGS=:snap_bluez_sdptool:snap_network-manager_networkmanager:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_bluez_bluetoothctl:snap_everactive-firmware-utilities_sensor-radio-version:snap_bluez_obexctl:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-firmware-utilities_hook_install:snap_everactive-gateway-services_receiver:systemd:snap_everactive-firmware-utilities_mc-update:snap_everactive-dnsmasq_dnsmasq:snap_everactive-firmware-utilities_mc-status:snap_everactive-dnsmasq_dnsmasq-start:snap_everactive-firmware-utilities_mc-activate: + +P: /devices/virtual/misc/snapshot +N: snapshot +L: 0 +E: DEVPATH=/devices/virtual/misc/snapshot +E: SUBSYSTEM=misc +E: DEVNAME=/dev/snapshot +E: MAJOR=10 +E: MINOR=231 + +P: /devices/virtual/misc/tun +N: net/tun +L: 0 +E: DEVPATH=/devices/virtual/misc/tun +E: SUBSYSTEM=misc +E: DEVNAME=/dev/net/tun +E: MAJOR=10 +E: MINOR=200 +E: USEC_INITIALIZED=15035585 +E: TAGS=:snap_everactive-firmware-utilities_mc-activate:snap_everactive-firmware-utilities_sensor-radio-update-no-reload:snap_everactive-gateway-services_receiver:snap_everactive-firmware-utilities_mc-update:snap_everactive-firmware-utilities_utilities-daemon:snap_everactive-dnsmasq_dnsmasq:snap_everactive-firmware-utilities_sensor-radio-update:snap_everactive-firmware-utilities_sensor-radio-version:snap_everactive-firmware-utilities_hook_install:snap_everactive-firmware-utilities_mc-status:snap_everactive-dnsmasq_dnsmasq-start: + +P: /devices/virtual/misc/udmabuf +N: udmabuf +L: 0 +E: DEVPATH=/devices/virtual/misc/udmabuf +E: SUBSYSTEM=misc +E: DEVNAME=/dev/udmabuf +E: MAJOR=10 +E: MINOR=60 + +P: /devices/virtual/misc/uinput +N: uinput +L: 0 +E: DEVPATH=/devices/virtual/misc/uinput +E: SUBSYSTEM=misc +E: DEVNAME=/dev/uinput +E: MAJOR=10 +E: MINOR=223 + +P: /devices/virtual/misc/vfio +N: vfio/vfio +L: 0 +E: DEVPATH=/devices/virtual/misc/vfio +E: SUBSYSTEM=misc +E: DEVNAME=/dev/vfio/vfio +E: DEVMODE=0666 +E: MAJOR=10 +E: MINOR=196 + +P: /devices/virtual/misc/vga_arbiter +N: vga_arbiter +L: 0 +E: DEVPATH=/devices/virtual/misc/vga_arbiter +E: SUBSYSTEM=misc +E: DEVNAME=/dev/vga_arbiter +E: MAJOR=10 +E: MINOR=63 + +P: /devices/virtual/net/lo +L: 0 +E: DEVPATH=/devices/virtual/net/lo +E: SUBSYSTEM=net +E: INTERFACE=lo +E: IFINDEX=1 +E: USEC_INITIALIZED=15060944 +E: ID_MM_CANDIDATE=1 +E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link + +P: /devices/virtual/powercap/intel-rapl +L: 0 +E: DEVPATH=/devices/virtual/powercap/intel-rapl +E: SUBSYSTEM=powercap + +P: /devices/virtual/powercap/intel-rapl/intel-rapl:0 +L: 0 +E: DEVPATH=/devices/virtual/powercap/intel-rapl/intel-rapl:0 +E: SUBSYSTEM=powercap + +P: /devices/virtual/powercap/intel-rapl/intel-rapl:0/intel-rapl:0:0 +L: 0 +E: DEVPATH=/devices/virtual/powercap/intel-rapl/intel-rapl:0/intel-rapl:0:0 +E: SUBSYSTEM=powercap + +P: /devices/virtual/powercap/intel-rapl/intel-rapl:0/intel-rapl:0:1 +L: 0 +E: DEVPATH=/devices/virtual/powercap/intel-rapl/intel-rapl:0/intel-rapl:0:1 +E: SUBSYSTEM=powercap + +P: /devices/virtual/powercap/intel-rapl/intel-rapl:0/intel-rapl:0:2 +L: 0 +E: DEVPATH=/devices/virtual/powercap/intel-rapl/intel-rapl:0/intel-rapl:0:2 +E: SUBSYSTEM=powercap + +P: /devices/virtual/ppp/ppp +N: ppp +L: 0 +E: DEVPATH=/devices/virtual/ppp/ppp +E: SUBSYSTEM=ppp +E: DEVNAME=/dev/ppp +E: MAJOR=108 +E: MINOR=0 +E: USEC_INITIALIZED=15043382 +E: TAGS=:snap_network-manager_networkmanager: + +P: /devices/virtual/pps/pps0 +N: pps0 +L: 0 +E: DEVPATH=/devices/virtual/pps/pps0 +E: SUBSYSTEM=pps +E: DEVNAME=/dev/pps0 +E: MAJOR=247 +E: MINOR=0 + +P: /devices/virtual/pps/pps1 +N: pps1 +L: 0 +E: DEVPATH=/devices/virtual/pps/pps1 +E: SUBSYSTEM=pps +E: DEVNAME=/dev/pps1 +E: MAJOR=247 +E: MINOR=1 + +P: /devices/virtual/sound/timer +N: snd/timer +L: 0 +E: DEVPATH=/devices/virtual/sound/timer +E: SUBSYSTEM=sound +E: DEVNAME=/dev/snd/timer +E: MAJOR=116 +E: MINOR=33 +E: USEC_INITIALIZED=16604942 +E: TAGS=:uaccess: + +P: /devices/virtual/thermal/cooling_device0 +L: 0 +E: DEVPATH=/devices/virtual/thermal/cooling_device0 +E: SUBSYSTEM=thermal + +P: /devices/virtual/thermal/cooling_device1 +L: 0 +E: DEVPATH=/devices/virtual/thermal/cooling_device1 +E: SUBSYSTEM=thermal + +P: /devices/virtual/thermal/cooling_device2 +L: 0 +E: DEVPATH=/devices/virtual/thermal/cooling_device2 +E: SUBSYSTEM=thermal + +P: /devices/virtual/thermal/cooling_device3 +L: 0 +E: DEVPATH=/devices/virtual/thermal/cooling_device3 +E: SUBSYSTEM=thermal + +P: /devices/virtual/thermal/cooling_device4 +L: 0 +E: DEVPATH=/devices/virtual/thermal/cooling_device4 +E: SUBSYSTEM=thermal + +P: /devices/virtual/thermal/cooling_device5 +L: 0 +E: DEVPATH=/devices/virtual/thermal/cooling_device5 +E: SUBSYSTEM=thermal + +P: /devices/virtual/thermal/cooling_device6 +L: 0 +E: DEVPATH=/devices/virtual/thermal/cooling_device6 +E: SUBSYSTEM=thermal + +P: /devices/virtual/thermal/cooling_device7 +L: 0 +E: DEVPATH=/devices/virtual/thermal/cooling_device7 +E: SUBSYSTEM=thermal + +P: /devices/virtual/thermal/thermal_zone0 +L: 0 +E: DEVPATH=/devices/virtual/thermal/thermal_zone0 +E: SUBSYSTEM=thermal + +P: /devices/virtual/thermal/thermal_zone0/hwmon1 +L: 0 +E: DEVPATH=/devices/virtual/thermal/thermal_zone0/hwmon1 +E: SUBSYSTEM=hwmon + +P: /devices/virtual/thermal/thermal_zone1 +L: 0 +E: DEVPATH=/devices/virtual/thermal/thermal_zone1 +E: SUBSYSTEM=thermal + +P: /devices/virtual/thermal/thermal_zone2 +L: 0 +E: DEVPATH=/devices/virtual/thermal/thermal_zone2 +E: SUBSYSTEM=thermal + +P: /devices/virtual/thermal/thermal_zone2/hwmon3 +L: 0 +E: DEVPATH=/devices/virtual/thermal/thermal_zone2/hwmon3 +E: SUBSYSTEM=hwmon + +P: /devices/virtual/tty/console +N: console +L: 0 +E: DEVPATH=/devices/virtual/tty/console +E: SUBSYSTEM=tty +E: DEVNAME=/dev/console +E: MAJOR=5 +E: MINOR=1 +E: USEC_INITIALIZED=15065409 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/ptmx +N: ptmx +L: 0 +E: DEVPATH=/devices/virtual/tty/ptmx +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ptmx +E: DEVMODE=0666 +E: MAJOR=5 +E: MINOR=2 +E: USEC_INITIALIZED=15071031 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty +N: tty +L: 0 +E: DEVPATH=/devices/virtual/tty/tty +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty +E: DEVMODE=0666 +E: MAJOR=5 +E: MINOR=0 +E: USEC_INITIALIZED=15079987 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty0 +N: tty0 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty0 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty0 +E: MAJOR=4 +E: MINOR=0 +E: USEC_INITIALIZED=15073786 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty1 +N: tty1 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty1 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty1 +E: MAJOR=4 +E: MINOR=1 +E: USEC_INITIALIZED=15079002 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty10 +N: tty10 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty10 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty10 +E: MAJOR=4 +E: MINOR=10 +E: USEC_INITIALIZED=15077284 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty11 +N: tty11 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty11 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty11 +E: MAJOR=4 +E: MINOR=11 +E: USEC_INITIALIZED=15075502 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty12 +N: tty12 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty12 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty12 +E: MAJOR=4 +E: MINOR=12 +E: USEC_INITIALIZED=15078116 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty13 +N: tty13 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty13 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty13 +E: MAJOR=4 +E: MINOR=13 +E: USEC_INITIALIZED=15075844 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty14 +N: tty14 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty14 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty14 +E: MAJOR=4 +E: MINOR=14 +E: USEC_INITIALIZED=15084697 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty15 +N: tty15 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty15 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty15 +E: MAJOR=4 +E: MINOR=15 +E: USEC_INITIALIZED=15094270 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty16 +N: tty16 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty16 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty16 +E: MAJOR=4 +E: MINOR=16 +E: USEC_INITIALIZED=15095523 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty17 +N: tty17 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty17 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty17 +E: MAJOR=4 +E: MINOR=17 +E: USEC_INITIALIZED=15094169 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty18 +N: tty18 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty18 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty18 +E: MAJOR=4 +E: MINOR=18 +E: USEC_INITIALIZED=15100399 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty19 +N: tty19 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty19 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty19 +E: MAJOR=4 +E: MINOR=19 +E: USEC_INITIALIZED=15103231 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty2 +N: tty2 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty2 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty2 +E: MAJOR=4 +E: MINOR=2 +E: USEC_INITIALIZED=15107328 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty20 +N: tty20 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty20 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty20 +E: MAJOR=4 +E: MINOR=20 +E: USEC_INITIALIZED=15102312 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty21 +N: tty21 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty21 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty21 +E: MAJOR=4 +E: MINOR=21 +E: USEC_INITIALIZED=15105320 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty22 +N: tty22 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty22 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty22 +E: MAJOR=4 +E: MINOR=22 +E: USEC_INITIALIZED=15106554 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty23 +N: tty23 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty23 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty23 +E: MAJOR=4 +E: MINOR=23 +E: USEC_INITIALIZED=15107765 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty24 +N: tty24 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty24 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty24 +E: MAJOR=4 +E: MINOR=24 +E: USEC_INITIALIZED=15108969 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty25 +N: tty25 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty25 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty25 +E: MAJOR=4 +E: MINOR=25 +E: USEC_INITIALIZED=15110408 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty26 +N: tty26 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty26 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty26 +E: MAJOR=4 +E: MINOR=26 +E: USEC_INITIALIZED=15124599 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty27 +N: tty27 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty27 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty27 +E: MAJOR=4 +E: MINOR=27 +E: USEC_INITIALIZED=15128980 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty28 +N: tty28 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty28 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty28 +E: MAJOR=4 +E: MINOR=28 +E: USEC_INITIALIZED=15126321 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty29 +N: tty29 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty29 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty29 +E: MAJOR=4 +E: MINOR=29 +E: USEC_INITIALIZED=15127671 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty3 +N: tty3 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty3 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty3 +E: MAJOR=4 +E: MINOR=3 +E: USEC_INITIALIZED=15129061 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty30 +N: tty30 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty30 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty30 +E: MAJOR=4 +E: MINOR=30 +E: USEC_INITIALIZED=15133760 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty31 +N: tty31 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty31 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty31 +E: MAJOR=4 +E: MINOR=31 +E: USEC_INITIALIZED=15135858 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty32 +N: tty32 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty32 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty32 +E: MAJOR=4 +E: MINOR=32 +E: USEC_INITIALIZED=15135107 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty33 +N: tty33 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty33 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty33 +E: MAJOR=4 +E: MINOR=33 +E: USEC_INITIALIZED=15136376 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty34 +N: tty34 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty34 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty34 +E: MAJOR=4 +E: MINOR=34 +E: USEC_INITIALIZED=15137531 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty35 +N: tty35 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty35 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty35 +E: MAJOR=4 +E: MINOR=35 +E: USEC_INITIALIZED=15140136 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty36 +N: tty36 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty36 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty36 +E: MAJOR=4 +E: MINOR=36 +E: USEC_INITIALIZED=15141405 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty37 +N: tty37 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty37 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty37 +E: MAJOR=4 +E: MINOR=37 +E: USEC_INITIALIZED=15146085 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty38 +N: tty38 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty38 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty38 +E: MAJOR=4 +E: MINOR=38 +E: USEC_INITIALIZED=15145680 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty39 +N: tty39 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty39 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty39 +E: MAJOR=4 +E: MINOR=39 +E: USEC_INITIALIZED=15143044 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty4 +N: tty4 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty4 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty4 +E: MAJOR=4 +E: MINOR=4 +E: USEC_INITIALIZED=15144561 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty40 +N: tty40 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty40 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty40 +E: MAJOR=4 +E: MINOR=40 +E: USEC_INITIALIZED=15147850 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty41 +N: tty41 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty41 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty41 +E: MAJOR=4 +E: MINOR=41 +E: USEC_INITIALIZED=15149342 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty42 +N: tty42 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty42 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty42 +E: MAJOR=4 +E: MINOR=42 +E: USEC_INITIALIZED=15150718 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty43 +N: tty43 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty43 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty43 +E: MAJOR=4 +E: MINOR=43 +E: USEC_INITIALIZED=15152024 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty44 +N: tty44 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty44 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty44 +E: MAJOR=4 +E: MINOR=44 +E: USEC_INITIALIZED=15157543 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty45 +N: tty45 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty45 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty45 +E: MAJOR=4 +E: MINOR=45 +E: USEC_INITIALIZED=15153982 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty46 +N: tty46 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty46 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty46 +E: MAJOR=4 +E: MINOR=46 +E: USEC_INITIALIZED=15153689 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty47 +N: tty47 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty47 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty47 +E: MAJOR=4 +E: MINOR=47 +E: USEC_INITIALIZED=15158011 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty48 +N: tty48 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty48 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty48 +E: MAJOR=4 +E: MINOR=48 +E: USEC_INITIALIZED=15156798 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty49 +N: tty49 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty49 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty49 +E: MAJOR=4 +E: MINOR=49 +E: USEC_INITIALIZED=15156786 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty5 +N: tty5 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty5 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty5 +E: MAJOR=4 +E: MINOR=5 +E: USEC_INITIALIZED=15170940 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty50 +N: tty50 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty50 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty50 +E: MAJOR=4 +E: MINOR=50 +E: USEC_INITIALIZED=15179361 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty51 +N: tty51 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty51 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty51 +E: MAJOR=4 +E: MINOR=51 +E: USEC_INITIALIZED=15175644 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty52 +N: tty52 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty52 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty52 +E: MAJOR=4 +E: MINOR=52 +E: USEC_INITIALIZED=15176117 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty53 +N: tty53 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty53 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty53 +E: MAJOR=4 +E: MINOR=53 +E: USEC_INITIALIZED=15176068 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty54 +N: tty54 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty54 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty54 +E: MAJOR=4 +E: MINOR=54 +E: USEC_INITIALIZED=15180457 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty55 +N: tty55 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty55 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty55 +E: MAJOR=4 +E: MINOR=55 +E: USEC_INITIALIZED=15225593 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty56 +N: tty56 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty56 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty56 +E: MAJOR=4 +E: MINOR=56 +E: USEC_INITIALIZED=15199516 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty57 +N: tty57 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty57 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty57 +E: MAJOR=4 +E: MINOR=57 +E: USEC_INITIALIZED=15182103 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty58 +N: tty58 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty58 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty58 +E: MAJOR=4 +E: MINOR=58 +E: USEC_INITIALIZED=15188761 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty59 +N: tty59 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty59 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty59 +E: MAJOR=4 +E: MINOR=59 +E: USEC_INITIALIZED=15214807 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty6 +N: tty6 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty6 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty6 +E: MAJOR=4 +E: MINOR=6 +E: USEC_INITIALIZED=15208524 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty60 +N: tty60 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty60 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty60 +E: MAJOR=4 +E: MINOR=60 +E: USEC_INITIALIZED=15186752 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty61 +N: tty61 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty61 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty61 +E: MAJOR=4 +E: MINOR=61 +E: USEC_INITIALIZED=15186363 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty62 +N: tty62 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty62 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty62 +E: MAJOR=4 +E: MINOR=62 +E: USEC_INITIALIZED=15211555 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty63 +N: tty63 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty63 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty63 +E: MAJOR=4 +E: MINOR=63 +E: USEC_INITIALIZED=15190745 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty7 +N: tty7 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty7 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty7 +E: MAJOR=4 +E: MINOR=7 +E: USEC_INITIALIZED=15223882 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty8 +N: tty8 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty8 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty8 +E: MAJOR=4 +E: MINOR=8 +E: USEC_INITIALIZED=15219083 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/tty9 +N: tty9 +L: 0 +E: DEVPATH=/devices/virtual/tty/tty9 +E: SUBSYSTEM=tty +E: DEVNAME=/dev/tty9 +E: MAJOR=4 +E: MINOR=9 +E: USEC_INITIALIZED=15225162 +E: ID_MM_CANDIDATE=1 + +P: /devices/virtual/tty/ttyprintk +N: ttyprintk +L: 0 +E: DEVPATH=/devices/virtual/tty/ttyprintk +E: SUBSYSTEM=tty +E: DEVNAME=/dev/ttyprintk +E: MAJOR=5 +E: MINOR=3 +E: USEC_INITIALIZED=15217327 +E: ID_MM_CANDIDATE=1 +E: TAGS=:systemd: + +P: /devices/virtual/vc/vcs +N: vcs +L: 0 +E: DEVPATH=/devices/virtual/vc/vcs +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcs +E: MAJOR=7 +E: MINOR=0 + +P: /devices/virtual/vc/vcs1 +N: vcs1 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcs1 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcs1 +E: MAJOR=7 +E: MINOR=1 + +P: /devices/virtual/vc/vcs2 +N: vcs2 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcs2 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcs2 +E: MAJOR=7 +E: MINOR=2 + +P: /devices/virtual/vc/vcs3 +N: vcs3 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcs3 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcs3 +E: MAJOR=7 +E: MINOR=3 + +P: /devices/virtual/vc/vcs4 +N: vcs4 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcs4 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcs4 +E: MAJOR=7 +E: MINOR=4 + +P: /devices/virtual/vc/vcs5 +N: vcs5 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcs5 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcs5 +E: MAJOR=7 +E: MINOR=5 + +P: /devices/virtual/vc/vcs6 +N: vcs6 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcs6 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcs6 +E: MAJOR=7 +E: MINOR=6 + +P: /devices/virtual/vc/vcsa +N: vcsa +L: 0 +E: DEVPATH=/devices/virtual/vc/vcsa +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcsa +E: MAJOR=7 +E: MINOR=128 + +P: /devices/virtual/vc/vcsa1 +N: vcsa1 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcsa1 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcsa1 +E: MAJOR=7 +E: MINOR=129 + +P: /devices/virtual/vc/vcsa2 +N: vcsa2 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcsa2 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcsa2 +E: MAJOR=7 +E: MINOR=130 + +P: /devices/virtual/vc/vcsa3 +N: vcsa3 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcsa3 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcsa3 +E: MAJOR=7 +E: MINOR=131 + +P: /devices/virtual/vc/vcsa4 +N: vcsa4 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcsa4 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcsa4 +E: MAJOR=7 +E: MINOR=132 + +P: /devices/virtual/vc/vcsa5 +N: vcsa5 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcsa5 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcsa5 +E: MAJOR=7 +E: MINOR=133 + +P: /devices/virtual/vc/vcsa6 +N: vcsa6 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcsa6 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcsa6 +E: MAJOR=7 +E: MINOR=134 + +P: /devices/virtual/vc/vcsu +N: vcsu +L: 0 +E: DEVPATH=/devices/virtual/vc/vcsu +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcsu +E: MAJOR=7 +E: MINOR=64 + +P: /devices/virtual/vc/vcsu1 +N: vcsu1 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcsu1 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcsu1 +E: MAJOR=7 +E: MINOR=65 + +P: /devices/virtual/vc/vcsu2 +N: vcsu2 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcsu2 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcsu2 +E: MAJOR=7 +E: MINOR=66 + +P: /devices/virtual/vc/vcsu3 +N: vcsu3 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcsu3 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcsu3 +E: MAJOR=7 +E: MINOR=67 + +P: /devices/virtual/vc/vcsu4 +N: vcsu4 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcsu4 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcsu4 +E: MAJOR=7 +E: MINOR=68 + +P: /devices/virtual/vc/vcsu5 +N: vcsu5 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcsu5 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcsu5 +E: MAJOR=7 +E: MINOR=69 + +P: /devices/virtual/vc/vcsu6 +N: vcsu6 +L: 0 +E: DEVPATH=/devices/virtual/vc/vcsu6 +E: SUBSYSTEM=vc +E: DEVNAME=/dev/vcsu6 +E: MAJOR=7 +E: MINOR=70 + +P: /devices/virtual/vtconsole/vtcon0 +L: 0 +E: DEVPATH=/devices/virtual/vtconsole/vtcon0 +E: SUBSYSTEM=vtconsole + +P: /devices/virtual/vtconsole/vtcon1 +L: 0 +E: DEVPATH=/devices/virtual/vtconsole/vtcon1 +E: SUBSYSTEM=vtconsole + +P: /devices/virtual/workqueue/blkcg_punt_bio +L: 0 +E: DEVPATH=/devices/virtual/workqueue/blkcg_punt_bio +E: SUBSYSTEM=workqueue + +P: /devices/virtual/workqueue/nvme-delete-wq +L: 0 +E: DEVPATH=/devices/virtual/workqueue/nvme-delete-wq +E: SUBSYSTEM=workqueue + +P: /devices/virtual/workqueue/nvme-reset-wq +L: 0 +E: DEVPATH=/devices/virtual/workqueue/nvme-reset-wq +E: SUBSYSTEM=workqueue + +P: /devices/virtual/workqueue/nvme-wq +L: 0 +E: DEVPATH=/devices/virtual/workqueue/nvme-wq +E: SUBSYSTEM=workqueue + +P: /devices/virtual/workqueue/writeback +L: 0 +E: DEVPATH=/devices/virtual/workqueue/writeback +E: SUBSYSTEM=workqueue + +P: /devices/virtual/block/dm-0 +N: dm-0 +L: 0 +E: DEVPATH=/devices/virtual/block/dm-0 +E: SUBSYSTEM=block +E: DEVNAME=/dev/dm-0 +E: DEVTYPE=disk +E: MAJOR=253 +E: MINOR=0 +E: USEC_INITIALIZED=15242519 +E: DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG=1 +E: DM_UDEV_DISABLE_DISK_RULES_FLAG=1 +E: DM_UDEV_DISABLE_OTHER_RULES_FLAG=1 +E: SYSTEMD_READY=0 +E: TAGS=:systemd: + +P: /devices/virtual/block/dm-1 +N: dm-1 +L: 0 +E: DEVPATH=/devices/virtual/block/dm-1 +E: SUBSYSTEM=block +E: DEVNAME=/dev/dm-1 +E: DEVTYPE=disk +E: MAJOR=253 +E: MINOR=1 +E: USEC_INITIALIZED=15247145 +E: DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG=1 +E: DM_UDEV_DISABLE_DISK_RULES_FLAG=1 +E: DM_UDEV_DISABLE_OTHER_RULES_FLAG=1 +E: SYSTEMD_READY=0 +E: TAGS=:systemd: diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/parsers/udevadm.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/parsers/udevadm.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/parsers/udevadm.py 2021-05-27 06:47:04.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/parsers/udevadm.py 2021-07-12 15:29:05.000000000 +0000 @@ -95,6 +95,8 @@ FLASH_RE = re.compile(r"Flash", re.I) FLASH_DISK_RE = re.compile(r"Mass|Storage|Disk", re.I) MD_DEVICE_RE = re.compile(r"MD_DEVICE_\w+_DEV") +ROOT_MOUNTPOINT = re.compile( + r'MOUNTPOINT=.*/(writable|hostfs|ubuntu-seed|ubuntu-boot)') def slugify(_string): @@ -118,7 +120,7 @@ ): return True if ( - re.search('MOUNTPOINT=.*/(writable|hostfs)', line) and + ROOT_MOUNTPOINT.search(line) and line.startswith('KNAME="{}'.format(devname)) ): return True diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/scripts/eddystone_scanner.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/scripts/eddystone_scanner.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/scripts/eddystone_scanner.py 2021-05-27 06:47:04.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/scripts/eddystone_scanner.py 2021-07-12 15:29:05.000000000 +0000 @@ -1,9 +1,10 @@ #!/usr/bin/env python3 # encoding: UTF-8 -# Copyright (c) 2018 Canonical Ltd. +# Copyright (c) 2021 Canonical Ltd. # # Authors: # Sylvain Pineau +# Paul Larson # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,88 +20,82 @@ # along with this program. If not, see . import argparse -import asyncio -import logging -import sys import time +from checkbox_support.vendor.beacontools import ( + BeaconScanner, EddystoneURLFrame) from checkbox_support.interactive_cmd import InteractiveCommand -from checkbox_support.vendor.aioblescan import create_bt_socket -from checkbox_support.vendor.aioblescan import BLEScanRequester -from checkbox_support.vendor.aioblescan import HCI_Cmd_LE_Advertise -from checkbox_support.vendor.aioblescan import HCI_Event -from checkbox_support.vendor.aioblescan.eddystone import EddyStone + + +def init_bluetooth(): + # Power on the bluetooth controller + with InteractiveCommand('bluetoothctl') as btctl: + btctl.writeline('power on') + time.sleep(3) + btctl.writeline('scan on') + time.sleep(3) + btctl.writeline('exit') + btctl.kill() + + +def beacon_scan(hci_device): + TIMEOUT = 10 + + beacon_mac = beacon_rssi = beacon_packet = '' + + def callback(bt_addr, rssi, packet, additional_info): + nonlocal beacon_mac, beacon_rssi, beacon_packet + beacon_mac, beacon_rssi, beacon_packet = bt_addr, rssi, packet + + scanner = BeaconScanner( + callback, + bt_device_id=hci_device, + packet_filter=EddystoneURLFrame + ) + + scanner.start() + start = time.time() + while not beacon_packet and time.time() - start < TIMEOUT: + time.sleep(1) + scanner.stop() + if beacon_packet: + print('Eddystone beacon detected: URL: {} ' + ''.format(beacon_packet.url, beacon_mac, beacon_rssi)) + return 0 + print('No EddyStone URL advertisement detected!') + return 1 def main(): - logger = logging.getLogger(__file__) - logger.setLevel(logging.DEBUG) - h1 = logging.StreamHandler(sys.stdout) - h1.setLevel(logging.DEBUG) - h1.addFilter(lambda record: record.levelno <= logging.INFO) - h2 = logging.StreamHandler() - h2.setLevel(logging.WARNING) - logger.addHandler(h1) - logger.addHandler(h2) + init_bluetooth() + parser = argparse.ArgumentParser( description="Track BLE advertised packets") parser.add_argument("-D", "--device", default='hci0', help="Select the hciX device to use " "(default hci0).") - - @asyncio.coroutine - def timeout(): - yield from asyncio.sleep(10) - - def ble_process(data): - ev = HCI_Event() - ev.decode(data) - advertisement = EddyStone().decode(ev) - if advertisement: - logger.info("EddyStone URL: %s" % advertisement['url']) - for task in asyncio.Task.all_tasks(): - task.cancel() + args = parser.parse_args() try: - opts = parser.parse_args() - except Exception as e: - parser.error("Error: " + str(e)) - return 1 - with InteractiveCommand('bluetoothctl') as btctl: - btctl.writeline('power on') - time.sleep(3) - btctl.writeline('exit') - btctl.kill() - event_loop = asyncio.get_event_loop() - # First create and configure a STREAM socket - try: - mysocket = create_bt_socket(int(opts.device.replace('hci', ''))) - except OSError as e: - logger.error('%s' % e) - return 1 - # Create a connection with the STREAM socket - fac = event_loop._create_connection_transport( - mysocket, BLEScanRequester, None, None) - # Start it - conn, btctrl = event_loop.run_until_complete(fac) - # Attach processing - btctrl.process = ble_process - # Probe - btctrl.send_scan_request() - try: - event_loop.run_until_complete(timeout()) - logger.error('No EddyStone URL advertisement detected!') - return 1 - except asyncio.CancelledError: - return 0 - except KeyboardInterrupt: - return 1 - finally: - btctrl.stop_scan_request() - command = HCI_Cmd_LE_Advertise(enable=False) - btctrl.send_command(command) - conn.close() - event_loop.close() + hci_device = int(args.device.replace('hci', '')) + except ValueError: + print('Bad device argument, defaulting to hci0') + hci_device = 0 + + # Newer bluetooth controllers and bluez versions allow extended commands + # supported by newer versions of beacontools. But with older controllers, + # especially when running on bionic, core18, bluez < 5.51, etc. they + # only work correctly with legacy commands, and need an older version + # of beacontools to work properly. + # Try the newest one first, then the older one if that doesn't work + rc = beacon_scan(hci_device) + if rc: + print('Trying again with older beacontools version...') + global BeaconScanner, EddystoneURLFrame + from checkbox_support.vendor.beacontools_2_0_2 import ( + BeaconScanner, EddystoneURLFrame) + rc = beacon_scan(hci_device) + return rc if __name__ == '__main__': diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/snap_utils/config.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/snap_utils/config.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/snap_utils/config.py 2021-05-27 06:47:04.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/snap_utils/config.py 2021-07-12 15:29:05.000000000 +0000 @@ -9,17 +9,17 @@ import json import os import re -import subprocess +import subprocess as sp import sys -def get_snapctl_config(keys): - """Query snapctl for given keys.""" - if len(keys) == 0: - return dict() - out = subprocess.check_output(['snapctl', 'get', '-d'] + keys).decode( - sys.stdout.encoding) - return json.loads(out) +def get_snapctl_config(): + """Query snapctl for config file variables""" + out = sp.check_output(['snapctl', 'get', 'conf']).decode( + sys.stdout.encoding).strip() + if out: + return json.loads(out) + return {} def get_configuration_set(): @@ -77,21 +77,24 @@ config = configparser.ConfigParser() config.optionxform = str config.read(checkbox_conf_path) - for key in config['environment']: - print('{}={}'.format(key, config['environment'][key])) + if config.has_section('environment'): + for key in config['environment']: + print('{}={}'.format(key, config['environment'][key])) def refresh_configuration(): """ Read config_vars, write the ones missing in snapd and call update configuration in both, snapd and checkbox.conf. + + This is called from the snap configure hook. """ - conf_set = get_configuration_set() - if conf_set: - current = get_snapctl_config(list(conf_set.keys())) - for key in conf_set.keys(): + config_vars = get_configuration_set() + if config_vars: + current = get_snapctl_config() + for key in config_vars.keys(): if key not in current.keys() or not current[key]: - current[key] = conf_set[key] + current[key] = config_vars[key] update_configuration(current) @@ -99,6 +102,8 @@ """ Update snapd configuration and write checkbox.conf file + The is called from the configure snap app. + :param updated_entries: A dict containing the configuration to set. Keys should contain lowercase letters, dashes and number only. @@ -108,7 +113,7 @@ for k, v in updated_entries.items(): if not key_re.match(k): raise ValueError("'%s' is not a valid key" % k) - vars_to_set.append('{}={}'.format(k.replace('_', '-').lower(), v)) - subprocess.run(['snapctl', 'set'] + sorted(vars_to_set)) - write_checkbox_conf( - get_snapctl_config(list(get_configuration_set().keys()))) + vars_to_set.append('conf.{}={}'.format( + k.replace('_', '-').lower(), v)) + sp.run(['snapctl', 'set'] + sorted(vars_to_set)) + write_checkbox_conf(get_snapctl_config()) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/snap_utils/tests/test_config.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/snap_utils/tests/test_config.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/snap_utils/tests/test_config.py 2021-05-27 06:47:04.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/snap_utils/tests/test_config.py 2021-07-12 15:29:05.000000000 +0000 @@ -8,7 +8,7 @@ import sys from textwrap import dedent -from unittest.mock import mock_open, patch +from unittest.mock import call, mock_open, patch from checkbox_support.snap_utils.config import get_configuration_set from checkbox_support.snap_utils.config import get_snapctl_config @@ -17,53 +17,23 @@ class TestSnapctlConfig(unittest.TestCase): - def test_no_keys(self): - self.assertEqual(get_snapctl_config([]), dict()) - def test_one_key(self): - SNAPCTL_OUT = dedent(""" - { - \t"foo": "bar" - } - """).lstrip().encode(sys.stdout.encoding) - with patch('subprocess.check_output', return_value=SNAPCTL_OUT) as p: - expected = {'foo': 'bar'} - self.assertEqual(get_snapctl_config(['foo']), expected) - p.assert_called_with(['snapctl', 'get', '-d', 'foo']) - - def test_not_set_key(self): - with patch('subprocess.check_output', return_value=b'{}\n') as p: - expected = {} - self.assertEqual(get_snapctl_config(['foo']), expected) - p.assert_called_with(['snapctl', 'get', '-d', 'foo']) + @patch('subprocess.check_output') + def test_no_config(self, mock_output): + SNAPCTL_NO_CONFIG = "\n".encode(sys.stdout.encoding) + mock_output.return_value = SNAPCTL_NO_CONFIG + self.assertEqual(get_snapctl_config(), dict()) - def test_two_keys(self): - SNAPCTL_OUT = dedent(""" + @patch('subprocess.check_output') + def test_some_config(self, mock_output): + SNAPCTL_EXISTING_CONFIG = dedent(""" { \t"foo": "bar", - \t"biz": "baz" - } - """).lstrip().encode(sys.stdout.encoding) - with patch('subprocess.check_output', return_value=SNAPCTL_OUT) as p: - expected = {'foo': 'bar', 'biz': 'baz'} - self.assertEqual(get_snapctl_config(['foo', 'biz']), expected) - p.assert_called_with(['snapctl', 'get', '-d', 'foo', 'biz']) - - def test_two_keys_one_missing(self): - SNAPCTL_OUT = dedent(""" - { - \t"foo": "bar" + \t"bar": "baz" } """).lstrip().encode(sys.stdout.encoding) - with patch('subprocess.check_output', return_value=SNAPCTL_OUT) as p: - expected = {'foo': 'bar'} - self.assertEqual(get_snapctl_config(['foo', 'biz']), expected) - p.assert_called_with(['snapctl', 'get', '-d', 'foo', 'biz']) - - def test_two_keys_both_missing(self): - with patch('subprocess.check_output', return_value=b'{}\n') as p: - self.assertEqual(get_snapctl_config(['foo', 'biz']), dict()) - p.assert_called_with(['snapctl', 'get', '-d', 'foo', 'biz']) + mock_output.return_value = SNAPCTL_EXISTING_CONFIG + self.assertEqual(get_snapctl_config(), {'foo': 'bar', 'bar': 'baz'}) class TestConfigSet(unittest.TestCase): @@ -110,6 +80,7 @@ class TestWriteCheckboxConf(unittest.TestCase): + def test_smoke(self): m = mock_open() with patch('builtins.open', m): @@ -154,7 +125,7 @@ self.assertFalse(mock_run.called) @patch('checkbox_support.snap_utils.config.get_configuration_set') - @patch('subprocess.check_output', return_value=b'{}\n') + @patch('subprocess.check_output') @patch('subprocess.run') def test_one_value(self, mock_run, mock_subproc, mock_conf_set): """ FOO=bar in config_vars, @@ -165,14 +136,22 @@ foo=bar """ mock_conf_set.return_value = {'foo': 'bar'} + mock_subproc.side_effect = [b'\n', dedent(""" + { + \t"foo": "bar" + } + """).lstrip().encode(sys.stdout.encoding)] m = mock_open() with patch('builtins.open', m): refresh_configuration() - m().write.called_once_with('[environ]\n') - m().write.called_once_with('FOO = bar\n') - m().write.called_once_with('\n') + m.assert_called_with("$SNAP_DATA/checkbox.conf", "wt") + m.return_value.write.assert_has_calls([ + call('[environment]\n'), + call('FOO = bar\n'), + call('\n') + ]) self.assertTrue(mock_conf_set.called) - mock_run.assert_called_once_with(['snapctl', 'set', 'foo=bar']) + mock_run.assert_called_once_with(['snapctl', 'set', 'conf.foo=bar']) @patch('checkbox_support.snap_utils.config.get_configuration_set') @patch('subprocess.check_output') @@ -186,18 +165,28 @@ "FOO=bar" """ mock_conf_set.return_value = {'foo': 'default'} - mock_subproc.return_value = dedent(""" - { - \t"foo": "bar" - } - """).lstrip().encode(sys.stdout.encoding) + mock_subproc.side_effect = [ + dedent(""" + { + \t"foo": "bar" + } + """).lstrip().encode(sys.stdout.encoding), + dedent(""" + { + \t"foo": "bar" + } + """).lstrip().encode(sys.stdout.encoding) + ] m = mock_open() with patch('builtins.open', m): refresh_configuration() - m().write.called_once_with('[environ]\n') - m().write.called_once_with('FOO = bar\n') - m().write.called_once_with('\n') - mock_run.assert_called_once_with(['snapctl', 'set', 'foo=bar']) + m.assert_called_with("$SNAP_DATA/checkbox.conf", "wt") + m.return_value.write.assert_has_calls([ + call('[environment]\n'), + call('FOO = bar\n'), + call('\n') + ]) + mock_run.assert_called_once_with(['snapctl', 'set', 'conf.foo=bar']) @patch('checkbox_support.snap_utils.config.get_configuration_set') @patch('subprocess.check_output') @@ -211,17 +200,28 @@ "FOO=old and BIZ=baz" """ mock_conf_set.return_value = {'foo': 'bar', 'biz': 'baz'} - mock_subproc.return_value = dedent(""" - { - \t"foo": "old" - } - """).lstrip().encode(sys.stdout.encoding) + mock_subproc.side_effect = [ + dedent(""" + { + \t"foo": "old" + } + """).lstrip().encode(sys.stdout.encoding), + dedent(""" + { + \t"biz": "baz", + \t"foo": "old" + } + """).lstrip().encode(sys.stdout.encoding) + ] m = mock_open() with patch('builtins.open', m): refresh_configuration() - m().write.called_once_with('[environ]\n') - m().write.called_once_with('FOO = old\n') - m().write.called_once_with('BIZ = baz\n') - m().write.called_once_with('\n') + m.assert_called_with("$SNAP_DATA/checkbox.conf", "wt") + m.return_value.write.assert_has_calls([ + call('[environment]\n'), + call('BIZ = baz\n'), + call('FOO = old\n'), + call('\n') + ]) mock_run.assert_called_once_with( - ['snapctl', 'set', 'biz=baz', 'foo=old']) + ['snapctl', 'set', 'conf.biz=baz', 'conf.foo=old']) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/ahocorapy/keywordtree.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/ahocorapy/keywordtree.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/ahocorapy/keywordtree.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/ahocorapy/keywordtree.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,225 @@ +''' +Ahocorasick implementation entirely written in python. +Supports unicode. + +Quite optimized, the code may not be as beautiful as you like, +since inlining and so on was necessary + +Created on Jan 5, 2016 + +@author: Frederik Petersen (fp@abusix.com) +''' + +from builtins import object + + +class State(object): + __slots__ = ['identifier', 'symbol', 'success', 'transitions', 'parent', + 'matched_keyword', 'longest_strict_suffix'] + + def __init__(self, identifier, symbol=None, parent=None, success=False): + self.symbol = symbol + self.identifier = identifier + self.transitions = {} + self.parent = parent + self.success = success + self.matched_keyword = None + self.longest_strict_suffix = None + + def __str__(self): + transitions_as_string = ','.join( + ['{0} -> {1}'.format(key, value.identifier) for key, value in self.transitions.items()]) + return "State {0}. Transitions: {1}".format(self.identifier, transitions_as_string) + + +class KeywordTree(object): + + def __init__(self, case_insensitive=False): + ''' + @param case_insensitive: If true, case will be ignored when searching. + Setting this to true will have a positive + impact on performance. + Defaults to false. + @param over_allocation: Determines how big initial transition arrays + are and how much space is allocated in addition + to what is essential when array needs to be + resized. Default value 2 seemed to be sweet + spot for memory as well as cpu. + ''' + self._zero_state = State(0) + self._counter = 1 + self._finalized = False + self._case_insensitive = case_insensitive + + def add(self, keyword): + ''' + Add a keyword to the tree. + Can only be used before finalize() has been called. + Keyword should be str or unicode. + ''' + if self._finalized: + raise ValueError('KeywordTree has been finalized.' + + ' No more keyword additions allowed') + original_keyword = keyword + if self._case_insensitive: + keyword = keyword.lower() + if len(keyword) <= 0: + return + current_state = self._zero_state + for char in keyword: + try: + current_state = current_state.transitions[char] + except KeyError: + next_state = State(self._counter, parent=current_state, + symbol=char) + self._counter += 1 + current_state.transitions[char] = next_state + current_state = next_state + current_state.success = True + current_state.matched_keyword = original_keyword + + def search(self, text): + ''' + Alias for the search_one method + ''' + return self.search_one(text) + + def search_one(self, text): + ''' + Search a text for any occurence of any added keyword. + Returns when one keyword has been found. + Can only be called after finalized() has been called. + O(n) with n = len(text) + @return: 2-Tuple with keyword and startindex in text. + Or None if no keyword was found in the text. + ''' + result_gen = self.search_all(text) + try: + return next(result_gen) + except StopIteration: + return None + + def search_all(self, text): + ''' + Search a text for all occurences of the added keywords. + Can only be called after finalized() has been called. + O(n) with n = len(text) + @return: Generator used to iterate over the results. + Or None if no keyword was found in the text. + ''' + if not self._finalized: + raise ValueError('KeywordTree has not been finalized.' + + ' No search allowed. Call finalize() first.') + if self._case_insensitive: + text = text.lower() + zero_state = self._zero_state + current_state = zero_state + for idx, symbol in enumerate(text): + current_state = current_state.transitions.get( + symbol, zero_state.transitions.get(symbol, zero_state)) + state = current_state + while state is not zero_state: + if state.success: + keyword = state.matched_keyword + yield (keyword, idx + 1 - len(keyword)) + state = state.longest_strict_suffix + + def finalize(self): + ''' + Needs to be called after all keywords have been added and + before any searching is performed. + ''' + if self._finalized: + raise ValueError('KeywordTree has already been finalized.') + self._zero_state.longest_strict_suffix = self._zero_state + self.search_lss_for_children(self._zero_state) + self._finalized = True + + def search_lss_for_children(self, zero_state): + processed = set() + to_process = [zero_state] + while to_process: + state = to_process.pop() + processed.add(state.identifier) + for child in state.transitions.values(): + if child.identifier not in processed: + self.search_lss(child) + to_process.append(child) + + def search_lss(self, state): + zero_state = self._zero_state + parent = state.parent + traversed = parent.longest_strict_suffix + while True: + if state.symbol in traversed.transitions and\ + traversed.transitions[state.symbol] is not state: + state.longest_strict_suffix =\ + traversed.transitions[state.symbol] + break + elif traversed is zero_state: + state.longest_strict_suffix = zero_state + break + else: + traversed = traversed.longest_strict_suffix + suffix = state.longest_strict_suffix + if suffix is zero_state: + return + if suffix.longest_strict_suffix is None: + self.search_lss(suffix) + for symbol, next_state in suffix.transitions.items(): + if symbol not in state.transitions: + state.transitions[symbol] = next_state + + def __str__(self): + return "ahocorapy KeywordTree" + + def __getstate__(self): + state_list = [None] * self._counter + todo_list = [self._zero_state] + while todo_list: + state = todo_list.pop() + transitions = {key: value.identifier for key, + value in state.transitions.items()} + state_list[state.identifier] = { + 'symbol': state.symbol, + 'success': state.success, + 'parent': state.parent.identifier if state.parent is not None else None, + 'matched_keyword': state.matched_keyword, + 'longest_strict_suffix': state.longest_strict_suffix.identifier if state.longest_strict_suffix is not None else None, + 'transitions': transitions + } + for child in state.transitions.values(): + if len(state_list) <= child.identifier or not state_list[child.identifier]: + todo_list.append(child) + + return { + 'case_insensitive': self._case_insensitive, + 'finalized': self._finalized, + 'counter': self._counter, + 'states': state_list + } + + def __setstate__(self, state): + self._case_insensitive = state['case_insensitive'] + self._counter = state['counter'] + self._finalized = state['finalized'] + states = [None] * len(state['states']) + for idx, serialized_state in enumerate(state['states']): + deserialized_state = State(idx, serialized_state['symbol']) + deserialized_state.success = serialized_state['success'] + deserialized_state.matched_keyword = serialized_state['matched_keyword'] + states[idx] = deserialized_state + for idx, serialized_state in enumerate(state['states']): + deserialized_state = states[idx] + if serialized_state['longest_strict_suffix'] is not None: + deserialized_state.longest_strict_suffix = states[ + serialized_state['longest_strict_suffix']] + else: + deserialized_state.longest_strict_suffix = None + if serialized_state['parent'] is not None: + deserialized_state.parent = states[serialized_state['parent']] + else: + deserialized_state.parent = None + deserialized_state.transitions = { + key: states[value] for key, value in serialized_state['transitions'].items()} + self._zero_state = states[0] diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/ahocorapy/LICENSE checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/ahocorapy/LICENSE --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/ahocorapy/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/ahocorapy/LICENSE 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Abusix, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/aioblescan.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/aioblescan.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/aioblescan.py 2021-05-27 06:47:04.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/aioblescan.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,1356 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding:utf-8 -*- -# -# This application is simply a python only Bluetooth LE Scan command with -# decoding of advertised packets -# -# Copyright (c) 2017 François Wautier -# -# Note large part of this code was taken from scapy and other opensource software -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -# of the Software, and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all copies -# or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -# IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE - -import socket, asyncio -from struct import pack, unpack, calcsize - - -#A little bit of HCI -HCI_COMMAND = 0x01 -HCI_ACL_DATA = 0x02 -HCI_SCO_DATA = 0x03 -HCI_EVENT = 0x04 -HCI_VENDOR = 0x05 - -PRINT_INDENT=" " - -CMD_SCAN_REQUEST = 0x200c #mixing the OGF in with that HCI shift - -# -EDDY_UUID=b"\xfe\xaa" #Google UUID - -#Generated from https://www.uuidgenerator.net/ 906ed6ab-6785-4eab-9847-bf9889c098ae alternative is 668997f8-4acd-48ea-b35b-749e54215860 -MY_UUID = b'\x90\x6e\xd6\xab\x67\x85\x4e\xab\x98\x47\xbf\x98\x89\xc0\x98\xae' -#MY_UUID = b'\x66\x89\x97\xf8\x4a\xcd\x48\xea\xb3\x5b\x74\x9e\x54\x21\x58\x60' -# -# Let's define some useful types -# -class MACAddr: - """Class representing a MAC address. - - :param name: The name of the instance - :type name: str - :param mac: the mac address. - :type mac: str - :returns: MACAddr instance. - :rtype: MACAddr - - """ - def __init__(self,name,mac="00:00:00:00:00:00"): - self.name = name - self.val=mac.lower() - - def encode (self): - """Encode the MAC address to a byte array. - - :returns: The encoded version of the MAC address - :rtype: bytes - """ - return int(self.val.replace(":",""),16).to_bytes(6,"little") - - def decode(self,data): - """Decode the MAC address from a byte array. - - This will take the first 6 bytes from data and transform them into a MAC address - string representation. This will be assigned to the attribute "val". It then returns - the data stream minus the bytes consumed - - :param data: The data stream containing the value to decode at its head - :type data: bytes - :returns: The datastream minus the bytes consumed - :rtype: bytes - """ - self.val=':'.join("%02x" % x for x in reversed(data[:6])) - return data[6:] - - def __len__(self): - return 6 - - def show(self,depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - print("{}{}".format(PRINT_INDENT*(depth+1),self.val)) - -class Bool: - """Class representing a boolean value. - - :param name: The name of the instance - :type name: str - :param val: the boolean value. - :type mac: bool - :returns: Bool instance. - :rtype: Bool - - """ - def __init__(self,name,val=True): - self.name = name - self.val = val - - def encode (self): - return b'\x01' if self.val else b'\x00' - - def decode(self,data): - self.val = (data[:1] == b"\x01") - return data[1:] - - def __len__(self): - return 1 - - def show(self,depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - print("{}{}".format(PRINT_INDENT*(depth+1),self.val)) - -class Byte: - """Class representing a single byte value. - - :param name: The name of the instance - :type name: str - :param val: the single byte value. - :type val: byte - :returns: Byte instance. - :rtype: Byte - - """ - def __init__(self,name,val=0): - self.name=name - self.val=val - - def encode (self): - val=pack("B",self.val) - return val - - def decode(self,data): - self.val= unpack(">B",data[:1])[0] - return data[1:] - - @property - def strval(self): - if self.val in self.loval: - return self.loval[self.val] - else: - return str(self.val) - - def __len__(self): - return 1 - - def show(self,depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - if self.val in self.loval: - print("{}{}".format(PRINT_INDENT*(depth+1),self.loval[self.val])) - else: - print("{}Undef".format(PRINT_INDENT*(depth+1))) - -class BitFieldByte: - """Class representing a single byte value as a bit field. - - :param name: The name of the instance - :type name: str - :param val: the single byte value. - :type val: byte - :param loval: the list defining the name of the property represented by each bit. - :type loval: list - :returns: BitFieldByte instance. - :rtype: BitFieldByte - - """ - def __init__(self,name,val=0,loval=["Undef"]*8): - self.name=name - self._val=val - self.loval=loval - - def encode (self): - val=pack(">B",self._val) - return val - - def decode(self,data): - self._val= unpack(">B",data[:1])[0] - return data[1:] - - def __len__(self): - return 1 - - @property - def val(self): - resu={} - for x in self.loval: - if x not in ["Undef","Reserv"]: - resu[x]=(self._val & mybit)>0 - return resu - - def show(self,depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - mybit=0x80 - for x in self.loval: - if x not in ["Undef","Reserv"]: - print("{}{}: {}".format(PRINT_INDENT*(depth+1),x, ((self._val & mybit) and "True") or False)) - mybit = mybit >>1 - -class IntByte: - """Class representing a single byte as a signed integer. - - :param name: The name of the instance - :type name: str - :param val: the integer value. - :type val: int - :returns: IntByte instance. - :rtype: IntByte - - """ - def __init__(self,name,val=0): - self.name=name - self.val=val - - def encode (self): - val=pack(">b",self.val) - return val - - def decode(self,data): - self.val= unpack(">b",data[:1])[0] - return data[1:] - - def __len__(self): - return 1 - - def show(self,depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - print("{}{}".format(PRINT_INDENT*(depth+1),self.val)) - -class UIntByte: - """Class representing a single byte as an unsigned integer. - - :param name: The name of the instance - :type name: str - :param val: the integer value. - :type val: int - :returns: UIntByte instance. - :rtype: UIntByte - - """ - def __init__(self,name,val=0): - self.name=name - self.val=val - - def encode (self): - val=pack(">B",self.val) - return val - - def decode(self,data): - self.val= unpack(">B",data[:1])[0] - return data[1:] - - def __len__(self): - return 1 - - def show(self,depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - print("{}{}".format(PRINT_INDENT*(depth+1),self.val)) - -class ShortInt: - """Class representing 2 bytes as a signed integer. - - :param name: The name of the instance - :type name: str - :param val: the integer value. - :type val: int - :param endian: Endianess of the bytes. "big" or no "big" (i.e. "little") - :type endian: str - :returns: ShortInt instance. - :rtype: ShortInt - - """ - def __init__(self,name,val=0,endian="big"): - self.name=name - self.val=val - self.endian = endian - - def encode (self): - if self.endian == "big": - val=pack(">h",self.val) - else: - val=pack("h",data[:2])[0] - else: - self.val= unpack("H",self.val) - else: - val=pack("H",data[:2])[0] - else: - self.val= unpack("l",self.val) - else: - val=pack("l",data[:4])[0] - else: - self.val= unpack("L",self.val) - else: - val=pack("L",data[:4])[0] - else: - self.val= unpack(">10 - self.ocf = int(val - (self.ogf<<10)).to_bytes(1,"big") - self.ogf = int(self.ogf).to_bytes(1,"big") - return data[len(self):] - - def __len__(self): - return calcsize("%ds"%len(self.val),self.val) - return val - - def decode(self,data): - self.val=unpack(">%ds"%len(data),data)[0] - return b"" - - def __len__(self): - return len(self.val) - - def show(self,depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - print("{}{}".format(PRINT_INDENT*(depth+1),":".join(map(lambda b: format(b, "02x"), self.val)))) - -class String: - """Class representing a string. - - :param name: The name of the instance - :type name: str - :returns: String instance. - :rtype: String - - """ - def __init__(self,name): - self.name=name - self.val="" - - def encode(self): - if isinstance(self.val,str): - self.val = self.val.encode() - val=pack(">%ds"%len(self.val),self.val) - return val - - def decode(self,data): - self.val=data - return b"" - - def __len__(self): - return len(self.val) - - def show(self,depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - print("{}{}".format(PRINT_INDENT*(depth+1),self.val)) - - -class NBytes: - """Class representing a byte string. - - :param name: The name of the instance - :type name: str - :param length: The length - :type length: int - :returns: NBytes instance. - :rtype: NBytes - - """ - def __init__(self,name,length=2): - self.name=name - self.length=length - self.val=b"" - - def encode(self): - val=pack(">%ds"%len(self.length),self.val) - return val - - def decode(self,data): - self.val=unpack(">%ds"%self.length,data[:self.length])[0][::-1] - return data[self.length:] - - def __len__(self): - return self.length - - def show(self,depth=0): - if self.name: - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - print("{}{}".format(PRINT_INDENT*(depth+1),":".join(map(lambda b: format(b, "02x"), self.val)))) - - def __eq__(self,b): - return self.val==b - -class NBytes_List: - """Class representing a list of bytes string. - - :param name: The name of the instance - :type name: str - :param bytes: Length of the bytes strings (2, 4 or 16) - :type bytes: int - :returns: NBytes_List instance. - :rtype: NBytes_List - - """ - def __init__(self,name,bytes=2): - #Bytes should be one of 2, 4 or 16 - self.name=name - self.length=bytes - self.lonbytes = [] - - def decode(self,data): - while data: - mynbyte=NBytes("",self.length) - data=mynbyte.decode(data) - self.lonbytes.append(mynbyte) - return data - - def show(self,depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - for x in self.lonbytes: - x.show(depth+1) - - def __len__(self): - return len(self.lonbytes)+self.length - - def __contains__(self,b): - for x in self.lonbytes: - if b == x: - return True - - return False - -class Float88: - """Class representing a 8.8 fixed point quantity. - - :param name: The name of the instance - :type name: str - :returns: Float88 instance. - :rtype: Float88 - - """ - def __init__(self,name): - self.name=name - self.val=0.0 - - def encode (self): - val=pack(">h",int(self.val*256)) - return val - - def decode(self,data): - self.val= unpack(">h",data)[0]/256.0 - return data[2:] - def __len__(self): - return 2 - - def show(self,depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - print("{}{}".format(PRINT_INDENT*(depth+1),self.val)) - - - - -class EmptyPayload: - def __init__(self): - pass - - def encode(self): - return b"" - - def decode(self,data): - return data - - def __len__(self): - return 0 - - def show(self,depth=0): - return - -# -# Bluetooth starts here -# - -class Packet: - """Class representing a generic HCI packet. - - :param header: The packet header. - :type header: bytes - :returns: Packet instance. - :rtype: Packet - - """ - """A generic packet that will be build fromparts""" - def __init__(self, header="\x00", fmt=">B"): - self.header = header - self.fmt = fmt - self.payload=[] - self.raw_data=None - - def encode (self) : - return pack(self.fmt, self.header) - - def decode (self, data): - try: - if unpack(self.fmt,data[:calcsize(self.fmt)])[0] == self.header: - self.raw_data=data - return data[calcsize(self.fmt):] - except: - pass - return None - - def retrieve(self,aclass): - """Look for a specifc class/name in the packet""" - resu=[] - for x in self.payload: - try: - if isinstance(aclass,str): - if x.name == aclass: - resu.append(x) - else: - if isinstance(x,aclass): - resu.append(x) - - resu+=x.retrieve(aclass) - except: - pass - return resu -# -# Commands -# - -class HCI_Command(Packet): - """Class representing a command HCI packet. - - :param ogf: the Op-code Group (6 bits). - :type ogf: bytes - :param ocf: the Op-code Command (10 bits). - :type ocf: bytes - :returns: HCI_Command instance. - :rtype: HCI_Command - - """ - - def __init__(self,ogf,ocf): - super().__init__(HCI_COMMAND) - self.cmd = OgfOcf("command",ogf,ocf) - self.payload = [] - - def encode(self): - pld=b"" - for x in self.payload: - pld+=x.encode() - plen=len(pld) - pld=b"".join([super().encode(),self.cmd.encode(),pack(">B",plen),pld]) - return pld - - def show(self,depth=0): - self.cmd.show(depth) - for x in self.payload: - x.show(depth+1) - -class HCI_Cmd_LE_Scan_Enable(HCI_Command): - """Class representing a command HCI command to enable/disable BLE scanning. - - :param enable: enable/disable scanning. - :type enable: bool - :param filter_dups: filter duplicates. - :type filter_dups: bool - :returns: HCI_Cmd_LE_Scan_Enable instance. - :rtype: HCI_Cmd_LE_Scan_Enable - - """ - - def __init__(self,enable=True,filter_dups=False): - super(self.__class__, self).__init__(b"\x08",b"\x0c") - self.payload.append(Bool("enable",enable)) - self.payload.append(Bool("filter",filter_dups)) - -class HCI_Cmd_LE_Set_Scan_Params(HCI_Command): - """Class representing an HCI command to set the scanning parameters. - - This will set a number of parameters related to the scanning functions. For the - interval and window, it will always silently enforce the Specs that says it should be >= 2.5 ms - and <= 10.24s. It will also silently enforce window <= interval - - :param scan_type: Type of scanning. 0 => Passive (default) - 1 => Active - :type scan_type: int - :param interval: Time in ms between the start of a scan and the next scan start. Default 10 - :type interval: int/float - :param window: maximum advertising interval in ms. Default 10 - :type window: int.float - :param oaddr_type: Type of own address Value 0 => public (default) - 1 => Random - 2 => Private with public fallback - 3 => Private with random fallback - :type oaddr_type: int - :param filter: How white list filter is applied. 0 => No filter (Default) - 1 => sender must be in white list - 2 => Similar to 0. Some directed advertising may be received. - 3 => Similar to 1. Some directed advertising may be received. - :type filter: int - :returns: HCI_Cmd_LE_Scan_Params instance. - :rtype: HCI_Cmd_LE_Scan_Params - - """ - - def __init__(self,scan_type=0x1,interval=10, window=750, oaddr_type=0,filter=0): - - super(self.__class__, self).__init__(b"\x08",b"\x0b") - self.payload.append(EnumByte("scan type",scan_type, - {0: "Passive", - 1: "Active"})) - self.payload.append(UShortInt("Interval",int(round(min(10240,max(2.5,interval))/0.625)),endian="little")) - self.payload.append(UShortInt("Window",int(round(min(10240,max(2.5,min(interval,window)))/0.625)),endian="little")) - self.payload.append(EnumByte("own addresss type",oaddr_type, - {0: "Public", - 1: "Random", - 2: "Private IRK or Public", - 3: "Private IRK or Random"})) - self.payload.append(EnumByte("filter policy",filter, - {0: "None", - 1: "Sender In White List", - 2: "Almost None", - 3: "SIWL and some"})) - - -class HCI_Cmd_LE_Advertise(HCI_Command): - """Class representing a command HCI command to enable/disable BLE advertising. - - :param enable: enable/disable advertising. - :type enable: bool - :returns: HCI_Cmd_LE_Scan_Enable instance. - :rtype: HCI_Cmd_LE_Scan_Enable - - """ - - def __init__(self,enable=True): - super(self.__class__, self).__init__(b"\x08",b"\x0a") - self.payload.append(Bool("enable",enable)) - -class HCI_Cmd_LE_Set_Advertised_Msg(HCI_Command): - """Class representing an HCI command to set the advertised content. - - :param enable: enable/disable advertising. - :type enable: bool - :returns: HCI_Cmd_LE_Scan_Enable instance. - :rtype: HCI_Cmd_LE_Scan_Enable - - """ - - def __init__(self,msg=EmptyPayload()): - super(self.__class__, self).__init__(b"\x08",b"\x08") - self.payload.append(msg) - -class HCI_Cmd_LE_Set_Advertised_Params(HCI_Command): - """Class representing an HCI command to set the advertised parameters. - - This will set a number of parameters relted to the advertising functions. For the - min and max intervals, it will always silently enforce the Specs that says it should be >= 20ms - and <= 10.24s. It will also silently enforce interval_max >= interval_min - - :param interval_min: minimum advertising interval in ms. Default 500 - :type interval_min: int/float - :param interval_max: maximum advertising interval in ms. Default 750 - :type interval_max: int/float - :param adv_type: Type of advertising. Value 0 +> Connectable, Scannable advertising - 1 => Connectable directed advertising (High duty cycle) - 2 => Scannable Undirected advertising - 3 => Non connectable undirected advertising (default) - :type adv_type: int - :param oaddr_type: Type of own address Value 0 => public (default) - 1 => Random - 2 => Private with public fallback - 3 => Private with random fallback - :type oaddr_type: int - :param paddr_type: Type of peer address Value 0 => public (default) - 1 => Random - :type paddr_type: int - :param peer_addr: Peer MAC address Default 00:00:00:00:00:00 - :type peer_addr: str - :param cmap: Channel map. A bit field dfined as "Channel 37","Channel 38","Channel 39","RFU","RFU","RFU","RFU","RFU" - Default value is 0x7. The value 0x0 is RFU. - :type cmap: int - :param filter: How white list filter is applied. 0 => No filter (Default) - 1 => scan are filtered - 2 => Connection are filtered - 3 => scan and connection are filtered - :type filter: int - :returns: HCI_Cmd_LE_Scan_Params instance. - :rtype: HCI_Cmd_LE_Scan_Params - - """ - - def __init__(self,interval_min=500, interval_max=750, - adv_type=0x3, oaddr_type=0, paddr_type=0, - peer_addr="00:00:00:00:00:00", cmap=0x7, filter=0): - - super(self.__class__, self).__init__(b"\x08",b"\x06") - self.payload.append(UShortInt("Adv minimum",int(round(min(10240,max(20,interval_min))/0.625)),endian="little")) - self.payload.append(UShortInt("Adv maximum",int(round(min(10240,max(20,max(interval_min,interval_max)))/0.625)),endian="little")) - self.payload.append(EnumByte("adv type",adv_type, - {0: "ADV_IND", - 1: "ADV_DIRECT_IND high", - 2: "ADV_SCAN_IND", - 3: "ADV_NONCONN_IND", - 4: "ADV_DIRECT_IND low"})) - self.payload.append(EnumByte("own addresss type",paddr_type, - {0: "Public", - 1: "Random", - 2: "Private IRK or Public", - 3: "Private IRK or Random"})) - self.payload.append(EnumByte("peer addresss type",oaddr_type, - {0: "Public", - 1: "Random"})) - self.payload.append(MACAddr("peer",mac=peer_addr)) - self.payload.append(BitFieldByte("Channels",cmap,["Channel 37","Channel 38","Channel 39","RFU","RFU","RFU","RFU", "RFU"])) - - self.payload.append(EnumByte("filter policy",filter, - {0: "None", - 1: "Scan", - 2: "Connection", - 3: "Scan and Connection"})) - -class HCI_Cmd_Reset(HCI_Command): - """Class representing an HCI command to reset the adapater. - - - :returns: HCI_Cmd_Reset instance. - :rtype: HCI_Cmd_Reset - - """ - - def __init__(self): - super(self.__class__, self).__init__(b"\x03",b"\x03") - - -#### -# HCI EVents -#### - -class HCI_Event(Packet): - - def __init__(self,code=0,payload=[]): - super().__init__(HCI_EVENT) - self.payload.append(Byte("code")) - self.payload.append(UIntByte("length")) - - def decode(self,data): - data=super().decode(data) - if data is None: - return None - - for x in self.payload: - x.decode(data[:len(x)]) - data=data[len(x):] - code=self.payload[0] - length=self.payload[1].val - if code.val==b"\x0e": - ev = HCI_CC_Event() - data=ev.decode(data) - self.payload.append(ev) - elif code.val==b"\x3e": - ev = HCI_LE_Meta_Event() - data=ev.decode(data) - self.payload.append(ev) - else: - ev=Itself("Payload") - data=ev.decode(data) - self.payload.append(ev) - return data - - def show(self,depth=0): - print("{}HCI Event:".format(PRINT_INDENT*depth)) - for x in self.payload: - x.show(depth+1) - - -class HCI_CC_Event(Packet): - """Command Complete event""" - def __init__(self): - self.name="Command Completed" - self.payload=[UIntByte("allow pkt"),OgfOcf("cmd"),Itself("resp code")] - - - def decode(self,data): - for x in self.payload: - data=x.decode(data) - return data - - def show(self,depth=0): - for x in self.payload: - x.show(depth+1) - -class HCI_LE_Meta_Event(Packet): - def __init__(self): - self.name="LE Meta" - self.payload=[Byte("code")] - - def decode(self,data): - for x in self.payload: - data=x.decode(data) - code=self.payload[0] - if code.val==b"\x02": - ev=RepeatedField("Reports", HCI_LEM_Adv_Report) - data=ev.decode(data) - self.payload.append(ev) - elif code.val==b"\x0d": - ev=RepeatedField("Ext Adv Report", HCI_LEM_Ext_Adv_Report) - data=ev.decode(data) - self.payload.append(ev) - else: - ev=Itself("Payload") - data=ev.decode(data) - self.payload.append(ev) - return data - - def show(self,depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - for x in self.payload: - x.show(depth+1) - -class ManufacturerSpecificData(Packet): - def __init__(self, name="Manufacturer Specific Data"): - self.name = name - self.payload = [UShortInt("Manufacturer ID", endian="little"), Itself("Payload")] - - def decode(self, data): - # Warning: Will consume all the data you give it! - for p in self.payload: - data = p.decode(data) - return data - - def show(self, depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - for x in self.payload: - x.show(depth+1) - - -class RepeatedField(Packet): - def __init__(self, name, subfield_cls, length_field_cls=UIntByte): - self.name = name - self.subfield_cls = subfield_cls - self.length_field = length_field_cls("count of " + name) - self.payload = [] - - def decode(self, data): - self.payload = [] - data = self.length_field.decode(data) - for x in range(self.length_field.val): - field = self.subfield_cls() - data = field.decode(data) - self.payload.append(field) - - return data - - def show(self, depth=0): - print("{}{}: {}".format(PRINT_INDENT*depth, self.name, self.length_field.val)) - for field in self.payload: - field.show(depth+1) - - -class HCI_LEM_Adv_Report(Packet): - def __init__(self): - self.name="Adv Report" - self.payload=[EnumByte("ev type",0,{0:"generic adv", 3:"no connection adv", 4:"scan rsp"}), - EnumByte("addr type",0,{0:"public", 1:"random"}), - MACAddr("peer"),UIntByte("length")] - - - def decode(self,data): - - for x in self.payload: - data=x.decode(data) - #Now we have a sequence of len, type data with possibly a RSSI byte at the end - datalength = self.payload[-1].val - - while datalength > 0: - ad=AD_Structure() - data=ad.decode(data) - self.payload.append(ad) - - datalength -= len(ad) - - if data: - myinfo=IntByte("rssi") - data=myinfo.decode(data) - self.payload.append(myinfo) - return data - - def show(self,depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - for x in self.payload: - x.show(depth+1) - - -class HCI_LEM_Ext_Adv_Report(Packet): - def __init__(self): - self.name="Ext Adv Report" - self.payload=[BitFieldByte("ev type",0,["Connectable", "Scannable", "Directed", "Scan Response", "Legacy", "Incomplete/more", "Incomplete/truncated", "RFU"]), - UIntByte("unused"), - EnumByte("addr type",0,{0:"public device", 1:"random device", 2:"public identity", 3:"random identity", 0xFF:"anonymous"}), - MACAddr("peer"), - EnumByte("primary phy",1,{1:"LE 1M", 3:"LE Coded"}), - EnumByte("secondary phy",0,{0:"N/A", 1:"LE 1M", 2:"LE 2M", 3:"LE Coded"}), - EnumByte("adv sid",255,{0:"0x00", 1:"0x01", 2:"0x02", 3:"0x03", 4:"0x04", 5:"0x05", 6:"0x06", 7:"0x07", 8:"0x08", 9:"0x09", 10:"0x0A", 11:"0x0B", 12:"0x0C", 13:"0x0D", 14:"0x0E", 15:"0x0F", 0xFF:"N/A"}), - IntByte("tx power"), - IntByte("rssi"), - UShortInt("adv interval", endian="little"), - EnumByte("direct addr type",0,{0:"public device", 1:"random device", 2:"public identity", 3:"random identity", 0xFE:"random device"}), - MACAddr("direct addr"), - UIntByte("data len")] - - - def decode(self,data): - - for x in self.payload: - data=x.decode(data) - - datalength = self.payload[-1].val - while datalength > 0: - ad=AD_Structure() - data=ad.decode(data) - self.payload.append(ad) - - datalength -= len(ad) - - def show(self,depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - for x in self.payload: - x.show(depth+1) - -class EIR_Hdr(Packet): - def __init__(self): - self.type= EnumByte("type", 0, { - 0x01: "flags", - 0x02: "incomplete_list_16_bit_svc_uuids", - 0x03: "complete_list_16_bit_svc_uuids", - 0x04: "incomplete_list_32_bit_svc_uuids", - 0x05: "complete_list_32_bit_svc_uuids", - 0x06: "incomplete_list_128_bit_svc_uuids", - 0x07: "complete_list_128_bit_svc_uuids", - 0x08: "shortened_local_name", - 0x09: "complete_local_name", - 0x0a: "tx_power_level", - 0x0d: "class_of_device", - 0x0e: "simple_pairing_hash", - 0x0f: "simple_pairing_rand", - 0x10: "sec_mgr_tk", - 0x11: "sec_mgr_oob_flags", - 0x12: "slave_conn_intvl_range", - 0x17: "pub_target_addr", - 0x18: "rand_target_addr", - 0x19: "appearance", - 0x1a: "adv_intvl", - 0x1b: "le_addr", - 0x1c: "le_role", - 0x14: "list_16_bit_svc_sollication_uuids", - 0x1f: "list_32_bit_svc_sollication_uuids", - 0x15: "list_128_bit_svc_sollication_uuids", - 0x16: "svc_data_16_bit_uuid", - 0x20: "svc_data_32_bit_uuid", - 0x21: "svc_data_128_bit_uuid", - 0x22: "sec_conn_confirm", - 0x23: "sec_conn_rand", - 0x24: "uri", - 0xff: "mfg_specific_data", - }) - - def decode(self,data): - return self.type.decode(data) - - def show(self,depth=0): - return self.type.show(depth) - - @property - def val(self): - return self.type.val - - @property - def strval(self): - return self.type.strval - - def __len__(self): - return len(self.type) - -class Adv_Data(Packet): - def __init__(self,name,length): - self.name=name - self.length=length - self.payload=[] - - def decode(self,data): - myinfo=NBytes("Service Data uuid",self.length) - data=myinfo.decode(data) - self.payload.append(myinfo) - if data: - myinfo=Itself("Adv Payload") - data=myinfo.decode(data) - self.payload.append(myinfo) - return data - - def show(self,depth=0): - print("{}{}:".format(PRINT_INDENT*depth,self.name)) - for x in self.payload: - x.show(depth+1) - - def __len__(self): - resu=0 - for x in self.payload: - resu+=len(x) - return resu - -class AD_Structure(Packet): - def __init__(self): - self.name="" - self.length=0 - self.payload=[] - - def __len__(self): - return self.length - - def decode(self,data): - length=UIntByte("sublen") - data=length.decode(data) - self.length=len(length)+length.val - self.payload=[] - if length.val == 0: - return data - - type=EIR_Hdr() - data=type.decode(data) - - val = None - if type.val == 0x01: - val=BitFieldByte("flags",0,["Undef","Undef","Simul LE - BR/EDR (Host)","Simul LE - BR/EDR (Control.)","BR/EDR Not Supported", - "LE General Disc.","LE Limited Disc."]) - elif type.val == 0x02: - val=NBytes_List("Incomplete uuids",2) - elif type.val == 0x03: - val=NBytes_List("Complete uuids",2) - elif type.val == 0x04: - val=NBytes_List("Incomplete uuids",4) - elif type.val == 0x05: - val=NBytes_List("Complete uuids",4) - elif type.val == 0x06: - val=NBytes_List("Incomplete uuids",16) - elif type.val == 0x07: - val=NBytes_List("Complete uuids",16) - elif type.val == 0x08: - val=String("Short Name") - elif type.val == 0x09: - val=String("Complete Name") - elif type.val == 0x14: - val=NBytes_List("Service Solicitation uuid",2) - elif type.val == 0x15: - val=NBytes_List("Service Solicitation uuid",16) - elif type.val == 0x16: - val=Adv_Data("Advertised Data",2) - elif type.val == 0x1f: - val=NBytes_List("Service Solicitation uuid",4) - elif type.val == 0x20: - val=Adv_Data("Advertised Data",4) - elif type.val == 0x21: - val=Adv_Data("Advertised Data",16) - elif type.val == 0xff: - val=ManufacturerSpecificData() - else: - val=Itself("Payload for %s"%type.strval) - - # Some data type may consume all input data, therefore an copy - # is passed instead. - val.decode(data[:length.val-len(type)]) - - self.payload.append(type) - self.payload.append(val) - - return data[length.val-len(type):] - - def show(self,depth=0): - for x in self.payload: - x.show(depth+1) - -# -# The defs are over. Now the realstuffs -# - -def create_bt_socket(interface=0): - exceptions = [] - sock = None - try: - sock = socket.socket(family=socket.AF_BLUETOOTH, - type=socket.SOCK_RAW, - proto=socket.BTPROTO_HCI) - sock.setblocking(False) - sock.setsockopt(socket.SOL_HCI, socket.HCI_FILTER, pack("IIIh2x", 0xffffffff,0xffffffff,0xffffffff,0)) #type mask, event mask, event mask, opcode - try: - sock.bind((interface,)) - except OSError as exc: - exc = OSError( - exc.errno, 'error while attempting to bind on ' - 'interface {!r}: {}'.format( - interface, exc.strerror)) - exceptions.append(exc) - except OSError as exc: - if sock is not None: - sock.close() - exceptions.append(exc) - except: - if sock is not None: - sock.close() - raise - if len(exceptions) == 1: - raise exceptions[0] - elif len(exceptions) > 1: - model = str(exceptions[0]) - if all(str(exc) == model for exc in exceptions): - raise exceptions[0] - raise OSError('Multiple exceptions: {}'.format( - ', '.join(str(exc) for exc in exceptions))) - return sock - -########### - -class BLEScanRequester(asyncio.Protocol): - '''Protocol handling the requests''' - def __init__(self): - self.transport = None - self.smac = None - self.sip = None - self.process = self.default_process - - def connection_made(self, transport): - self.transport = transport - command=HCI_Cmd_LE_Set_Scan_Params() - self.transport.write(command.encode()) - - def connection_lost(self, exc): - super().connection_lost(exc) - - def send_scan_request(self): - '''Sending LE scan request''' - command=HCI_Cmd_LE_Scan_Enable(True,False) - self.transport.write(command.encode()) - - def stop_scan_request(self): - '''Sending LE scan request''' - command=HCI_Cmd_LE_Scan_Enable(False,False) - self.transport.write(command.encode()) - - def send_command(self,command): - '''Sending an arbitrary command''' - self.transport.write(command.encode()) - - def data_received(self, packet): - self.process(packet) - - def default_process(self,data): - pass diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/eddystone.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/eddystone.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/eddystone.py 2021-05-27 06:47:04.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/eddystone.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,361 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding:utf-8 -*- -# -# This file deal with EddyStone formated message -# -# Copyright (c) 2017 François Wautier -# -# Note part of this code was adapted from PyBeacon (https://github.com/nirmankarta/PyBeacon) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -# of the Software, and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all copies -# or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -# IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE - -import checkbox_support.vendor.aioblescan as aios -from urllib.parse import urlparse -from enum import Enum - -# -EDDY_UUID=b"\xfe\xaa" #Google UUID - -class ESType(Enum): - """Enumerator for Eddystone types.""" - uid = 0x00 - url = 0x10 - tlm = 0x20 - eid = 0x30 - -url_schemes = [ - ("http",True), - ("https",True), - ("http",False), - ("https",False), - ] - -url_domain = [ - "com","org","edu","net","info","biz","gov"] - -class EddyStone(object): - """Class defining the content of an EddyStone advertisement. - - Here the param type will depend on the type. - - For URL it should be a string with a compatible URL. - - For UID it is a dictionary with 2 keys, "namespace" and "instance", values are bytes . - - For TLM it shall be an dictionary with 4 keys: "battery","temperature", "count" and "uptime". - Any missing key shall be replaced by its default value. - - For EID it should me a bytes string of length 8 - - :param type: The type of EddyStone advertisement. From ESType - :type type: ESType - :oaram param: The payload corresponding to the type - - """ - - def __init__(self, type=ESType.url, param="https://goo.gl/m9UiEA"): - self.power = 0 - self.payload = [] #As defined in https://github.com/google/eddystone/blob/master/protocol-specification.md - self.payload.append(aios.Byte("Flag Length",b'\x02')) - self.payload.append(aios.Byte("Flag Data Type",b'\x01')) - self.payload.append(aios.Byte("Flag Data",b'\x1a')) - self.payload.append(aios.Byte("Length UUID services",b'\x03')) - self.payload.append(aios.Byte("Complete List UUID Service",b'\x03')) - self.payload.append(aios.Byte("Eddystone UUID",b'\xaa')) - self.payload.append(aios.Byte("...",b'\xfe')) - self.service_data_length = aios.IntByte("Service Data length",4) - self.payload.append(self.service_data_length) - self.payload.append(aios.Byte("Service Data data type value",b'\x16')) - self.payload.append(aios.Byte("Eddystone UUID",b'\xaa')) - self.payload.append(aios.Byte("...",b'\xfe')) - self.type = aios.EnumByte("type",type.value,{ESType.uid.value:"Eddystone-UID", - ESType.url.value:"Eddystone-URL", - ESType.tlm.value:"Eddystone-TLM", - ESType.eid.value:"Eddystone-EID"}) - self.payload.append(self.type) - self.parsed_payload = b'' - self.type_payload=param - - def change_type(self, type, param): - self.type.val=type.value - self.type_payload=param - self.service_data_length.val=4 - self.parsed_payload = b'' - - def change_type_payload(self, param): - self.type_payload=param - self.service_data_length.val=4 - self.parsed_payload = b'' - - def url_encoder(self): - encodedurl = [] - encodedurl.append(aios.IntByte("Tx Power",self.power)) - asisurl="" - myurl = urlparse(self.type_payload) - myhostname = myurl.hostname - mypath = myurl.path - if (myurl.scheme,myhostname.startswith("www.")) in url_schemes: - encodedurl.append(aios.IntByte("URL Scheme", - url_schemes.index((myurl.scheme,myhostname.startswith("www."))))) - if myhostname.startswith("www."): - myhostname = myhostname[4:] - extval=None - if myhostname.split(".")[-1] in url_domain: - extval = url_domain.index(myhostname.split(".")[-1]) - myhostname = ".".join(myhostname.split(".")[:-1]) - if extval is not None and not mypath.startswith("/"): - extval+=7 - else: - if myurl.port is None: - if extval is not None: - mypath = mypath[1:] - else: - extval += 7 - encodedurl.append(aios.String("URL string")) - encodedurl[-1].val = myhostname - if extval is not None: - encodedurl.append(aios.IntByte("URL Extention",extval)) - - if myurl.port: - asisurl += ":"+str(myurl.port)+mypath - asisurl += mypath - if myurl.params: - asisurl += ";"+myurl.params - if myurl.query: - asisurl += "?"+myurl.query - if myurl.fragment: - asisurl += "#"+myurl.fragment - encodedurl.append(aios.String("Rest of URL")) - encodedurl[-1].val = asisurl - tlength=0 - for x in encodedurl: #Check the payload length - tlength += len(x) - if tlength > 19: #Actually 18 but we have tx power - raise Exception("Encoded url too long (max 18 bytes)") - self.service_data_length.val += tlength #Update the payload length - return encodedurl - - - def uid_encoder(self): - encodedurl = [] - encodedurl.append(aios.IntByte("Tx Power",self.power)) - encodedurl.append(aios.NBytes("Namespace",10)) - encodedurl[-1].val = self.type_payload["namespace"] - encodedurl.append(aios.NBytes("Instance",6)) - encodedurl[-1].val = self.type_payload["instance"] - encodedurl.append(aios.NBytes("RFU",2)) - encodedurl[-1].val = b'\x00\x00' - self.service_data_length.val = 23 #Update the payload length/ways the same for uid - return encodedurl - - def tlm_encoder(self): - encodedurl = [] - encodedurl.append(aios.NBytes("VBATT",2)) - if "battery" in self.type_payload: - encodedurl[-1].val = self.type_payload["battery"] - else: - encodedurl[-1].val = -128 - encodedurl.append(aios.Float88("Temperature")) - if "temperature" in self.type_payload: - encodedurl[-1].val = self.type_payload["temperature"] - else: - encodedurl[-1].val = -128 - - encodedurl.append(aios.ULongInt("Count")) - if "count" in self.type_payload: - encodedurl[-1].val = self.type_payload["count"] - else: - encodedurl[-1].val = 0 - - encodedurl.append(aios.ULongInt("Uptime")) - if "uptime" in self.type_payload: - encodedurl[-1].val = self.type_payload["uptime"] - else: - encodedurl[-1].val = 0 - return encodedurl - - - def eid_encoder(self): - encodedurl = [] - encodedurl.append(aios.IntByte("Tx Power",self.power)) - encodedurl.append(aios.NBytes("Namespace",8)) - encodedurl[-1].val = self.type_payload - self.service_data_length.val = 13 - return encodedurl - - - def encode(self): - #Generate the payload - if self.type.val == ESType.uid.value: - espayload = self.uid_encoder() - elif self.type.val == ESType.url.value: - espayload = self.url_encoder() - elif self.type.val == ESType.tlm.value: - espayload = self.tlm_encoder() - elif self.type.val == ESType.eid.value: - espayload = self.eid_encoder() - encmsg=b'' - for x in self.payload+espayload: - encmsg += x.encode() - mylen=aios.IntByte("Length",len(encmsg)) - encmsg = mylen.encode()+encmsg - for x in range(32-len(encmsg)): - encmsg+=b'\x00' - return encmsg - - def decode(self, packet): - """Check a parsed packet and figure out if it is an Eddystone Beacon. - If it is , return the relevant data as a dictionary. - - Return None, it is not an Eddystone Beacon advertising packet""" - - ssu=packet.retrieve("Complete uuids") - found=False - for x in ssu: - if EDDY_UUID in x: - found=True - break - if not found: - return None - - found=False - adv=packet.retrieve("Advertised Data") - for x in adv: - luuid=x.retrieve("Service Data uuid") - for uuid in luuid: - if EDDY_UUID == uuid: - found=x - break - if found: - break - - - if not found: - return None - - try: - top=found.retrieve("Adv Payload")[0] - except: - return None - #Rebuild that part of the structure - found.payload.remove(top) - #Now decode - result={} - data=top.val - etype = aios.EnumByte("type",self.type.val,{ESType.uid.value:"Eddystone-UID", - ESType.url.value:"Eddystone-URL", - ESType.tlm.value:"Eddystone-TLM", - ESType.eid.value:"Eddystone-EID"}) - data=etype.decode(data) - found.payload.append(etype) - if etype.val== ESType.uid.value: - power=aios.IntByte("tx_power") - data=power.decode(data) - found.payload.append(power) - result["tx_power"]=power.val - - nspace=aios.Itself("namespace") - xx=nspace.decode(data[:10]) #According to https://github.com/google/eddystone/tree/master/eddystone-uid - data=data[10:] - found.payload.append(nspace) - result["name space"]=nspace.val - - nspace=aios.Itself("instance") - xx=nspace.decode(data[:6]) #According to https://github.com/google/eddystone/tree/master/eddystone-uid - data=data[6:] - found.payload.append(nspace) - result["instance"]=nspace.val - - elif etype.val== ESType.url.value: - power=aios.IntByte("tx_power") - data=power.decode(data) - found.payload.append(power) - result["tx_power"]=power.val - - url=aios.EnumByte("type",0,{0x00:"http://www.",0x01:"https://www.",0x02:"http://",0x03:"https://"}) - data=url.decode(data) - result["url"]=url.strval - for x in data: - if bytes([x]) == b"\x00": - result["url"]+=".com/" - elif bytes([x]) == b"\x01": - result["url"]+=".org/" - elif bytes([x]) == b"\x02": - result["url"]+=".edu/" - elif bytes([x]) == b"\x03": - result["url"]+=".net/" - elif bytes([x]) == b"\x04": - result["url"]+=".info/" - elif bytes([x]) == b"\x05": - result["url"]+=".biz/" - elif bytes([x]) == b"\x06": - result["url"]+=".gov/" - elif bytes([x]) == b"\x07": - result["url"]+=".com" - elif bytes([x]) == b"\x08": - result["url"]+=".org" - elif bytes([x]) == b"\x09": - result["url"]+=".edu" - elif bytes([x]) == b"\x10": - result["url"]+=".net" - elif bytes([x]) == b"\x11": - result["url"]+=".info" - elif bytes([x]) == b"\x12": - result["url"]+=".biz" - elif bytes([x]) == b"\x13": - result["url"]+=".gov" - else: - result["url"]+=chr(x) #x.decode("ascii") #Yep ASCII only - url=aios.String("url") - url.decode(result["url"]) - found.payload.append(url) - elif etype.val== ESType.tlm.value: - myinfo=aios.IntByte("version") - data=myinfo.decode(data) - found.payload.append(myinfo) - myinfo=aios.ShortInt("battery") - data=myinfo.decode(data) - result["battery"]=myinfo.val - found.payload.append(myinfo) - myinfo=aios.Float88("temperature") - data=myinfo.decode(data) - found.payload.append(myinfo) - result["temperature"]=myinfo.val - myinfo=aios.LongInt("pdu count") - data=myinfo.decode(data) - found.payload.append(myinfo) - result["pdu count"]=myinfo.val - myinfo=aios.LongInt("uptime") - data=myinfo.decode(data) - found.payload.append(myinfo) - result["uptime"]=myinfo.val*100 #in msecs - return result - #elif etype.val== ESType.tlm.eid: - else: - result["data"]=data - xx=Itself("data") - xx.decode(data) - found.payload.append(xx) - - rssi=packet.retrieve("rssi") - if rssi: - result["rssi"]=rssi[-1].val - mac=packet.retrieve("peer") - if mac: - result["mac address"]=mac[-1].val - return result diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/__init__.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/__init__.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/__init__.py 2021-05-27 06:47:04.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/__init__.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -from .aioblescan import * -__version__ = '0.2.1' diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/LICENSE.txt checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/LICENSE.txt --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/LICENSE.txt 2021-05-27 06:47:04.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/aioblescan/LICENSE.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright © 2017 François Wautier - -Permission is hereby granted, free of charge, to any person obtaining a copy of this -oftware and associated documentation files (the "Software"), to deal in the Software -without restriction, including without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be included in all copies -or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT ORxi -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/backend/freebsd.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/backend/freebsd.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/backend/freebsd.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/backend/freebsd.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,61 @@ +"""Custom backend for FreeBSD.""" +import os +import socket +import struct +import ctypes + +libc = ctypes.cdll.LoadLibrary('libc.so.7') + +NG_HCI_EVENT_MASK_LE = 0x2000000000000000 +SOL_HCI_RAW = 0x0802 +SOL_HCI_RAW_FILTER = 1 + +class SockaddrHci(ctypes.Structure): + """Structure representing a hci socket address.""" + _fields_ = [ + ('hci_len', ctypes.c_char), + ('hci_family', ctypes.c_char), + ('hci_node', ctypes.c_char * 32), + ] + +class HciRawFilter(ctypes.Structure): + """Structure specifying filter masks.""" + _fields_ = [ + ('packet_mask', ctypes.c_uint32), + ('event_mask', ctypes.c_uint64), + ] + +def open_dev(bt_device_id): + """Open hci device socket.""" + # pylint: disable=no-member + sock = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI) + + # Unlike Linux, FreeBSD has separate numbering depending on hardware + # (ubt - USB bluetooth - is the most common, so convert numbers to that) + if not isinstance(bt_device_id, str): + bt_device_id = 'ubt{}hci'.format(bt_device_id) + + # Python's BTPROTO_HCI address parsing is busted: https://bugs.python.org/issue41130 + adr = SockaddrHci(ctypes.sizeof(SockaddrHci), socket.AF_BLUETOOTH, bt_device_id.ljust(32, '\0').encode('utf-8')) + if libc.bind(sock.fileno(), ctypes.pointer(adr), ctypes.sizeof(SockaddrHci)) != 0: + raise ConnectionError(ctypes.get_errno(), os.strerror(ctypes.get_errno())) + if libc.connect(sock.fileno(), ctypes.pointer(adr), ctypes.sizeof(SockaddrHci)) != 0: + raise ConnectionError(ctypes.get_errno(), os.strerror(ctypes.get_errno())) + # pylint: enable=no-member + + fltr = HciRawFilter(0, NG_HCI_EVENT_MASK_LE) + if libc.setsockopt(sock.fileno(), + SOL_HCI_RAW, SOL_HCI_RAW_FILTER, + ctypes.pointer(fltr), ctypes.sizeof(HciRawFilter)) != 0: + raise ConnectionError(ctypes.get_errno(), os.strerror(ctypes.get_errno())) + + return sock + +def send_cmd(sock, group_field, command_field, data): + """Send hci command to device.""" + opcode = (((group_field & 0x3f) << 10) | (command_field & 0x3ff)) + sock.send(struct.pack('".format( + name=self.name, temperature=self.temperature, + humidity=self.humidity, light=self.light) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/eddystone.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/eddystone.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/eddystone.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/eddystone.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,149 @@ +"""Packet classes for Eddystone beacons.""" +from binascii import hexlify +from ..const import EDDYSTONE_URL_SCHEMES, EDDYSTONE_TLD_ENCODINGS +from ..utils import data_to_hexstring, data_to_binstring + +class EddystoneUIDFrame(object): + """Eddystone UID frame.""" + + def __init__(self, data): + self._tx_power = data['tx_power'] + self._namespace = data_to_hexstring(data['namespace']) + self._instance = data_to_hexstring(data['instance']) + + @property + def tx_power(self): + """Calibrated Tx power at 0 m.""" + return self._tx_power + + @property + def namespace(self): + """10-byte namespace identifier.""" + return self._namespace + + @property + def instance(self): + """6-byte instance identifier.""" + return self._instance + + @property + def properties(self): + """Get beacon properties.""" + return {'namespace': self.namespace, 'instance': self.instance} + + def __str__(self): + return "EddystoneUIDFrame" \ + % (self.tx_power, self.namespace, self.instance) + + +class EddystoneURLFrame(object): + """Eddystone URL frame.""" + + def __init__(self, data): + self._tx_power = data['tx_power'] + url_scheme = EDDYSTONE_URL_SCHEMES[data['url_scheme']] + url = data['url'] + + # Replace url encodings with their expanded version + for enc, tld in EDDYSTONE_TLD_ENCODINGS.items(): + url = url.replace(chr(enc), tld) + + self._url = url_scheme + url + + @property + def tx_power(self): + """Calibrated Tx power at 0 m.""" + return self._tx_power + + @property + def url(self): + """Transmitted URL.""" + return self._url + + def __str__(self): + return "EddystoneURLFrame" \ + % (self.tx_power, self.url) + + +class EddystoneEncryptedTLMFrame(object): + """Eddystone encrypted TLM frame.""" + + def __init__(self, data): + self._encrypted_data = data_to_binstring(data['encrypted_data']) + self._salt = data['salt'] + self._mic = data['mic'] + + @property + def encrypted_data(self): + """Encrypted TLM data.""" + return self._encrypted_data + + @property + def salt(self): + """16-bit salt.""" + return self._salt + + @property + def mic(self): + """16-bit message integrity check.""" + return self._mic + + def __str__(self): + return "EddystoneEncryptedTLMFrame" \ + % (hexlify(self.encrypted_data), self.salt, self.mic) + + +class EddystoneTLMFrame(object): + """Eddystone TLM frame.""" + + def __init__(self, data): + self._voltage = data['voltage'] + self._temperature = data['temperature'] / float(256) + self._advertising_count = data['advertising_count'] + self._seconds_since_boot = data['seconds_since_boot'] + + @property + def voltage(self): + """Battery voltage measured in mV.""" + return self._voltage + + @property + def temperature(self): + """Temperature in degree Celsius.""" + return self._temperature + + @property + def advertising_count(self): + """Advertising PDU count.""" + return self._advertising_count + + @property + def seconds_since_boot(self): + """Time since power-on or reboot.""" + return self._seconds_since_boot + + def __str__(self): + return "EddystoneTLMFrame" % (self.voltage, self.temperature, \ + self.advertising_count, self.seconds_since_boot) + +class EddystoneEIDFrame(object): + """Eddystone EID frame.""" + + def __init__(self, data): + self._tx_power = data['tx_power'] + self._eid = data_to_binstring(data['eid']) + + @property + def tx_power(self): + """Calibrated Tx power at 0 m.""" + return self._tx_power + + @property + def eid(self): + """8-byte Ephemeral Identifier.""" + return self._eid + + def __str__(self): + return "EddystoneEIDFrame" \ + % (self.tx_power, hexlify(self.eid)) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/estimote.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/estimote.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/estimote.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/estimote.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,288 @@ +"""Packet classes for Estimote beacons.""" +from ..utils import data_to_hexstring + +class EstimoteTelemetryFrameA(object): + """Estimote telemetry subframe A.""" + + def __init__(self, data, protocol_version): + self._protocol_version = protocol_version + self._identifier = data_to_hexstring(data['identifier']) + sub = data['sub_frame'] + # acceleration: convert to tuple and normalize + self._acceleration = tuple([v * 2 / 127.0 for v in sub['acceleration']]) + # motion states + self._previous_motion_state = self.parse_motion_state(sub['previous_motion']) + self._current_motion_state = self.parse_motion_state(sub['current_motion']) + self._is_moving = (sub['combined_fields'][0] & 0b00000011) == 1 + # gpio + states = [] + for i in range(4): + states.append((sub['combined_fields'][0] & (1 << (4+i))) != 0) + self._gpio_states = tuple(states) + # error codes + if self.protocol_version == 2: + self._has_firmware_error = ((sub['combined_fields'][0] & 0b00000100) >> 2) == 1 + self._has_clock_error = ((sub['combined_fields'][0] & 0b00001000) >> 3) == 1 + elif self.protocol_version == 1: + self._has_firmware_error = (sub['combined_fields'][1] & 0b00000001) == 1 + self._has_clock_error = ((sub['combined_fields'][1] & 0b00000010) >> 1) == 1 + else: + self._has_firmware_error = None + self._has_clock_error = None + # pressure + if self.protocol_version == 2: + self._pressure = sub['combined_fields'][1] | \ + sub['combined_fields'][2] << 8 | \ + sub['combined_fields'][3] << 16 | \ + sub['combined_fields'][4] << 24 + if self._pressure == 0xffffffff: + self._pressure = None + else: + self._pressure /= 256.0 + else: + self._pressure = None + + @staticmethod + def parse_motion_state(val): + """Convert motion state byte to seconds.""" + number = val & 0b00111111 + unit = (val & 0b11000000) >> 6 + if unit == 1: + number *= 60 # minutes + elif unit == 2: + number *= 60 * 60 # hours + elif unit == 3 and number < 32: + number *= 60 * 60 * 24 # days + elif unit == 3: + number -= 32 + number *= 60 * 60 * 24 * 7 # weeks + return number + + @property + def protocol_version(self): + """Protocol version of the packet.""" + return self._protocol_version + + @property + def identifier(self): + """First half of the identifier of the beacon (8 bytes).""" + return self._identifier + + @property + def acceleration(self): + """Tuple of acceleration values for (X, Y, Z) axis, in g.""" + return self._acceleration + + @property + def is_moving(self): + """Whether the beacon is in motion at the moment (Bool)""" + return self._is_moving + + @property + def current_motion_state(self): + """Duration of current motion state in seconds. + E.g., if is_moving is True, this states how long the beacon is beeing moved already and + previous_motion_state will tell how long it has been still before.""" + return self._current_motion_state + + + @property + def previous_motion_state(self): + """Duration of previous motion state in seconds (see current_motion_state).""" + return self._previous_motion_state + + @property + def gpio_states(self): + """Tuple with state of the GPIO pins 0-3 (True is high, False is low).""" + return self._gpio_states + + @property + def has_firmware_error(self): + """If beacon has a firmware problem. + Only available if protocol version > 0, None otherwise.""" + return self._has_firmware_error + + @property + def has_clock_error(self): + """If beacon has a clock problem. Only available if protocol version > 0, None otherwise.""" + return self._has_clock_error + + @property + def pressure(self): + """Atmosperic pressure in Pascal. None if all bits are set. + Only available if protocol version is 2, None otherwise .""" + return self._pressure + + @property + def properties(self): + """Get beacon properties.""" + return {'identifier': self.identifier, 'protocol_version': self.protocol_version} + + def __str__(self): + return "EstimoteTelemetryFrameA" \ + % (self.identifier, self.protocol_version) + + +class EstimoteTelemetryFrameB(object): + """Estimote telemetry subframe B.""" + + def __init__(self, data, protocol_version): + self._protocol_version = protocol_version + self._identifier = data_to_hexstring(data['identifier']) + sub = data['sub_frame'] + # magnetic field: convert to tuple and normalize + if sub['magnetic_field'] == [-1, -1, -1]: + self._magnetic_field = None + else: + self._magnetic_field = tuple([v / 128.0 for v in sub['magnetic_field']]) + # ambient light + ambient_upper = (sub['ambient_light'] & 0b11110000) >> 4 + ambient_lower = sub['ambient_light'] & 0b00001111 + if ambient_upper == 0xf and ambient_lower == 0xf: + self._ambient_light = None + else: + self._ambient_light = pow(2, ambient_upper) * ambient_lower * 0.72 + # uptime + uptime_unit_code = (sub['combined_fields'][1] & 0b00110000) >> 4 + uptime_number = ((sub['combined_fields'][1] & 0b00001111) << 8) | \ + sub['combined_fields'][0] + if uptime_unit_code == 1: + uptime_number *= 60 # minutes + elif uptime_unit_code == 2: + uptime_number *= 60 * 60 # hours + elif uptime_unit_code == 3: + uptime_number *= 60 * 60 * 24 # days + else: + uptime_number = 0 + self._uptime = uptime_number + # temperature + temperature = ((sub['combined_fields'][3] & 0b00000011) << 10) | \ + (sub['combined_fields'][2] << 2) | \ + ((sub['combined_fields'][1] & 0b11000000) >> 6) + temperature = temperature - 4096 if temperature > 2047 else temperature + self._temperature = temperature / 16.0 + # battery voltage + voltage = (sub['combined_fields'][4] << 6) | \ + ((sub['combined_fields'][3] & 0b11111100) >> 2) + self._voltage = None if voltage == 0b11111111111111 else voltage + if self._protocol_version == 0: + # errors (only protocol ver 0) + self._has_firmware_error = (sub['battery_level'] & 0b00000001) == 1 + self._has_clock_error = (sub['battery_level'] & 0b00000010) == 0b10 + self._battery_level = None + else: + self._battery_level = None if sub['battery_level'] == 0xFF else sub['battery_level'] + self._has_clock_error = None + self._has_firmware_error = None + + + @property + def protocol_version(self): + """Protocol version of the packet.""" + return self._protocol_version + + @property + def identifier(self): + """First half of the identifier of the beacon (8 bytes).""" + return self._identifier + + @property + def magnetic_field(self): + """Tuple of magnetic field values for (X, Y, Z) axis. + Between -1 and 1 or None if all bits are set.""" + return self._magnetic_field + + @property + def ambient_light(self): + """Ambient light in lux.""" + return self._ambient_light + + @property + def uptime(self): + """Uptime in seconds.""" + return self._uptime + + @property + def temperature(self): + """Ambient temperature in celsius.""" + return self._temperature + + @property + def has_firmware_error(self): + """Whether beacon has a firmware problem. + Only available if protocol version is 0, None otherwise.""" + return self._has_firmware_error + + @property + def has_clock_error(self): + """Whether beacon has a clock problem. + Only available if protocol version is 0, None otherwise.""" + return self._has_clock_error + + @property + def battery_level(self): + """Beacon battery level between 0 and 100. + None if protocol version is 0 or not measured yet.""" + return self._battery_level + + @property + def properties(self): + """Get beacon properties.""" + return {'identifier': self.identifier, 'protocol_version': self.protocol_version} + + def __str__(self): + return "EstimoteTelemetryFrameB" \ + % (self.identifier, self.protocol_version) + + +class EstimoteNearable(object): + """Estimote Nearable advertisement.""" + + def __init__(self, data): + self._identifier = data_to_hexstring(data['identifier']) + self._hardware_version = data['hardware_version'] + self._firmware_version = data['firmware_version'] + + # byte 13 and the first 4 bits of byte 14 is the temperature in signed, + temperature_raw_value = (data['temperature'] & 0x0fff) + if temperature_raw_value > 2047: + # convert a 12-bit unsigned integer to a signed one + temperature_raw_value = temperature_raw_value - 4096 + temperature = temperature_raw_value / 16.0 + self._temperature = temperature + self._is_moving = data['is_moving'] & 0b01000000 != 0 + + @property + def identifier(self): + """The Nearable identifier (8 bytes).""" + return self._identifier + + @property + def hardware_version(self): + """The hardware version of the nearable.""" + return self._hardware_version + + @property + def firmware_version(self): + """The firmware version of the nearable.""" + return self._firmware_version + + @property + def temperature(self): + """The temperature reading taken by the nearable.""" + return self._temperature + + @property + def is_moving(self): + """Whether the beacon is in motion at the moment.""" + return self._is_moving + + @property + def properties(self): + """Get beacon properties.""" + return {'identifier': self.identifier, 'temperature': self.temperature, + 'is_moving': self._is_moving} + + def __str__(self): + return "EstimoteNearable" \ + % self.identifier diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/exposure_notification.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/exposure_notification.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/exposure_notification.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/exposure_notification.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,27 @@ +"""Packet classes for Eddystone beacons.""" +from ..utils import data_to_hexstring, data_to_binstring + +class ExposureNotificationFrame(object): + """COVID-19 Exposure Notification frame.""" + + def __init__(self, data): + self._identifier = data_to_hexstring(data['identifier']) + self._encrypted_metadata = data_to_binstring(data['encrypted_metadata']) + + @property + def identifier(self): + """16 byte Rolling Proximity Identifier""" + return self._identifier + + @property + def encrypted_metadata(self): + """4 byte encrypted data containing version info and transmission power""" + return self._encrypted_metadata + + @property + def properties(self): + """Get beacon properties.""" + return {'identifier': self.identifier, 'encrypted_metadata' : self.encrypted_metadata} + + def __str__(self): + return "ExposureNotificationFrame" % (self.identifier) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/ibeacon.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/ibeacon.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/ibeacon.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/ibeacon.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,50 @@ +"""Packet classes for iBeacon beacons.""" +from ..utils import data_to_uuid + +class IBeaconAdvertisement(object): + """iBeacon advertisement.""" + + def __init__(self, data): + self._uuid = data_to_uuid(data['uuid']) + self._major = data['major'] + self._minor = data['minor'] + self._tx_power = data['tx_power'] + + @property + def tx_power(self): + """Calibrated Tx power at 0 m.""" + return self._tx_power + + @property + def uuid(self): + """16-byte uuid.""" + return self._uuid + + @property + def major(self): + """2-byte major identifier.""" + return self._major + + @property + def minor(self): + """2-byte minor identifier.""" + return self._minor + + @property + def cypress_temperature(self): + """Cypress iBeacon Sensor temperature in C.""" + return 175.72*((self._minor & 0xff)*256)/65536 - 46.85 + + @property + def cypress_humidity(self): + """Cypress iBeacon Sensor humidity RH%.""" + return 125.0*(self._minor & 0xff00)/65536 - 6 + + @property + def properties(self): + """Get beacon properties.""" + return {'uuid': self.uuid, 'major': self.major, 'minor': self.minor} + + def __str__(self): + return "IBeaconAdvertisement" \ + % (self.tx_power, self.uuid, self.major, self.minor) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/__init__.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/__init__.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/packet_types/__init__.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,7 @@ +"""Packets supported by the parser.""" +from .eddystone import EddystoneUIDFrame, EddystoneURLFrame, EddystoneEncryptedTLMFrame, \ + EddystoneTLMFrame, EddystoneEIDFrame +from .ibeacon import IBeaconAdvertisement +from .estimote import EstimoteTelemetryFrameA, EstimoteTelemetryFrameB, EstimoteNearable +from .controlj import CJMonitorAdvertisement +from .exposure_notification import ExposureNotificationFrame diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/parser.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/parser.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/parser.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/parser.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,85 @@ +"""Beacon advertisement parser.""" +from checkbox_support.vendor.construct import ConstructError + +from .structs import LTVFrame +from .packet_types import EddystoneUIDFrame, EddystoneURLFrame, EddystoneEncryptedTLMFrame, \ + EddystoneTLMFrame, EddystoneEIDFrame, IBeaconAdvertisement, \ + EstimoteTelemetryFrameA, EstimoteTelemetryFrameB, EstimoteNearable, \ + CJMonitorAdvertisement, ExposureNotificationFrame +from .const import EDDYSTONE_TLM_UNENCRYPTED, EDDYSTONE_TLM_ENCRYPTED, SERVICE_DATA_TYPE, \ + EDDYSTONE_UID_FRAME, EDDYSTONE_TLM_FRAME, EDDYSTONE_URL_FRAME, \ + EDDYSTONE_EID_FRAME, EDDYSTONE_UUID, ESTIMOTE_UUID, ESTIMOTE_TELEMETRY_FRAME, \ + ESTIMOTE_TELEMETRY_SUBFRAME_A, ESTIMOTE_TELEMETRY_SUBFRAME_B, \ + MANUFACTURER_SPECIFIC_DATA_TYPE, ESTIMOTE_MANUFACTURER_ID, CJ_MANUFACTURER_ID, \ + IBEACON_MANUFACTURER_ID, EXPOSURE_NOTIFICATION_UUID + +# pylint: disable=invalid-name,too-many-return-statements + +def parse_packet(packet): + """Parse a beacon advertisement packet.""" + return parse_ltv_packet(packet) + +def parse_ltv_packet(packet): + """Parse a tag-length-value style beacon packet.""" + try: + frame = LTVFrame.parse(packet) + + for ltv in frame: + if ltv['type'] == SERVICE_DATA_TYPE: + data = ltv['value'] + + if data["service_identifier"] == EDDYSTONE_UUID: + return parse_eddystone_service_data(data['service_data']) + + elif data["service_identifier"] == ESTIMOTE_UUID: + return parse_estimote_service_data(data['service_data']) + + elif data["service_identifier"] == EXPOSURE_NOTIFICATION_UUID: + return ExposureNotificationFrame(data["service_data"]) + + + elif ltv['type'] == MANUFACTURER_SPECIFIC_DATA_TYPE: + data = ltv["value"] + + if data["company_identifier"] == ESTIMOTE_MANUFACTURER_ID: + return EstimoteNearable(data['data']) + + elif data["company_identifier"] == CJ_MANUFACTURER_ID: + return CJMonitorAdvertisement(frame) + + elif data["company_identifier"] == IBEACON_MANUFACTURER_ID: + return IBeaconAdvertisement(data['data']) + + except ConstructError: + return None + + return None + +def parse_eddystone_service_data(data): + """Parse Eddystone service data.""" + if data['frame_type'] == EDDYSTONE_UID_FRAME: + return EddystoneUIDFrame(data['frame']) + + elif data['frame_type'] == EDDYSTONE_TLM_FRAME: + if data['frame']['tlm_version'] == EDDYSTONE_TLM_ENCRYPTED: + return EddystoneEncryptedTLMFrame(data['frame']['data']) + elif data['frame']['tlm_version'] == EDDYSTONE_TLM_UNENCRYPTED: + return EddystoneTLMFrame(data['frame']['data']) + + elif data['frame_type'] == EDDYSTONE_URL_FRAME: + return EddystoneURLFrame(data['frame']) + + elif data['frame_type'] == EDDYSTONE_EID_FRAME: + return EddystoneEIDFrame(data['frame']) + else: + return None + +def parse_estimote_service_data(data): + """Parse Estimote service data.""" + if data['frame_type'] & 0xF == ESTIMOTE_TELEMETRY_FRAME: + protocol_version = (data['frame_type'] & 0xF0) >> 4 + if data['frame']['subframe_type'] == ESTIMOTE_TELEMETRY_SUBFRAME_A: + return EstimoteTelemetryFrameA(data['frame'], protocol_version) + elif data['frame']['subframe_type'] == ESTIMOTE_TELEMETRY_SUBFRAME_B: + return EstimoteTelemetryFrameB(data['frame'], protocol_version) + return None diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/scanner.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/scanner.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/scanner.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools/scanner.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,341 @@ +"""Classes responsible for Beacon scanning.""" +import logging +import struct +import threading +from importlib import import_module +from enum import IntEnum +from checkbox_support.vendor.construct import Struct, Byte, Bytes, GreedyRange, ConstructError + +from checkbox_support.vendor.ahocorapy.keywordtree import KeywordTree + +from .const import (CJ_MANUFACTURER_ID, EDDYSTONE_UUID, + ESTIMOTE_MANUFACTURER_ID, ESTIMOTE_UUID, + EVT_LE_ADVERTISING_REPORT, EXPOSURE_NOTIFICATION_UUID, + IBEACON_MANUFACTURER_ID, IBEACON_PROXIMITY_TYPE, + LE_META_EVENT, MANUFACTURER_SPECIFIC_DATA_TYPE, + MS_FRACTION_DIVIDER, OCF_LE_SET_SCAN_ENABLE, + OCF_LE_SET_SCAN_PARAMETERS, OGF_LE_CTL, + BluetoothAddressType, ScanFilter, ScannerMode, ScanType, + OCF_LE_SET_EXT_SCAN_PARAMETERS, OCF_LE_SET_EXT_SCAN_ENABLE, + EVT_LE_EXT_ADVERTISING_REPORT, OGF_INFO_PARAM, + OCF_READ_LOCAL_VERSION, EVT_CMD_COMPLETE) +from .device_filters import BtAddrFilter, DeviceFilter +from .packet_types import (EddystoneEIDFrame, EddystoneEncryptedTLMFrame, + EddystoneTLMFrame, EddystoneUIDFrame, + EddystoneURLFrame) +from .parser import parse_packet +from .utils import (bin_to_int, bt_addr_to_string, get_mode, is_one_of, + is_packet_type, to_int) + + +class HCIVersion(IntEnum): + """HCI version enumeration + + https://www.bluetooth.com/specifications/assigned-numbers/host-controller-interface/ + """ + BT_CORE_SPEC_1_0 = 0 + BT_CODE_SPEC_1_1 = 1 + BT_CODE_SPEC_1_2 = 2 + BT_CORE_SPEC_2_0 = 3 + BT_CORE_SPEC_2_1 = 4 + BT_CORE_SPEC_3_0 = 5 + BT_CORE_SPEC_4_0 = 6 + BT_CORE_SPEC_4_1 = 7 + BT_CORE_SPEC_4_2 = 8 + BT_CORE_SPEC_5_0 = 9 + BT_CORE_SPEC_5_1 = 10 + BT_CORE_SPEC_5_2 = 11 + + +_LOGGER = logging.getLogger(__name__) +_LOGGER.setLevel(logging.DEBUG) + +# pylint: disable=no-member + + +class BeaconScanner(object): + """Scan for Beacon advertisements.""" + + def __init__(self, callback, bt_device_id=0, device_filter=None, packet_filter=None, scan_parameters=None): + """Initialize scanner.""" + # check if device filters are valid + if device_filter is not None: + if not isinstance(device_filter, list): + device_filter = [device_filter] + if len(device_filter) > 0: + for filtr in device_filter: + if not isinstance(filtr, DeviceFilter): + raise ValueError("Device filters must be instances of DeviceFilter") + else: + device_filter = None + + # check if packet filters are valid + if packet_filter is not None: + if not isinstance(packet_filter, list): + packet_filter = [packet_filter] + if len(packet_filter) > 0: + for filtr in packet_filter: + if not is_packet_type(filtr): + raise ValueError("Packet filters must be one of the packet types") + else: + packet_filter = None + + if scan_parameters is None: + scan_parameters = {} + + self._mon = Monitor(callback, bt_device_id, device_filter, packet_filter, scan_parameters) + + def start(self): + """Start beacon scanning.""" + self._mon.start() + + def stop(self): + """Stop beacon scanning.""" + self._mon.terminate() + + +class Monitor(threading.Thread): + """Continously scan for BLE advertisements.""" + + def __init__(self, callback, bt_device_id, device_filter, packet_filter, scan_parameters): + """Construct interface object.""" + # do import here so that the package can be used in parsing-only mode (no bluez required) + self.backend = import_module('checkbox_support.vendor.beacontools.backend') + + threading.Thread.__init__(self) + self.daemon = False + self.keep_going = True + self.callback = callback + + # number of the bt device (hciX) + self.bt_device_id = bt_device_id + # list of beacons to monitor + self.device_filter = device_filter + self.mode = get_mode(device_filter) + # list of packet types to monitor + self.packet_filter = packet_filter + # bluetooth socket + self.socket = None + # keep track of Eddystone Beacon <-> bt addr mapping + self.eddystone_mappings = [] + # parameters to pass to bt device + self.scan_parameters = scan_parameters + # hci version + self.hci_version = HCIVersion.BT_CORE_SPEC_1_0 + + # construct an aho-corasick search tree for efficient prefiltering + service_uuid_prefix = b"\x03\x03" + self.kwtree = KeywordTree() + if self.mode & ScannerMode.MODE_IBEACON: + self.kwtree.add(bytes([MANUFACTURER_SPECIFIC_DATA_TYPE]) + IBEACON_MANUFACTURER_ID + IBEACON_PROXIMITY_TYPE) + if self.mode & ScannerMode.MODE_EDDYSTONE: + self.kwtree.add(service_uuid_prefix + EDDYSTONE_UUID) + if self.mode & ScannerMode.MODE_ESTIMOTE: + self.kwtree.add(service_uuid_prefix + ESTIMOTE_UUID) + self.kwtree.add(bytes([MANUFACTURER_SPECIFIC_DATA_TYPE]) + ESTIMOTE_MANUFACTURER_ID) + if self.mode & ScannerMode.MODE_CJMONITOR: + self.kwtree.add(bytes([MANUFACTURER_SPECIFIC_DATA_TYPE]) + CJ_MANUFACTURER_ID) + if self.mode & ScannerMode.MODE_EXPOSURE_NOTIFICATION: + self.kwtree.add(service_uuid_prefix + EXPOSURE_NOTIFICATION_UUID) + self.kwtree.finalize() + + def run(self): + """Continously scan for BLE advertisements.""" + self.socket = self.backend.open_dev(self.bt_device_id) + + self.hci_version = self.get_hci_version() + self.set_scan_parameters(**self.scan_parameters) + self.toggle_scan(True) + + while self.keep_going: + pkt = self.socket.recv(255) + event = to_int(pkt[1]) + subevent = to_int(pkt[3]) + if event == LE_META_EVENT and subevent in [EVT_LE_ADVERTISING_REPORT, EVT_LE_EXT_ADVERTISING_REPORT]: + # we have an BLE advertisement + self.process_packet(pkt) + self.socket.close() + + def get_hci_version(self): + """Gets the HCI version""" + local_version = Struct( + "status" / Byte, + "hci_version" / Byte, + "hci_revision" / Bytes(2), + "lmp_version" / Byte, + "manufacturer_name" / Bytes(2), + "lmp_subversion" / Bytes(2), + ) + + try: + resp = self.backend.send_req(self.socket, OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION, + EVT_CMD_COMPLETE, local_version.sizeof(), bytes(), 0) + return HCIVersion(GreedyRange(local_version).parse(resp)[0]["hci_version"]) + except (ConstructError, NotImplementedError): + return HCIVersion.BT_CORE_SPEC_1_0 + + def set_scan_parameters(self, scan_type=ScanType.ACTIVE, interval_ms=10, window_ms=10, + address_type=BluetoothAddressType.RANDOM, filter_type=ScanFilter.ALL): + """"Sets the le scan parameters + + For extended set scan parameters command additional parameter scanning PHYs has to be provided. + The parameter indicates the PHY(s) on which the advertising packets should be received on the + primary advertising physical channel. For further information have a look on BT Core 5.1 Specification, + page 1439 ( LE Set Extended Scan Parameters command). + + Args: + scan_type: ScanType.(PASSIVE|ACTIVE) + interval: ms (as float) between scans (valid range 2.5ms - 10240ms or 40.95s for extended version) + ..note:: when interval and window are equal, the scan + runs continuos + window: ms (as float) scan duration (valid range 2.5ms - 10240ms or 40.95s for extended version) + address_type: Bluetooth address type BluetoothAddressType.(PUBLIC|RANDOM) + * PUBLIC = use device MAC address + * RANDOM = generate a random MAC address and use that + filter: ScanFilter.(ALL|WHITELIST_ONLY) only ALL is supported, which will + return all fetched bluetooth packets (WHITELIST_ONLY is not supported, + because OCF_LE_ADD_DEVICE_TO_WHITE_LIST command is not implemented) + + Raises: + ValueError: A value had an unexpected format or was not in range + """ + max_interval = (0x4000 if self.hci_version < HCIVersion.BT_CORE_SPEC_5_0 else 0xFFFF) + interval_fractions = interval_ms / MS_FRACTION_DIVIDER + if interval_fractions < 0x0004 or interval_fractions > max_interval: + raise ValueError( + "Invalid interval given {}, must be in range of 2.5ms to {}ms!".format( + interval_fractions, max_interval * MS_FRACTION_DIVIDER)) + window_fractions = window_ms / MS_FRACTION_DIVIDER + if window_fractions < 0x0004 or window_fractions > max_interval: + raise ValueError( + "Invalid window given {}, must be in range of 2.5ms to {}ms!".format( + window_fractions, max_interval * MS_FRACTION_DIVIDER)) + + interval_fractions, window_fractions = int(interval_fractions), int(window_fractions) + + if self.hci_version < HCIVersion.BT_CORE_SPEC_5_0: + command_field = OCF_LE_SET_SCAN_PARAMETERS + scan_parameter_pkg = struct.pack( + "> 4) + 5 + return ((1 << position) | ((mudata & 0xF) << (position - 4)) | (1 << (position - 5))) - 33 + +def bt_addr_to_string(addr): + """Convert a binary string to the hex representation.""" + addr_str = array.array('B', addr) + addr_str.reverse() + hex_str = hexlify(addr_str.tobytes()).decode('ascii') + # insert ":" seperator between the bytes + return ':'.join(a+b for a, b in zip(hex_str[::2], hex_str[1::2])) + + +def is_one_of(obj, types): + """Return true iff obj is an instance of one of the types.""" + for type_ in types: + if isinstance(obj, type_): + return True + return False + + +def is_packet_type(cls): + """Check if class is one the packet types.""" + # pylint: disable=import-outside-toplevel + from .packet_types import EddystoneUIDFrame, EddystoneURLFrame, \ + EddystoneEncryptedTLMFrame, EddystoneTLMFrame, \ + EddystoneEIDFrame, IBeaconAdvertisement, \ + EstimoteTelemetryFrameA, EstimoteTelemetryFrameB, \ + ExposureNotificationFrame + # pylint: enable=import-outside-toplevel + + return (cls in [EddystoneURLFrame, EddystoneUIDFrame, EddystoneEncryptedTLMFrame, \ + EddystoneTLMFrame, EddystoneEIDFrame, IBeaconAdvertisement, \ + EstimoteTelemetryFrameA, EstimoteTelemetryFrameB, \ + ExposureNotificationFrame]) + + +def to_int(string): + """Convert a one element byte string to int for python 2 support.""" + if isinstance(string, str): + return ord(string[0]) + else: + return string + + +def bin_to_int(string): + """Convert a one element byte string to signed int for python 2 support.""" + if isinstance(string, str): + return struct.unpack("b", string)[0] + else: + return struct.unpack("b", bytes([string]))[0] + + +def get_mode(device_filter): + """Determine which beacons the scanner should look for.""" + from .device_filters import IBeaconFilter, EddystoneFilter, BtAddrFilter, EstimoteFilter, \ + CJMonitorFilter, ExposureNotificationFilter # pylint: disable=import-outside-toplevel + + if device_filter is None or len(device_filter) == 0: + return ScannerMode.MODE_ALL + + mode = ScannerMode.MODE_NONE + for filtr in device_filter: + if isinstance(filtr, IBeaconFilter): + mode |= ScannerMode.MODE_IBEACON + elif isinstance(filtr, EddystoneFilter): + mode |= ScannerMode.MODE_EDDYSTONE + elif isinstance(filtr, EstimoteFilter): + mode |= ScannerMode.MODE_ESTIMOTE + elif isinstance(filtr, CJMonitorFilter): + mode |= ScannerMode.MODE_CJMONITOR + elif isinstance(filtr, ExposureNotificationFilter): + mode |= ScannerMode.MODE_EXPOSURE_NOTIFICATION + elif isinstance(filtr, BtAddrFilter): + mode |= ScannerMode.MODE_ALL + break + + return mode diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/backend/freebsd.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/backend/freebsd.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/backend/freebsd.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/backend/freebsd.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,57 @@ +"""Custom backend for FreeBSD.""" +import os +import socket +import struct +import ctypes + +libc = ctypes.cdll.LoadLibrary('libc.so.7') + +NG_HCI_EVENT_MASK_LE = 0x2000000000000000 +SOL_HCI_RAW = 0x0802 +SOL_HCI_RAW_FILTER = 1 + +class SockaddrHci(ctypes.Structure): + """Structure representing a hci socket address.""" + _fields_ = [ + ('hci_len', ctypes.c_char), + ('hci_family', ctypes.c_char), + ('hci_node', ctypes.c_char * 32), + ] + +class HciRawFilter(ctypes.Structure): + """Structure specifying filter masks.""" + _fields_ = [ + ('packet_mask', ctypes.c_uint32), + ('event_mask', ctypes.c_uint64), + ] + +def open_dev(bt_device_id): + """Open hci device socket.""" + # pylint: disable=no-member + sock = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI) + + # Unlike Linux, FreeBSD has separate numbering depending on hardware + # (ubt - USB bluetooth - is the most common, so convert numbers to that) + if not isinstance(bt_device_id, str): + bt_device_id = 'ubt{}hci'.format(bt_device_id) + + # Python's BTPROTO_HCI address parsing is busted: https://bugs.python.org/issue41130 + adr = SockaddrHci(ctypes.sizeof(SockaddrHci), socket.AF_BLUETOOTH, bt_device_id.ljust(32, '\0').encode('utf-8')) + if libc.bind(sock.fileno(), ctypes.pointer(adr), ctypes.sizeof(SockaddrHci)) != 0: + raise ConnectionError(ctypes.get_errno(), os.strerror(ctypes.get_errno())) + if libc.connect(sock.fileno(), ctypes.pointer(adr), ctypes.sizeof(SockaddrHci)) != 0: + raise ConnectionError(ctypes.get_errno(), os.strerror(ctypes.get_errno())) + # pylint: enable=no-member + + fltr = HciRawFilter(0, NG_HCI_EVENT_MASK_LE) + if libc.setsockopt(sock.fileno(), + SOL_HCI_RAW, SOL_HCI_RAW_FILTER, + ctypes.pointer(fltr), ctypes.sizeof(HciRawFilter)) != 0: + raise ConnectionError(ctypes.get_errno(), os.strerror(ctypes.get_errno())) + + return sock + +def send_cmd(sock, group_field, command_field, data): + """Send hci command to device.""" + opcode = (((group_field & 0x3f) << 10) | (command_field & 0x3ff)) + sock.send(struct.pack('".format( + name=self.name, temperature=self.temperature, + humidity=self.humidity, light=self.light) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/eddystone.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/eddystone.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/eddystone.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/eddystone.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,149 @@ +"""Packet classes for Eddystone beacons.""" +from binascii import hexlify +from ..const import EDDYSTONE_URL_SCHEMES, EDDYSTONE_TLD_ENCODINGS +from ..utils import data_to_hexstring, data_to_binstring + +class EddystoneUIDFrame(object): + """Eddystone UID frame.""" + + def __init__(self, data): + self._tx_power = data['tx_power'] + self._namespace = data_to_hexstring(data['namespace']) + self._instance = data_to_hexstring(data['instance']) + + @property + def tx_power(self): + """Calibrated Tx power at 0 m.""" + return self._tx_power + + @property + def namespace(self): + """10-byte namespace identifier.""" + return self._namespace + + @property + def instance(self): + """6-byte instance identifier.""" + return self._instance + + @property + def properties(self): + """Get beacon properties.""" + return {'namespace': self.namespace, 'instance': self.instance} + + def __str__(self): + return "EddystoneUIDFrame" \ + % (self.tx_power, self.namespace, self.instance) + + +class EddystoneURLFrame(object): + """Eddystone URL frame.""" + + def __init__(self, data): + self._tx_power = data['tx_power'] + url_scheme = EDDYSTONE_URL_SCHEMES[data['url_scheme']] + url = data['url'] + + # Replace url encodings with their expanded version + for enc, tld in EDDYSTONE_TLD_ENCODINGS.items(): + url = url.replace(chr(enc), tld) + + self._url = url_scheme + url + + @property + def tx_power(self): + """Calibrated Tx power at 0 m.""" + return self._tx_power + + @property + def url(self): + """Transmitted URL.""" + return self._url + + def __str__(self): + return "EddystoneURLFrame" \ + % (self.tx_power, self.url) + + +class EddystoneEncryptedTLMFrame(object): + """Eddystone encrypted TLM frame.""" + + def __init__(self, data): + self._encrypted_data = data_to_binstring(data['encrypted_data']) + self._salt = data['salt'] + self._mic = data['mic'] + + @property + def encrypted_data(self): + """Encrypted TLM data.""" + return self._encrypted_data + + @property + def salt(self): + """16-bit salt.""" + return self._salt + + @property + def mic(self): + """16-bit message integrity check.""" + return self._mic + + def __str__(self): + return "EddystoneEncryptedTLMFrame" \ + % (hexlify(self.encrypted_data), self.salt, self.mic) + + +class EddystoneTLMFrame(object): + """Eddystone TLM frame.""" + + def __init__(self, data): + self._voltage = data['voltage'] + self._temperature = data['temperature'] / float(256) + self._advertising_count = data['advertising_count'] + self._seconds_since_boot = data['seconds_since_boot'] + + @property + def voltage(self): + """Battery voltage measured in mV.""" + return self._voltage + + @property + def temperature(self): + """Temperature in degree Celsius.""" + return self._temperature + + @property + def advertising_count(self): + """Advertising PDU count.""" + return self._advertising_count + + @property + def seconds_since_boot(self): + """Time since power-on or reboot.""" + return self._seconds_since_boot + + def __str__(self): + return "EddystoneTLMFrame" % (self.voltage, self.temperature, \ + self.advertising_count, self.seconds_since_boot) + +class EddystoneEIDFrame(object): + """Eddystone EID frame.""" + + def __init__(self, data): + self._tx_power = data['tx_power'] + self._eid = data_to_binstring(data['eid']) + + @property + def tx_power(self): + """Calibrated Tx power at 0 m.""" + return self._tx_power + + @property + def eid(self): + """8-byte Ephemeral Identifier.""" + return self._eid + + def __str__(self): + return "EddystoneEIDFrame" \ + % (self.tx_power, hexlify(self.eid)) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/estimote.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/estimote.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/estimote.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/estimote.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,288 @@ +"""Packet classes for Estimote beacons.""" +from ..utils import data_to_hexstring + +class EstimoteTelemetryFrameA(object): + """Estimote telemetry subframe A.""" + + def __init__(self, data, protocol_version): + self._protocol_version = protocol_version + self._identifier = data_to_hexstring(data['identifier']) + sub = data['sub_frame'] + # acceleration: convert to tuple and normalize + self._acceleration = tuple([v * 2 / 127.0 for v in sub['acceleration']]) + # motion states + self._previous_motion_state = self.parse_motion_state(sub['previous_motion']) + self._current_motion_state = self.parse_motion_state(sub['current_motion']) + self._is_moving = (sub['combined_fields'][0] & 0b00000011) == 1 + # gpio + states = [] + for i in range(4): + states.append((sub['combined_fields'][0] & (1 << (4+i))) != 0) + self._gpio_states = tuple(states) + # error codes + if self.protocol_version == 2: + self._has_firmware_error = ((sub['combined_fields'][0] & 0b00000100) >> 2) == 1 + self._has_clock_error = ((sub['combined_fields'][0] & 0b00001000) >> 3) == 1 + elif self.protocol_version == 1: + self._has_firmware_error = (sub['combined_fields'][1] & 0b00000001) == 1 + self._has_clock_error = ((sub['combined_fields'][1] & 0b00000010) >> 1) == 1 + else: + self._has_firmware_error = None + self._has_clock_error = None + # pressure + if self.protocol_version == 2: + self._pressure = sub['combined_fields'][1] | \ + sub['combined_fields'][2] << 8 | \ + sub['combined_fields'][3] << 16 | \ + sub['combined_fields'][4] << 24 + if self._pressure == 0xffffffff: + self._pressure = None + else: + self._pressure /= 256.0 + else: + self._pressure = None + + @staticmethod + def parse_motion_state(val): + """Convert motion state byte to seconds.""" + number = val & 0b00111111 + unit = (val & 0b11000000) >> 6 + if unit == 1: + number *= 60 # minutes + elif unit == 2: + number *= 60 * 60 # hours + elif unit == 3 and number < 32: + number *= 60 * 60 * 24 # days + elif unit == 3: + number -= 32 + number *= 60 * 60 * 24 * 7 # weeks + return number + + @property + def protocol_version(self): + """Protocol version of the packet.""" + return self._protocol_version + + @property + def identifier(self): + """First half of the identifier of the beacon (8 bytes).""" + return self._identifier + + @property + def acceleration(self): + """Tuple of acceleration values for (X, Y, Z) axis, in g.""" + return self._acceleration + + @property + def is_moving(self): + """Whether the beacon is in motion at the moment (Bool)""" + return self._is_moving + + @property + def current_motion_state(self): + """Duration of current motion state in seconds. + E.g., if is_moving is True, this states how long the beacon is beeing moved already and + previous_motion_state will tell how long it has been still before.""" + return self._current_motion_state + + + @property + def previous_motion_state(self): + """Duration of previous motion state in seconds (see current_motion_state).""" + return self._previous_motion_state + + @property + def gpio_states(self): + """Tuple with state of the GPIO pins 0-3 (True is high, False is low).""" + return self._gpio_states + + @property + def has_firmware_error(self): + """If beacon has a firmware problem. + Only available if protocol version > 0, None otherwise.""" + return self._has_firmware_error + + @property + def has_clock_error(self): + """If beacon has a clock problem. Only available if protocol version > 0, None otherwise.""" + return self._has_clock_error + + @property + def pressure(self): + """Atmosperic pressure in Pascal. None if all bits are set. + Only available if protocol version is 2, None otherwise .""" + return self._pressure + + @property + def properties(self): + """Get beacon properties.""" + return {'identifier': self.identifier, 'protocol_version': self.protocol_version} + + def __str__(self): + return "EstimoteTelemetryFrameA" \ + % (self.identifier, self.protocol_version) + + +class EstimoteTelemetryFrameB(object): + """Estimote telemetry subframe B.""" + + def __init__(self, data, protocol_version): + self._protocol_version = protocol_version + self._identifier = data_to_hexstring(data['identifier']) + sub = data['sub_frame'] + # magnetic field: convert to tuple and normalize + if sub['magnetic_field'] == [-1, -1, -1]: + self._magnetic_field = None + else: + self._magnetic_field = tuple([v / 128.0 for v in sub['magnetic_field']]) + # ambient light + ambient_upper = (sub['ambient_light'] & 0b11110000) >> 4 + ambient_lower = sub['ambient_light'] & 0b00001111 + if ambient_upper == 0xf and ambient_lower == 0xf: + self._ambient_light = None + else: + self._ambient_light = pow(2, ambient_upper) * ambient_lower * 0.72 + # uptime + uptime_unit_code = (sub['combined_fields'][1] & 0b00110000) >> 4 + uptime_number = ((sub['combined_fields'][1] & 0b00001111) << 8) | \ + sub['combined_fields'][0] + if uptime_unit_code == 1: + uptime_number *= 60 # minutes + elif uptime_unit_code == 2: + uptime_number *= 60 * 60 # hours + elif uptime_unit_code == 3: + uptime_number *= 60 * 60 * 24 # days + else: + uptime_number = 0 + self._uptime = uptime_number + # temperature + temperature = ((sub['combined_fields'][3] & 0b00000011) << 10) | \ + (sub['combined_fields'][2] << 2) | \ + ((sub['combined_fields'][1] & 0b11000000) >> 6) + temperature = temperature - 4096 if temperature > 2047 else temperature + self._temperature = temperature / 16.0 + # battery voltage + voltage = (sub['combined_fields'][4] << 6) | \ + ((sub['combined_fields'][3] & 0b11111100) >> 2) + self._voltage = None if voltage == 0b11111111111111 else voltage + if self._protocol_version == 0: + # errors (only protocol ver 0) + self._has_firmware_error = (sub['battery_level'] & 0b00000001) == 1 + self._has_clock_error = (sub['battery_level'] & 0b00000010) == 0b10 + self._battery_level = None + else: + self._battery_level = None if sub['battery_level'] == 0xFF else sub['battery_level'] + self._has_clock_error = None + self._has_firmware_error = None + + + @property + def protocol_version(self): + """Protocol version of the packet.""" + return self._protocol_version + + @property + def identifier(self): + """First half of the identifier of the beacon (8 bytes).""" + return self._identifier + + @property + def magnetic_field(self): + """Tuple of magnetic field values for (X, Y, Z) axis. + Between -1 and 1 or None if all bits are set.""" + return self._magnetic_field + + @property + def ambient_light(self): + """Ambient light in lux.""" + return self._ambient_light + + @property + def uptime(self): + """Uptime in seconds.""" + return self._uptime + + @property + def temperature(self): + """Ambient temperature in celsius.""" + return self._temperature + + @property + def has_firmware_error(self): + """Whether beacon has a firmware problem. + Only available if protocol version is 0, None otherwise.""" + return self._has_firmware_error + + @property + def has_clock_error(self): + """Whether beacon has a clock problem. + Only available if protocol version is 0, None otherwise.""" + return self._has_clock_error + + @property + def battery_level(self): + """Beacon battery level between 0 and 100. + None if protocol version is 0 or not measured yet.""" + return self._battery_level + + @property + def properties(self): + """Get beacon properties.""" + return {'identifier': self.identifier, 'protocol_version': self.protocol_version} + + def __str__(self): + return "EstimoteTelemetryFrameB" \ + % (self.identifier, self.protocol_version) + + +class EstimoteNearable(object): + """Estimote Nearable advertisement.""" + + def __init__(self, data): + self._identifier = data_to_hexstring(data['identifier']) + self._hardware_version = data['hardware_version'] + self._firmware_version = data['firmware_version'] + + # byte 13 and the first 4 bits of byte 14 is the temperature in signed, + temperature_raw_value = (data['temperature'] & 0x0fff) + if temperature_raw_value > 2047: + # convert a 12-bit unsigned integer to a signed one + temperature_raw_value = temperature_raw_value - 4096 + temperature = temperature_raw_value / 16.0 + self._temperature = temperature + self._is_moving = data['is_moving'] & 0b01000000 != 0 + + @property + def identifier(self): + """The Nearable identifier (8 bytes).""" + return self._identifier + + @property + def hardware_version(self): + """The hardware version of the nearable.""" + return self._hardware_version + + @property + def firmware_version(self): + """The firmware version of the nearable.""" + return self._firmware_version + + @property + def temperature(self): + """The temperature reading taken by the nearable.""" + return self._temperature + + @property + def is_moving(self): + """Whether the beacon is in motion at the moment.""" + return self._is_moving + + @property + def properties(self): + """Get beacon properties.""" + return {'identifier': self.identifier, 'temperature': self.temperature, + 'is_moving': self._is_moving} + + def __str__(self): + return "EstimoteNearable" \ + % self.identifier diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/exposure_notification.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/exposure_notification.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/exposure_notification.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/exposure_notification.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,27 @@ +"""Packet classes for Eddystone beacons.""" +from ..utils import data_to_hexstring, data_to_binstring + +class ExposureNotificationFrame(object): + """COVID-19 Exposure Notification frame.""" + + def __init__(self, data): + self._identifier = data_to_hexstring(data['identifier']) + self._encrypted_metadata = data_to_binstring(data['encrypted_metadata']) + + @property + def identifier(self): + """16 byte Rolling Proximity Identifier""" + return self._identifier + + @property + def encrypted_metadata(self): + """4 byte encrypted data containing version info and transmission power""" + return self._encrypted_metadata + + @property + def properties(self): + """Get beacon properties.""" + return {'identifier': self.identifier, 'encrypted_metadata' : self.encrypted_metadata} + + def __str__(self): + return "ExposureNotificationFrame" % (self.identifier) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/ibeacon.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/ibeacon.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/ibeacon.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/ibeacon.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,50 @@ +"""Packet classes for iBeacon beacons.""" +from ..utils import data_to_uuid + +class IBeaconAdvertisement(object): + """iBeacon advertisement.""" + + def __init__(self, data): + self._uuid = data_to_uuid(data['uuid']) + self._major = data['major'] + self._minor = data['minor'] + self._tx_power = data['tx_power'] + + @property + def tx_power(self): + """Calibrated Tx power at 0 m.""" + return self._tx_power + + @property + def uuid(self): + """16-byte uuid.""" + return self._uuid + + @property + def major(self): + """2-byte major identifier.""" + return self._major + + @property + def minor(self): + """2-byte minor identifier.""" + return self._minor + + @property + def cypress_temperature(self): + """Cypress iBeacon Sensor temperature in C.""" + return 175.72*((self._minor & 0xff)*256)/65536 - 46.85 + + @property + def cypress_humidity(self): + """Cypress iBeacon Sensor humidity RH%.""" + return 125.0*(self._minor & 0xff00)/65536 - 6 + + @property + def properties(self): + """Get beacon properties.""" + return {'uuid': self.uuid, 'major': self.major, 'minor': self.minor} + + def __str__(self): + return "IBeaconAdvertisement" \ + % (self.tx_power, self.uuid, self.major, self.minor) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/__init__.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/__init__.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/packet_types/__init__.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,7 @@ +"""Packets supported by the parser.""" +from .eddystone import EddystoneUIDFrame, EddystoneURLFrame, EddystoneEncryptedTLMFrame, \ + EddystoneTLMFrame, EddystoneEIDFrame +from .ibeacon import IBeaconAdvertisement +from .estimote import EstimoteTelemetryFrameA, EstimoteTelemetryFrameB, EstimoteNearable +from .controlj import CJMonitorAdvertisement +from .exposure_notification import ExposureNotificationFrame diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/parser.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/parser.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/parser.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/parser.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,85 @@ +"""Beacon advertisement parser.""" +from checkbox_support.vendor.construct import ConstructError + +from .structs import LTVFrame +from .packet_types import EddystoneUIDFrame, EddystoneURLFrame, EddystoneEncryptedTLMFrame, \ + EddystoneTLMFrame, EddystoneEIDFrame, IBeaconAdvertisement, \ + EstimoteTelemetryFrameA, EstimoteTelemetryFrameB, EstimoteNearable, \ + CJMonitorAdvertisement, ExposureNotificationFrame +from .const import EDDYSTONE_TLM_UNENCRYPTED, EDDYSTONE_TLM_ENCRYPTED, SERVICE_DATA_TYPE, \ + EDDYSTONE_UID_FRAME, EDDYSTONE_TLM_FRAME, EDDYSTONE_URL_FRAME, \ + EDDYSTONE_EID_FRAME, EDDYSTONE_UUID, ESTIMOTE_UUID, ESTIMOTE_TELEMETRY_FRAME, \ + ESTIMOTE_TELEMETRY_SUBFRAME_A, ESTIMOTE_TELEMETRY_SUBFRAME_B, \ + MANUFACTURER_SPECIFIC_DATA_TYPE, ESTIMOTE_MANUFACTURER_ID, CJ_MANUFACTURER_ID, \ + IBEACON_MANUFACTURER_ID, EXPOSURE_NOTIFICATION_UUID + +# pylint: disable=invalid-name,too-many-return-statements + +def parse_packet(packet): + """Parse a beacon advertisement packet.""" + return parse_ltv_packet(packet) + +def parse_ltv_packet(packet): + """Parse a tag-length-value style beacon packet.""" + try: + frame = LTVFrame.parse(packet) + + for ltv in frame: + if ltv['type'] == SERVICE_DATA_TYPE: + data = ltv['value'] + + if data["service_identifier"] == EDDYSTONE_UUID: + return parse_eddystone_service_data(data['service_data']) + + elif data["service_identifier"] == ESTIMOTE_UUID: + return parse_estimote_service_data(data['service_data']) + + elif data["service_identifier"] == EXPOSURE_NOTIFICATION_UUID: + return ExposureNotificationFrame(data["service_data"]) + + + elif ltv['type'] == MANUFACTURER_SPECIFIC_DATA_TYPE: + data = ltv["value"] + + if data["company_identifier"] == ESTIMOTE_MANUFACTURER_ID: + return EstimoteNearable(data['data']) + + elif data["company_identifier"] == CJ_MANUFACTURER_ID: + return CJMonitorAdvertisement(frame) + + elif data["company_identifier"] == IBEACON_MANUFACTURER_ID: + return IBeaconAdvertisement(data['data']) + + except ConstructError: + return None + + return None + +def parse_eddystone_service_data(data): + """Parse Eddystone service data.""" + if data['frame_type'] == EDDYSTONE_UID_FRAME: + return EddystoneUIDFrame(data['frame']) + + elif data['frame_type'] == EDDYSTONE_TLM_FRAME: + if data['frame']['tlm_version'] == EDDYSTONE_TLM_ENCRYPTED: + return EddystoneEncryptedTLMFrame(data['frame']['data']) + elif data['frame']['tlm_version'] == EDDYSTONE_TLM_UNENCRYPTED: + return EddystoneTLMFrame(data['frame']['data']) + + elif data['frame_type'] == EDDYSTONE_URL_FRAME: + return EddystoneURLFrame(data['frame']) + + elif data['frame_type'] == EDDYSTONE_EID_FRAME: + return EddystoneEIDFrame(data['frame']) + else: + return None + +def parse_estimote_service_data(data): + """Parse Estimote service data.""" + if data['frame_type'] & 0xF == ESTIMOTE_TELEMETRY_FRAME: + protocol_version = (data['frame_type'] & 0xF0) >> 4 + if data['frame']['subframe_type'] == ESTIMOTE_TELEMETRY_SUBFRAME_A: + return EstimoteTelemetryFrameA(data['frame'], protocol_version) + elif data['frame']['subframe_type'] == ESTIMOTE_TELEMETRY_SUBFRAME_B: + return EstimoteTelemetryFrameB(data['frame'], protocol_version) + return None diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/scanner.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/scanner.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/scanner.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/beacontools_2_0_2/scanner.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,261 @@ +"""Classes responsible for Beacon scanning.""" +import logging +import struct +import threading +from importlib import import_module + +from checkbox_support.vendor.ahocorapy.keywordtree import KeywordTree + +from .const import (CJ_MANUFACTURER_ID, EDDYSTONE_UUID, + ESTIMOTE_MANUFACTURER_ID, ESTIMOTE_UUID, + EVT_LE_ADVERTISING_REPORT, EXPOSURE_NOTIFICATION_UUID, + IBEACON_MANUFACTURER_ID, IBEACON_PROXIMITY_TYPE, + LE_META_EVENT, MANUFACTURER_SPECIFIC_DATA_TYPE, + MS_FRACTION_DIVIDER, OCF_LE_SET_SCAN_ENABLE, + OCF_LE_SET_SCAN_PARAMETERS, OGF_LE_CTL, + BluetoothAddressType, ScanFilter, ScannerMode, ScanType) +from .device_filters import BtAddrFilter, DeviceFilter +from .packet_types import (EddystoneEIDFrame, EddystoneEncryptedTLMFrame, + EddystoneTLMFrame, EddystoneUIDFrame, + EddystoneURLFrame) +from .parser import parse_packet +from .utils import (bin_to_int, bt_addr_to_string, get_mode, is_one_of, + is_packet_type, to_int) + +_LOGGER = logging.getLogger(__name__) +_LOGGER.setLevel(logging.DEBUG) + +# pylint: disable=no-member,too-many-arguments + + +class BeaconScanner(object): + """Scan for Beacon advertisements.""" + + def __init__(self, callback, bt_device_id=0, device_filter=None, packet_filter=None, scan_parameters=None): + """Initialize scanner.""" + # check if device filters are valid + if device_filter is not None: + if not isinstance(device_filter, list): + device_filter = [device_filter] + if len(device_filter) > 0: + for filtr in device_filter: + if not isinstance(filtr, DeviceFilter): + raise ValueError("Device filters must be instances of DeviceFilter") + else: + device_filter = None + + # check if packet filters are valid + if packet_filter is not None: + if not isinstance(packet_filter, list): + packet_filter = [packet_filter] + if len(packet_filter) > 0: + for filtr in packet_filter: + if not is_packet_type(filtr): + raise ValueError("Packet filters must be one of the packet types") + else: + packet_filter = None + + if scan_parameters is None: + scan_parameters = {} + + self._mon = Monitor(callback, bt_device_id, device_filter, packet_filter, scan_parameters) + + def start(self): + """Start beacon scanning.""" + self._mon.start() + + def stop(self): + """Stop beacon scanning.""" + self._mon.terminate() + + +class Monitor(threading.Thread): + """Continously scan for BLE advertisements.""" + + def __init__(self, callback, bt_device_id, device_filter, packet_filter, scan_parameters): + """Construct interface object.""" + # do import here so that the package can be used in parsing-only mode (no bluez required) + self.backend = import_module('checkbox_support.vendor.beacontools_2_0_2.backend') + + threading.Thread.__init__(self) + self.daemon = False + self.keep_going = True + self.callback = callback + + # number of the bt device (hciX) + self.bt_device_id = bt_device_id + # list of beacons to monitor + self.device_filter = device_filter + self.mode = get_mode(device_filter) + # list of packet types to monitor + self.packet_filter = packet_filter + # bluetooth socket + self.socket = None + # keep track of Eddystone Beacon <-> bt addr mapping + self.eddystone_mappings = [] + # parameters to pass to bt device + self.scan_parameters = scan_parameters + + # construct an aho-corasick search tree for efficient prefiltering + service_uuid_prefix = b"\x03\x03" + self.kwtree = KeywordTree() + if self.mode & ScannerMode.MODE_IBEACON: + self.kwtree.add(bytes([MANUFACTURER_SPECIFIC_DATA_TYPE]) + IBEACON_MANUFACTURER_ID + IBEACON_PROXIMITY_TYPE) + if self.mode & ScannerMode.MODE_EDDYSTONE: + self.kwtree.add(service_uuid_prefix + EDDYSTONE_UUID) + if self.mode & ScannerMode.MODE_ESTIMOTE: + self.kwtree.add(service_uuid_prefix + ESTIMOTE_UUID) + self.kwtree.add(bytes([MANUFACTURER_SPECIFIC_DATA_TYPE]) + ESTIMOTE_MANUFACTURER_ID) + if self.mode & ScannerMode.MODE_CJMONITOR: + self.kwtree.add(bytes([MANUFACTURER_SPECIFIC_DATA_TYPE]) + CJ_MANUFACTURER_ID) + if self.mode & ScannerMode.MODE_EXPOSURE_NOTIFICATION: + self.kwtree.add(service_uuid_prefix + EXPOSURE_NOTIFICATION_UUID) + self.kwtree.finalize() + + def run(self): + """Continously scan for BLE advertisements.""" + self.socket = self.backend.open_dev(self.bt_device_id) + + self.set_scan_parameters(**self.scan_parameters) + self.toggle_scan(True) + + while self.keep_going: + pkt = self.socket.recv(255) + event = to_int(pkt[1]) + subevent = to_int(pkt[3]) + if event == LE_META_EVENT and subevent == EVT_LE_ADVERTISING_REPORT: + # we have an BLE advertisement + self.process_packet(pkt) + self.socket.close() + + def set_scan_parameters(self, scan_type=ScanType.ACTIVE, interval_ms=10, window_ms=10, + address_type=BluetoothAddressType.RANDOM, filter_type=ScanFilter.ALL): + """"sets the le scan parameters + + Args: + scan_type: ScanType.(PASSIVE|ACTIVE) + interval: ms (as float) between scans (valid range 2.5ms - 10240ms) + ..note:: when interval and window are equal, the scan + runs continuos + window: ms (as float) scan duration (valid range 2.5ms - 10240ms) + address_type: Bluetooth address type BluetoothAddressType.(PUBLIC|RANDOM) + * PUBLIC = use device MAC address + * RANDOM = generate a random MAC address and use that + filter: ScanFilter.(ALL|WHITELIST_ONLY) only ALL is supported, which will + return all fetched bluetooth packets (WHITELIST_ONLY is not supported, + because OCF_LE_ADD_DEVICE_TO_WHITE_LIST command is not implemented) + + Raises: + ValueError: A value had an unexpected format or was not in range + """ + interval_fractions = interval_ms / MS_FRACTION_DIVIDER + if interval_fractions < 0x0004 or interval_fractions > 0x4000: + raise ValueError( + "Invalid interval given {}, must be in range of 2.5ms to 10240ms!".format( + interval_fractions)) + window_fractions = window_ms / MS_FRACTION_DIVIDER + if window_fractions < 0x0004 or window_fractions > 0x4000: + raise ValueError( + "Invalid window given {}, must be in range of 2.5ms to 10240ms!".format( + window_fractions)) + + interval_fractions, window_fractions = int(interval_fractions), int(window_fractions) + + scan_parameter_pkg = struct.pack( + "> 4) + 5 + return ((1 << position) | ((mudata & 0xF) << (position - 4)) | (1 << (position - 5))) - 33 + +def bt_addr_to_string(addr): + """Convert a binary string to the hex representation.""" + addr_str = array.array('B', addr) + addr_str.reverse() + hex_str = hexlify(addr_str.tobytes()).decode('ascii') + # insert ":" seperator between the bytes + return ':'.join(a+b for a, b in zip(hex_str[::2], hex_str[1::2])) + + +def is_one_of(obj, types): + """Return true iff obj is an instance of one of the types.""" + for type_ in types: + if isinstance(obj, type_): + return True + return False + + +def is_packet_type(cls): + """Check if class is one the packet types.""" + # pylint: disable=import-outside-toplevel + from .packet_types import EddystoneUIDFrame, EddystoneURLFrame, \ + EddystoneEncryptedTLMFrame, EddystoneTLMFrame, \ + EddystoneEIDFrame, IBeaconAdvertisement, \ + EstimoteTelemetryFrameA, EstimoteTelemetryFrameB, \ + ExposureNotificationFrame + # pylint: enable=import-outside-toplevel + + return (cls in [EddystoneURLFrame, EddystoneUIDFrame, EddystoneEncryptedTLMFrame, \ + EddystoneTLMFrame, EddystoneEIDFrame, IBeaconAdvertisement, \ + EstimoteTelemetryFrameA, EstimoteTelemetryFrameB, \ + ExposureNotificationFrame]) + + +def to_int(string): + """Convert a one element byte string to int for python 2 support.""" + if isinstance(string, str): + return ord(string[0]) + else: + return string + + +def bin_to_int(string): + """Convert a one element byte string to signed int for python 2 support.""" + if isinstance(string, str): + return struct.unpack("b", string)[0] + else: + return struct.unpack("b", bytes([string]))[0] + + +def get_mode(device_filter): + """Determine which beacons the scanner should look for.""" + from .device_filters import IBeaconFilter, EddystoneFilter, BtAddrFilter, EstimoteFilter, \ + CJMonitorFilter, ExposureNotificationFilter # pylint: disable=import-outside-toplevel + + if device_filter is None or len(device_filter) == 0: + return ScannerMode.MODE_ALL + + mode = ScannerMode.MODE_NONE + for filtr in device_filter: + if isinstance(filtr, IBeaconFilter): + mode |= ScannerMode.MODE_IBEACON + elif isinstance(filtr, EddystoneFilter): + mode |= ScannerMode.MODE_EDDYSTONE + elif isinstance(filtr, EstimoteFilter): + mode |= ScannerMode.MODE_ESTIMOTE + elif isinstance(filtr, CJMonitorFilter): + mode |= ScannerMode.MODE_CJMONITOR + elif isinstance(filtr, ExposureNotificationFilter): + mode |= ScannerMode.MODE_EXPOSURE_NOTIFICATION + elif isinstance(filtr, BtAddrFilter): + mode |= ScannerMode.MODE_ALL + break + + return mode diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/core.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/core.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/core.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/core.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,5730 @@ +# -*- coding: utf-8 -*- + +import struct, io, binascii, itertools, collections, pickle, sys, os, tempfile, hashlib, importlib, imp + +from checkbox_support.vendor.construct.lib import * +from checkbox_support.vendor.construct.expr import * +from checkbox_support.vendor.construct.version import * + + +#=============================================================================== +# exceptions +#=============================================================================== +class ConstructError(Exception): + def __init__(self, message='', path=None): + self.path = path + if path is None: + super(ConstructError, self).__init__(message) + else: + message = "Error in path {}\n".format(path) + message + super(ConstructError, self).__init__(message) +class SizeofError(ConstructError): + pass +class AdaptationError(ConstructError): + pass +class ValidationError(ConstructError): + pass +class StreamError(ConstructError): + pass +class FormatFieldError(ConstructError): + pass +class IntegerError(ConstructError): + pass +class StringError(ConstructError): + pass +class MappingError(ConstructError): + pass +class RangeError(ConstructError): + pass +class RepeatError(ConstructError): + pass +class ConstError(ConstructError): + pass +class IndexFieldError(ConstructError): + pass +class CheckError(ConstructError): + pass +class ExplicitError(ConstructError): + pass +class NamedTupleError(ConstructError): + pass +class TimestampError(ConstructError): + pass +class UnionError(ConstructError): + pass +class SelectError(ConstructError): + pass +class SwitchError(ConstructError): + pass +class StopFieldError(ConstructError): + pass +class PaddingError(ConstructError): + pass +class TerminatedError(ConstructError): + pass +class RawCopyError(ConstructError): + pass +class RotationError(ConstructError): + pass +class ChecksumError(ConstructError): + pass +class CancelParsing(ConstructError): + pass + + +#=============================================================================== +# used internally +#=============================================================================== +def singleton(arg): + x = arg() + x.__reduce__ = lambda: arg.__name__ + return x + + +def stream_read(stream, length, path): + if length < 0: + raise StreamError("length must be non-negative, found %s" % length, path=path) + try: + data = stream.read(length) + except Exception: + raise StreamError("stream.read() failed, requested %s bytes" % (length,), path=path) + if len(data) != length: + raise StreamError("stream read less than specified amount, expected %d, found %d" % (length, len(data)), path=path) + return data + + +def stream_read_entire(stream, path): + try: + return stream.read() + except Exception: + raise StreamError("stream.read() failed when reading until EOF", path=path) + + +def stream_write(stream, data, length, path): + if not isinstance(data, bytestringtype): + raise StringError("given non-bytes value, perhaps unicode? %r" % (data,), path=path) + if length < 0: + raise StreamError("length must be non-negative, found %s" % length, path=path) + if len(data) != length: + raise StreamError("bytes object of wrong length, expected %d, found %d" % (length, len(data)), path=path) + try: + written = stream.write(data) + except Exception: + raise StreamError("stream.write() failed, given %r" % (data,), path=path) + if written != length: + raise StreamError("stream written less than specified, expected %d, written %d" % (length, written), path=path) + + +def stream_seek(stream, offset, whence, path): + try: + return stream.seek(offset, whence) + except Exception: + raise StreamError("stream.seek() failed, offset %s, whence %s" % (offset, whence), path=path) + + +def stream_tell(stream, path): + try: + return stream.tell() + except Exception: + raise StreamError("stream.tell() failed", path=path) + + +def stream_size(stream): + fallback = stream.tell() + end = stream.seek(0, 2) + stream.seek(fallback) + return end + + +def stream_iseof(stream): + fallback = stream.tell() + data = stream.read(1) + stream.seek(fallback) + return not data + + +class CodeGen: + def __init__(self): + self.blocks = [] + self.nextid = 0 + self.parsercache = {} + self.linkedinstances = {} + self.linkedparsers = {} + + def allocateId(self): + self.nextid += 1 + return self.nextid + + def append(self, block): + block = [s for s in block.splitlines() if s.strip()] + firstline = block[0] + trim = len(firstline) - len(firstline.lstrip()) + block = "\n".join(s[trim:] for s in block) + if block not in self.blocks: + self.blocks.append(block) + + def toString(self): + return "\n".join(self.blocks + [""]) + + +class KsyGen: + def __init__(self): + self.instances = {} + self.enums = {} + self.types = {} + self.nextid = 0 + + def allocateId(self): + self.nextid += 1 + return self.nextid + + +def hyphenatedict(d): + return {k.replace("_","-").rstrip("-"):v for k,v in d.items()} + + +def hyphenatelist(l): + return [hyphenatedict(d) for d in l] + + +def extractfield(sc): + if isinstance(sc, Renamed): + return extractfield(sc.subcon) + return sc + + +def evaluate(param, context): + return param(context) if callable(param) else param + + +def disableif(condition): + return "# " if condition else "pass; " + + +#=============================================================================== +# abstract constructs +#=============================================================================== +class Construct(object): + r""" + The mother of all constructs. + + This object is generally not directly instantiated, and it does not directly implement parsing and building, so it is largely only of interest to subclass implementors. There are also other abstract classes sitting on top of this one. + + The external user API: + + * `parse` + * `parse_stream` + * `parse_file` + * `build` + * `build_stream` + * `build_file` + * `sizeof` + * `compile` + * `benchmark` + + Subclass authors should not override the external methods. Instead, another API is available: + + * `_parse` + * `_build` + * `_sizeof` + * `_actualsize` + * `_emitparse` + * `_emitbuild` + * `__getstate__` + * `__setstate__` + + Attributes and Inheritance: + + All constructs have a name and flags. The name is used for naming struct members and context dictionaries. Note that the name can be a string, or None by default. A single underscore "_" is a reserved name, used as up-level in nested containers. The name should be descriptive, short, and valid as a Python identifier, although these rules are not enforced. The flags specify additional behavioral information about this construct. Flags are used by enclosing constructs to determine a proper course of action. Flags are often inherited from inner subconstructs but that depends on each class. + """ + + def __init__(self): + self.name = None + self.docs = "" + self.flagbuildnone = False + self.parsed = None + + def __repr__(self): + return "<%s%s%s%s>" % (self.__class__.__name__, " "+self.name if self.name else "", " +nonbuild" if self.flagbuildnone else "", " +docs" if self.docs else "", ) + + def __getstate__(self): + attrs = {} + if hasattr(self, "__dict__"): + attrs.update(self.__dict__) + slots = [] + c = self.__class__ + while c is not None: + if hasattr(c, "__slots__"): + slots.extend(c.__slots__) + c = c.__base__ + for name in slots: + if hasattr(self, name): + attrs[name] = getattr(self, name) + return attrs + + def __setstate__(self, attrs): + for name, value in attrs.items(): + setattr(self, name, value) + + def __copy__(self): + self2 = object.__new__(self.__class__) + self2.__setstate__(self, self.__getstate__()) + return self2 + + def parse(self, data, **contextkw): + r""" + Parse an in-memory buffer (often bytes object). Strings, buffers, memoryviews, and other complete buffers can be parsed with this method. + + Whenever data cannot be read, ConstructError or its derivative is raised. This method is NOT ALLOWED to raise any other exceptions although (1) user-defined lambdas can raise arbitrary exceptions which are propagated (2) external libraries like numpy can raise arbitrary exceptions which are propagated (3) some list and dict lookups can raise IndexError and KeyError which are propagated. + + Context entries are passed only as keyword parameters \*\*contextkw. + + :param \*\*contextkw: context entries, usually empty + + :returns: some value, usually based on bytes read from the stream but sometimes it is computed from nothing or from the context dictionary, sometimes its non-deterministic + + :raises ConstructError: raised for any reason + """ + return self.parse_stream(io.BytesIO(data), **contextkw) + + def parse_stream(self, stream, **contextkw): + r""" + Parse a stream. Files, pipes, sockets, and other streaming sources of data are handled by this method. See parse(). + """ + context = Container(**contextkw) + context._parsing = True + context._building = False + context._sizing = False + context._params = context + try: + return self._parsereport(stream, context, "(parsing)") + except CancelParsing: + pass + + def parse_file(self, filename, **contextkw): + r""" + Parse a closed binary file. See parse(). + """ + with io.open(filename, 'rb') as f: + return self.parse_stream(f, **contextkw) + + def _parsereport(self, stream, context, path): + obj = self._parse(stream, context, path) + if self.parsed is not None: + self.parsed(obj, context) + return obj + + def _parse(self, stream, context, path): + """Override in your subclass.""" + raise NotImplementedError + + def build(self, obj, **contextkw): + r""" + Build an object in memory (a bytes object). + + Whenever data cannot be written, ConstructError or its derivative is raised. This method is NOT ALLOWED to raise any other exceptions although (1) user-defined lambdas can raise arbitrary exceptions which are propagated (2) external libraries like numpy can raise arbitrary exceptions which are propagated (3) some list and dict lookups can raise IndexError and KeyError which are propagated. + + Context entries are passed only as keyword parameters \*\*contextkw. + + :param \*\*contextkw: context entries, usually empty + + :returns: bytes + + :raises ConstructError: raised for any reason + """ + stream = io.BytesIO() + self.build_stream(obj, stream, **contextkw) + return stream.getvalue() + + def build_stream(self, obj, stream, **contextkw): + r""" + Build an object directly into a stream. See build(). + """ + context = Container(**contextkw) + context._parsing = False + context._building = True + context._sizing = False + context._params = context + self._build(obj, stream, context, "(building)") + + def build_file(self, obj, filename, **contextkw): + r""" + Build an object into a closed binary file. See build(). + """ + with io.open(filename, 'wb') as f: + self.build_stream(obj, f, **contextkw) + + def _build(self, obj, stream, context, path): + """Override in your subclass.""" + raise NotImplementedError + + def sizeof(self, **contextkw): + r""" + Calculate the size of this object, optionally using a context. + + Some constructs have fixed size (like FormatField), some have variable-size and can determine their size given a context entry (like Bytes(this.otherfield1)), and some cannot determine their size (like VarInt). + + Whenever size cannot be determined, SizeofError is raised. This method is NOT ALLOWED to raise any other exception, even if eg. context dictionary is missing a key, or subcon propagates ConstructError-derivative exception. + + Context entries are passed only as keyword parameters \*\*contextkw. + + :param \*\*contextkw: context entries, usually empty + + :returns: integer if computable, SizeofError otherwise + + :raises SizeofError: size could not be determined in actual context, or is impossible to be determined + """ + context = Container(**contextkw) + context._parsing = False + context._building = False + context._sizing = True + context._params = context + return self._sizeof(context, "(sizeof)") + + def _sizeof(self, context, path): + """Override in your subclass.""" + raise SizeofError(path=path) + + def _actualsize(self, stream, context, path): + return self._sizeof(context, path) + + def compile(self, filename=None): + """ + Transforms a construct into another construct that does same thing (has same parsing and building semantics) but is much faster when parsing. Already compiled instances just compile into itself. + + Optionally, partial source code can be saved to a text file. This is meant only to inspect the generated code, not to import it from external scripts. + + :returns: Compiled instance + """ + + code = CodeGen() + code.append(""" + # generated by Construct, this source is for inspection only! do not import! + + from checkbox_support.vendor.construct import * + from checkbox_support.vendor.construct.lib import * + from io import BytesIO + import struct + import collections + import itertools + + def read_bytes(io, count): + if not count >= 0: raise StreamError + data = io.read(count) + if not len(data) == count: raise StreamError + return data + def restream(data, func): + return func(BytesIO(data)) + def reuse(obj, func): + return func(obj) + + linkedinstances = {} + linkedparsers = {} + + len_ = len + sum_ = sum + min_ = min + max_ = max + abs_ = abs + """) + code.append(""" + def parseall(io, this): + return %s + compiled = Compiled(None, None, parseall) + """ % (self._compileparse(code),)) + source = code.toString() + + if filename: + with open(filename, "wt") as f: + f.write(source) + + modulename = hexlify(hashlib.sha1(source.encode()).digest()).decode() + module = imp.new_module(modulename) + c = compile(source, '', 'exec') + exec(c, module.__dict__) + + module.linkedinstances = code.linkedinstances + module.linkedparsers = code.linkedparsers + compiled = module.compiled + compiled.source = source + compiled.module = module + compiled.modulename = modulename + compiled.defersubcon = self + return compiled + + def _compileinstance(self, code): + """Used internally.""" + if id(self) in code.linkedinstances: + return code.linkedinstances[id(self)] + + code.append(""" + # linkedinstances[%s] is %r + """ % (id(self), self, )) + + field = extractfield(self) + code.linkedinstances[id(self)] = field + code.linkedparsers[id(self)] = field._parse + return "linkedinstances[%s]" % id(self) + + def _compileparse(self, code): + """Used internally.""" + try: + if id(self) in code.parsercache: + return code.parsercache[id(self)] + emitted = self._emitparse(code) + code.parsercache[id(self)] = emitted + return emitted + except NotImplementedError: + self._compileinstance(code) + return "linkedparsers[%s](io, this, '(???)')" % id(self) + + def _compilebuild(self, code): + """Used internally.""" + raise NotImplementedError + + def _emitparse(self, code): + """Override in your subclass.""" + raise NotImplementedError + + def _emitbuild(self, code): + """Override in your subclass.""" + raise NotImplementedError + + def benchmark(self, sampledata, filename=None): + """ + Measures performance of your construct (its parsing and building runtime), both for the original instance and the compiled instance. Uses timeit module, over at min 1 sample, and at max over 1 second time. + + Optionally, results are saved to a text file for later inspection. Otherwise you can print the result string to terminal. + + Also this method checks correctness, by comparing parsing/building results from both instances. + + :param sampledata: bytes, a valid blob parsable by this construct + :param filename: optional, string, source is saved to that file + + :returns: string containing measurements + """ + from timeit import timeit + + try: + parsetime = "failed" + buildtime = "failed" + parsetime2 = "failed" + + sampleobj = self.parse(sampledata) + parsetime = timeit(lambda: self.parse(sampledata), number=1) + runs = min(1000, max(1, int(1./parsetime))) + if runs > 1: + parsetime = timeit(lambda: self.parse(sampledata), number=runs)/runs + parsetime = "{:.10f} sec/call".format(parsetime) + + self.build(sampleobj) + buildtime = timeit(lambda: self.build(sampleobj), number=1) + runs = min(1000, max(1, int(1./buildtime))) + if runs > 1: + buildtime = timeit(lambda: self.build(sampleobj), number=runs)/runs + buildtime = "{:.10f} sec/call".format(buildtime) + + compiled = self.compile() + + obj = compiled.parse(sampledata) + assert sampleobj == obj + parsetime2 = timeit(lambda: compiled.parse(sampledata), number=1) + runs = min(1000, max(1, int(1./parsetime2))) + if runs > 1: + parsetime2 = timeit(lambda: compiled.parse(sampledata), number=runs)/runs + parsetime2 = "{:.10f} sec/call".format(parsetime2) + + except Exception: + pass + + lines = [ + "Timeit measurements:", + "parsing: {}", + "parsing compiled: {}", + "building: {}", + "" + ] + results = "\n".join(lines).format(parsetime, parsetime2, buildtime) + + if filename: + with open(filename, "wt") as f: + f.write(results) + return results + + def export_ksy(self, schemaname="unnamed_schema", filename=None): + from ruamel.yaml import YAML + yaml = YAML() + yaml.default_flow_style = False + output = io.StringIO() + gen = KsyGen() + main = dict(meta=dict(id=schemaname), seq=self._compileseq(gen), instances=gen.instances, enums=gen.enums, types=gen.types) + yaml.dump(main, output) + source = output.getvalue() + + if filename: + with open(filename, "wt") as f: + f.write(source) + return source + + def _compileseq(self, ksy, bitwise=False, recursion=0): + if recursion >= 3: + raise ConstructError("construct does not implement KSY export") + try: + return hyphenatelist(self._emitseq(ksy, bitwise)) + except NotImplementedError: + return [dict(id="x", **self._compilefulltype(ksy, bitwise, recursion+1))] + + def _compileprimitivetype(self, ksy, bitwise=False, recursion=0): + if recursion >= 3: + raise ConstructError("construct does not implement KSY export") + try: + return self._emitprimitivetype(ksy, bitwise) + except NotImplementedError: + name = "type_%s" % ksy.allocateId() + ksy.types[name] = dict(seq=self._compileseq(ksy, bitwise, recursion+1)) + return name + + def _compilefulltype(self, ksy, bitwise=False, recursion=0): + if recursion >= 3: + raise ConstructError("construct does not implement KSY export") + try: + return hyphenatedict(self._emitfulltype(ksy, bitwise)) + except NotImplementedError: + return dict(type=self._compileprimitivetype(ksy, bitwise, recursion+1)) + + def _emitseq(self, ksy, bitwise): + """Override in your subclass.""" + raise NotImplementedError + + def _emitprimitivetype(self, ksy, bitwise): + """Override in your subclass.""" + raise NotImplementedError + + def _emitfulltype(self, ksy, bitwise): + """Override in your subclass.""" + raise NotImplementedError + + def __rtruediv__(self, name): + """ + Used for renaming subcons, usually part of a Struct, like Struct("index" / Byte). + """ + return Renamed(self, newname=name) + + __rdiv__ = __rtruediv__ + + def __mul__(self, other): + """ + Used for adding docstrings and parsed hooks to subcons, like "field" / Byte * "docstring" * processfunc. + """ + if isinstance(other, stringtypes): + return Renamed(self, newdocs=other) + if callable(other): + return Renamed(self, newparsed=other) + raise ConstructError("operator * can only be used with string or lambda") + + def __rmul__(self, other): + """ + Used for adding docstrings and parsed hooks to subcons, like "field" / Byte * "docstring" * processfunc. + """ + if isinstance(other, stringtypes): + return Renamed(self, newdocs=other) + if callable(other): + return Renamed(self, newparsed=other) + raise ConstructError("operator * can only be used with string or lambda") + + def __add__(self, other): + """ + Used for making Struct like ("index"/Byte + "prefix"/Byte). + """ + lhs = self.subcons if isinstance(self, Struct) else [self] + rhs = other.subcons if isinstance(other, Struct) else [other] + return Struct(*(lhs + rhs)) + + def __rshift__(self, other): + """ + Used for making Sequences like (Byte >> Short). + """ + lhs = self.subcons if isinstance(self, Sequence) else [self] + rhs = other.subcons if isinstance(other, Sequence) else [other] + return Sequence(*(lhs + rhs)) + + def __getitem__(self, count): + """ + Used for making Arrays like Byte[5] and Byte[this.count]. + """ + if isinstance(count, slice): + raise ConstructError("subcon[N] syntax can only be used for Arrays, use GreedyRange(subcon) instead?") + if isinstance(count, int) or callable(count): + return Array(count, self) + raise ConstructError("subcon[N] syntax expects integer or context lambda") + + +class Subconstruct(Construct): + r""" + Abstract subconstruct (wraps an inner construct, inheriting its name and flags). Parsing and building is by default deferred to subcon, same as sizeof. + + :param subcon: Construct instance + """ + def __init__(self, subcon): + if not isinstance(subcon, Construct): + raise TypeError("subcon should be a Construct field") + super(Subconstruct, self).__init__() + self.subcon = subcon + self.flagbuildnone = subcon.flagbuildnone + + def __repr__(self): + return "<%s%s%s%s %s>" % (self.__class__.__name__, " "+self.name if self.name else "", " +nonbuild" if self.flagbuildnone else "", " +docs" if self.docs else "", repr(self.subcon), ) + + def _parse(self, stream, context, path): + return self.subcon._parsereport(stream, context, path) + + def _build(self, obj, stream, context, path): + return self.subcon._build(obj, stream, context, path) + + def _sizeof(self, context, path): + return self.subcon._sizeof(context, path) + + +class Adapter(Subconstruct): + r""" + Abstract adapter class. + + Needs to implement `_decode()` for parsing and `_encode()` for building. + + :param subcon: Construct instance + """ + def _parse(self, stream, context, path): + obj = self.subcon._parsereport(stream, context, path) + return self._decode(obj, context, path) + + def _build(self, obj, stream, context, path): + obj2 = self._encode(obj, context, path) + buildret = self.subcon._build(obj2, stream, context, path) + return obj + + def _decode(self, obj, context, path): + raise NotImplementedError + + def _encode(self, obj, context, path): + raise NotImplementedError + + +class SymmetricAdapter(Adapter): + r""" + Abstract adapter class. + + Needs to implement `_decode()` only, for both parsing and building. + + :param subcon: Construct instance + """ + def _encode(self, obj, context, path): + return self._decode(obj, context, path) + + +class Validator(SymmetricAdapter): + r""" + Abstract class that validates a condition on the encoded/decoded object. + + Needs to implement `_validate()` that returns a bool (or a truthy value) + + :param subcon: Construct instance + """ + def _decode(self, obj, context, path): + if not self._validate(obj, context, path): + raise ValidationError("object failed validation: %s" % (obj,), path=path) + return obj + + def _validate(self, obj, context, path): + raise NotImplementedError + + +class Tunnel(Subconstruct): + r""" + Abstract class that allows other constructs to read part of the stream as if they were reading the entire stream. See Prefixed for example. + + Needs to implement `_decode()` for parsing and `_encode()` for building. + """ + def _parse(self, stream, context, path): + data = stream_read_entire(stream, path) # reads entire stream + data = self._decode(data, context, path) + return self.subcon.parse(data, **context) + + def _build(self, obj, stream, context, path): + stream2 = io.BytesIO() + buildret = self.subcon._build(obj, stream2, context, path) + data = stream2.getvalue() + data = self._encode(data, context, path) + stream_write(stream, data, len(data), path) + return obj + + def _sizeof(self, context, path): + raise SizeofError(path=path) + + def _decode(self, data, context, path): + raise NotImplementedError + + def _encode(self, data, context, path): + raise NotImplementedError + + +class Compiled(Construct): + """Used internally.""" + + def __init__(self, source, defersubcon, parsefunc): + super(Compiled, self).__init__() + self.source = source + self.defersubcon = defersubcon + self.parsefunc = parsefunc + + def _parse(self, stream, context, path): + return self.parsefunc(stream, context) + + def _build(self, obj, stream, context, path): + return self.defersubcon._build(obj, stream, context, path) + + def _sizeof(self, context, path): + return self.defersubcon._sizeof(context, path) + + def compile(self, filename=None): + return self + + def benchmark(self, sampledata, filename=None): + return self.defersubcon.benchmark(sampledata, filename) + + +#=============================================================================== +# bytes and bits +#=============================================================================== +class Bytes(Construct): + r""" + Field consisting of a specified number of bytes. + + Parses into a bytes (of given length). Builds into the stream directly (but checks that given object matches specified length). Can also build from an integer for convenience (although BytesInteger should be used instead). Size is the specified length. + + :param length: integer or context lambda + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises StringError: building from non-bytes value, perhaps unicode + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = Bytes(4) + >>> d.parse(b'beef') + b'beef' + >>> d.build(b'beef') + b'beef' + >>> d.build(0) + b'\x00\x00\x00\x00' + >>> d.sizeof() + 4 + + >>> d = Struct( + ... "length" / Int8ub, + ... "data" / Bytes(this.length), + ... ) + >>> d.parse(b"\x04beef") + Container(length=4)(data=b'beef') + >>> d.sizeof() + construct.core.SizeofError: cannot calculate size, key not found in context + """ + + def __init__(self, length): + super(Bytes, self).__init__() + self.length = length + + def _parse(self, stream, context, path): + length = self.length(context) if callable(self.length) else self.length + return stream_read(stream, length, path) + + def _build(self, obj, stream, context, path): + length = self.length(context) if callable(self.length) else self.length + data = integer2bytes(obj, length) if isinstance(obj, int) else obj + stream_write(stream, data, length, path) + return data + + def _sizeof(self, context, path): + try: + return self.length(context) if callable(self.length) else self.length + except (KeyError, AttributeError): + raise SizeofError("cannot calculate size, key not found in context", path=path) + + def _emitparse(self, code): + return "read_bytes(io, %s)" % (self.length,) + + def _emitfulltype(self, ksy, bitwise): + return dict(size=self.length) + + +@singleton +class GreedyBytes(Construct): + r""" + Field consisting of unknown number of bytes. + + Parses the stream to the end. Builds into the stream directly (without checks). Size is undefined. + + :raises StreamError: stream failed when reading until EOF + :raises StringError: building from non-bytes value, perhaps unicode + + Example:: + + >>> GreedyBytes.parse(b"asislight") + b'asislight' + >>> GreedyBytes.build(b"asislight") + b'asislight' + """ + + def _parse(self, stream, context, path): + return stream_read_entire(stream, path) + + def _build(self, obj, stream, context, path): + stream_write(stream, obj, len(obj), path) + return obj + + def _emitparse(self, code): + return "io.read()" + + def _emitfulltype(self, ksy, bitwise): + return dict(size_eos=True) + + +def Bitwise(subcon): + r""" + Converts the stream from bytes to bits, and passes the bitstream to underlying subcon. Bitstream is a stream that contains 8 times as many bytes, and each byte is either \\x00 or \\x01 (in documentation those bytes are called bits). + + Parsing building and size are deferred to subcon, although size gets divided by 8. + + :param subcon: Construct instance, any field that works with bits (like BitsInteger) or is bit-byte agnostic (like Struct or Flag) + + See :class:`~construct.core.Transformed` and :class:`~construct.core.Restreamed` for raisable exceptions. + + Example:: + + >>> d = Bitwise(Struct( + ... 'a' / Nibble, + ... 'b' / Bytewise(Float32b), + ... 'c' / Padding(4), + ... )) + >>> d.parse(bytes(5)) + Container(a=0)(b=0.0)(c=None) + >>> d.sizeof() + 5 + """ + + try: + size = subcon.sizeof() + macro = Transformed(subcon, bytes2bits, size//8, bits2bytes, size//8) + except SizeofError: + macro = Restreamed(subcon, bytes2bits, 1, bits2bytes, 8, lambda n: n//8) + def _emitseq(ksy, bitwise): + return subcon._compileseq(ksy, bitwise=True) + def _emitprimitivetype(ksy, bitwise): + return subcon._compileprimitivetype(ksy, bitwise=True) + def _emitfulltype(ksy, bitwise): + return subcon._compilefulltype(ksy, bitwise=True) + macro._emitseq = _emitseq + macro._emitprimitivetype = _emitprimitivetype + macro._emitfulltype = _emitfulltype + return macro + + +def Bytewise(subcon): + r""" + Converts the bitstream back to normal byte stream. Must be used within :class:`~construct.core.Bitwise`. + + Parsing building and size are deferred to subcon, although size gets multiplied by 8. + + :param subcon: Construct instance, any field that works with bytes or is bit-byte agnostic + + See :class:`~construct.core.Transformed` and :class:`~construct.core.Restreamed` for raisable exceptions. + + Example:: + + >>> d = Bitwise(Struct( + ... 'a' / Nibble, + ... 'b' / Bytewise(Float32b), + ... 'c' / Padding(4), + ... )) + >>> d.parse(bytes(5)) + Container(a=0)(b=0.0)(c=None) + >>> d.sizeof() + 5 + """ + + try: + size = subcon.sizeof() + macro = Transformed(subcon, bits2bytes, size*8, bytes2bits, size*8) + except SizeofError: + macro = Restreamed(subcon, bits2bytes, 8, bytes2bits, 1, lambda n: n*8) + def _emitseq(ksy, bitwise): + return subcon._compileseq(ksy, bitwise=False) + def _emitprimitivetype(ksy, bitwise): + return subcon._compileprimitivetype(ksy, bitwise=False) + def _emitfulltype(ksy, bitwise): + return subcon._compilefulltype(ksy, bitwise=False) + macro._emitseq = _emitseq + macro._emitprimitivetype = _emitprimitivetype + macro._emitfulltype = _emitfulltype + return macro + + +#=============================================================================== +# integers and floats +#=============================================================================== +class FormatField(Construct): + r""" + Field that uses `struct` module to pack and unpack CPU-sized integers and floats. This is used to implement most Int* Float* fields, but for example cannot pack 24-bit integers, which is left to :class:`~construct.core.BytesInteger` class. + + See `struct module `_ documentation for instructions on crafting format strings. + + Parses into an integer. Builds from an integer into specified byte count and endianness. Size is determined by `struct` module according to specified format string. + + :param endianity: string, character like: < > = + :param format: string, character like: f d B H L Q b h l q + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises FormatFieldError: wrong format string, or struct.(un)pack complained about the value + + Example:: + + >>> d = FormatField(">", "H") or Int16ub + >>> d.parse(b"\x01\x00") + 256 + >>> d.build(256) + b"\x01\x00" + >>> d.sizeof() + 2 + """ + + def __init__(self, endianity, format): + if endianity not in list("=<>"): + raise FormatFieldError("endianity must be like: = < >", endianity) + + if format not in list("fdBHLQbhlqe"): + raise FormatFieldError("format must be like: f d B H L Q b h l q e", format) + + super(FormatField, self).__init__() + self.fmtstr = endianity+format + if format != 'e' or supportshalffloats: + self.length = struct.calcsize(endianity+format) + self.packer = struct.Struct(endianity+format) + + def _parse(self, stream, context, path): + data = stream_read(stream, self.length, path) + try: + return self.packer.unpack(data)[0] + except Exception: + raise FormatFieldError("struct %r error during parsing" % self.fmtstr, path=path) + + def _build(self, obj, stream, context, path): + try: + data = self.packer.pack(obj) + except Exception: + raise FormatFieldError("struct %r error during building, given value %r" % (self.fmtstr, obj), path=path) + stream_write(stream, data, self.length, path) + return obj + + def _sizeof(self, context, path): + return self.length + + def _emitparse(self, code): + fname = "formatfield_%s" % code.allocateId() + code.append("%s = struct.Struct(%r)" % (fname, self.fmtstr, )) + return "%s.unpack(read_bytes(io, %s))[0]" % (fname, self.length) + + def _emitprimitivetype(self, ksy, bitwise): + endianity,format = self.fmtstr + signed = format.islower() + swapped = (endianity == "<") or (endianity == "=" and sys.byteorder == "little") + if format in "bhlqBHLQ": + if bitwise: + assert not signed + assert not swapped + return "b%s" % (8*self.length, ) + else: + return "%s%s%s" % ("s" if signed else "u", self.length, "le" if swapped else "be", ) + if format in "fd": + assert not bitwise + return "f%s%s" % (self.length, "le" if swapped else "be", ) + + +class BytesInteger(Construct): + r""" + Field that packs arbitrarily large integers. Some Int24* fields use this class. + + Parses into an integer. Builds from an integer into specified byte count and endianness. Size is specified in ctor. + + Analog to :class:`~construct.core.BitsInteger` that operates on bits. In fact, ``BytesInteger(n)`` is equivalent to ``Bitwise(BitsInteger(8*n))`` and ``BitsInteger(n)`` is equivalent to ``Bytewise(BytesInteger(n//8)))`` . + + :param length: integer or context lambda, number of bytes in the field + :param signed: bool, whether the value is signed (two's complement), default is False (unsigned) + :param swapped: bool, whether to swap byte order (little endian), default is False (big endian) + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises IntegerError: lenght is negative, given a negative value when field is not signed, or not an integer + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = BytesInteger(4) or Int32ub + >>> d.parse(b"abcd") + 1633837924 + >>> d.build(1) + b'\x00\x00\x00\x01' + >>> d.sizeof() + 4 + """ + + def __init__(self, length, signed=False, swapped=False): + super(BytesInteger, self).__init__() + self.length = length + self.signed = signed + self.swapped = swapped + + def _parse(self, stream, context, path): + length = self.length + if callable(length): + length = length(context) + if length < 0: + raise IntegerError("length must be non-negative", path=path) + data = stream_read(stream, length, path) + if self.swapped: + data = data[::-1] + return bytes2integer(data, self.signed) + + def _build(self, obj, stream, context, path): + if not isinstance(obj, integertypes): + raise IntegerError("value %r is not an integer" % (obj,), path=path) + if obj < 0 and not self.signed: + raise IntegerError("value %r is negative, but field is not signed" % (obj,), path=path) + length = self.length + if callable(length): + length = length(context) + if length < 0: + raise IntegerError("length must be non-negative", path=path) + data = integer2bytes(obj, length) + if self.swapped: + data = data[::-1] + stream_write(stream, data, length, path) + return obj + + def _sizeof(self, context, path): + try: + length = self.length + if callable(length): + length = length(context) + return length + except (KeyError, AttributeError): + raise SizeofError("cannot calculate size, key not found in context", path=path) + + def _emitparse(self, code): + return "bytes2integer(read_bytes(io, %s)%s, %s)" % (self.length, "[::-1]" if self.swapped else "", self.signed) + + def _emitprimitivetype(self, ksy, bitwise): + if bitwise: + assert not self.signed + assert not self.swapped + return "b%s" % (8*self.length, ) + else: + return "%s%s%s" % ("s" if self.signed else "u", self.length, "le" if self.swapped else "be", ) + + +class BitsInteger(Construct): + r""" + Field that packs arbitrarily large (or small) integers. Some fields (Bit Nibble Octet) use this class. Must be enclosed in :class:`~construct.core.Bitwise` context. + + Parses into an integer. Builds from an integer into specified bit count and endianness. Size (in bits) is specified in ctor. + + Note that little-endianness is only defined for multiples of 8 bits. + + Analog to :class:`~construct.core.BytesInteger` that operates on bytes. In fact, ``BytesInteger(n)`` is equivalent to ``Bitwise(BitsInteger(8*n))`` and ``BitsInteger(n)`` is equivalent to ``Bytewise(BytesInteger(n//8)))`` . + + :param length: integer or context lambda, number of bits in the field + :param signed: bool, whether the value is signed (two's complement), default is False (unsigned) + :param swapped: bool, whether to swap byte order (little endian), default is False (big endian) + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises IntegerError: lenght is negative, given a negative value when field is not signed, or not an integer + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = Bitwise(BitsInteger(8)) or Bitwise(Octet) + >>> d.parse(b"\x10") + 16 + >>> d.build(255) + b'\xff' + >>> d.sizeof() + 1 + """ + + def __init__(self, length, signed=False, swapped=False): + super(BitsInteger, self).__init__() + self.length = length + self.signed = signed + self.swapped = swapped + + def _parse(self, stream, context, path): + length = self.length + if callable(length): + length = length(context) + if length < 0: + raise IntegerError("length must be non-negative", path=path) + data = stream_read(stream, length, path) + if self.swapped: + if length & 7: + raise IntegerError("little-endianness is only defined for multiples of 8 bits", path=path) + data = swapbytes(data) + return bits2integer(data, self.signed) + + def _build(self, obj, stream, context, path): + if not isinstance(obj, integertypes): + raise IntegerError("value %r is not an integer" % (obj,), path=path) + if obj < 0 and not self.signed: + raise IntegerError("value %r is negative, but field is not signed" % (obj,), path=path) + length = self.length + if callable(length): + length = length(context) + if length < 0: + raise IntegerError("length must be non-negative", path=path) + data = integer2bits(obj, length) + if self.swapped: + if length & 7: + raise IntegerError("little-endianness is only defined for multiples of 8 bits", path=path) + data = swapbytes(data) + stream_write(stream, data, length, path) + return obj + + def _sizeof(self, context, path): + try: + length = self.length + if callable(length): + length = length(context) + return length + except (KeyError, AttributeError): + raise SizeofError("cannot calculate size, key not found in context", path=path) + + def _emitparse(self, code): + return "bits2integer(read_bytes(io, %s)%s, %s)" % (self.length, "[::-1]" if self.swapped else "", self.signed, ) + + def _emitprimitivetype(self, ksy, bitwise): + assert not self.signed + assert not self.swapped + return "b%s" % (self.length, ) + + +@singleton +def Bit(): + """A 1-bit integer, must be enclosed in a Bitwise (eg. BitStruct)""" + return BitsInteger(1) +@singleton +def Nibble(): + """A 4-bit integer, must be enclosed in a Bitwise (eg. BitStruct)""" + return BitsInteger(4) +@singleton +def Octet(): + """A 8-bit integer, must be enclosed in a Bitwise (eg. BitStruct)""" + return BitsInteger(8) + +@singleton +def Int8ub(): + """Unsigned, big endian 8-bit integer""" + return FormatField(">", "B") +@singleton +def Int16ub(): + """Unsigned, big endian 16-bit integer""" + return FormatField(">", "H") +@singleton +def Int32ub(): + """Unsigned, big endian 32-bit integer""" + return FormatField(">", "L") +@singleton +def Int64ub(): + """Unsigned, big endian 64-bit integer""" + return FormatField(">", "Q") + +@singleton +def Int8sb(): + """Signed, big endian 8-bit integer""" + return FormatField(">", "b") +@singleton +def Int16sb(): + """Signed, big endian 16-bit integer""" + return FormatField(">", "h") +@singleton +def Int32sb(): + """Signed, big endian 32-bit integer""" + return FormatField(">", "l") +@singleton +def Int64sb(): + """Signed, big endian 64-bit integer""" + return FormatField(">", "q") + +@singleton +def Int8ul(): + """Unsigned, little endian 8-bit integer""" + return FormatField("<", "B") +@singleton +def Int16ul(): + """Unsigned, little endian 16-bit integer""" + return FormatField("<", "H") +@singleton +def Int32ul(): + """Unsigned, little endian 32-bit integer""" + return FormatField("<", "L") +@singleton +def Int64ul(): + """Unsigned, little endian 64-bit integer""" + return FormatField("<", "Q") + +@singleton +def Int8sl(): + """Signed, little endian 8-bit integer""" + return FormatField("<", "b") +@singleton +def Int16sl(): + """Signed, little endian 16-bit integer""" + return FormatField("<", "h") +@singleton +def Int32sl(): + """Signed, little endian 32-bit integer""" + return FormatField("<", "l") +@singleton +def Int64sl(): + """Signed, little endian 64-bit integer""" + return FormatField("<", "q") + +@singleton +def Int8un(): + """Unsigned, native endianity 8-bit integer""" + return FormatField("=", "B") +@singleton +def Int16un(): + """Unsigned, native endianity 16-bit integer""" + return FormatField("=", "H") +@singleton +def Int32un(): + """Unsigned, native endianity 32-bit integer""" + return FormatField("=", "L") +@singleton +def Int64un(): + """Unsigned, native endianity 64-bit integer""" + return FormatField("=", "Q") + +@singleton +def Int8sn(): + """Signed, native endianity 8-bit integer""" + return FormatField("=", "b") +@singleton +def Int16sn(): + """Signed, native endianity 16-bit integer""" + return FormatField("=", "h") +@singleton +def Int32sn(): + """Signed, native endianity 32-bit integer""" + return FormatField("=", "l") +@singleton +def Int64sn(): + """Signed, native endianity 64-bit integer""" + return FormatField("=", "q") + +Byte = Int8ub +Short = Int16ub +Int = Int32ub +Long = Int64ub + +@singleton +def Float16b(): + """Big endian, 16-bit IEEE 754 floating point number""" + return FormatField(">", "e") +@singleton +def Float16l(): + """Little endian, 16-bit IEEE 754 floating point number""" + return FormatField("<", "e") +@singleton +def Float16n(): + """Native endianity, 16-bit IEEE 754 floating point number""" + return FormatField("=", "e") + +@singleton +def Float32b(): + """Big endian, 32-bit IEEE floating point number""" + return FormatField(">", "f") +@singleton +def Float32l(): + """Little endian, 32-bit IEEE floating point number""" + return FormatField("<", "f") +@singleton +def Float32n(): + """Native endianity, 32-bit IEEE floating point number""" + return FormatField("=", "f") + +@singleton +def Float64b(): + """Big endian, 64-bit IEEE floating point number""" + return FormatField(">", "d") +@singleton +def Float64l(): + """Little endian, 64-bit IEEE floating point number""" + return FormatField("<", "d") +@singleton +def Float64n(): + """Native endianity, 64-bit IEEE floating point number""" + return FormatField("=", "d") + +Half = Float16b +Single = Float32b +Double = Float64b + +native = (sys.byteorder == "little") + +@singleton +def Int24ub(): + """A 3-byte big-endian unsigned integer, as used in ancient file formats.""" + return BytesInteger(3, signed=False, swapped=False) +@singleton +def Int24ul(): + """A 3-byte little-endian unsigned integer, as used in ancient file formats.""" + return BytesInteger(3, signed=False, swapped=True) +@singleton +def Int24un(): + """A 3-byte native-endian unsigned integer, as used in ancient file formats.""" + return BytesInteger(3, signed=False, swapped=native) +@singleton +def Int24sb(): + """A 3-byte big-endian signed integer, as used in ancient file formats.""" + return BytesInteger(3, signed=True, swapped=False) +@singleton +def Int24sl(): + """A 3-byte little-endian signed integer, as used in ancient file formats.""" + return BytesInteger(3, signed=True, swapped=True) +@singleton +def Int24sn(): + """A 3-byte native-endian signed integer, as used in ancient file formats.""" + return BytesInteger(3, signed=True, swapped=native) + + +@singleton +class VarInt(Construct): + r""" + VarInt encoded integer. Each 7 bits of the number are encoded in one byte of the stream, where leftmost bit (MSB) is unset when byte is terminal. Scheme is defined at Google site related to `Protocol Buffers `_. + + Can only encode non-negative numbers. + + Parses into an integer. Builds from an integer. Size is undefined. + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises IntegerError: given a negative value, or not an integer + + Example:: + + >>> VarInt.build(1) + b'\x01' + >>> VarInt.build(2**100) + b'\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x04' + """ + + def _parse(self, stream, context, path): + acc = [] + while True: + b = byte2int(stream_read(stream, 1, path)) + acc.append(b & 0b01111111) + if not b & 0b10000000: + break + num = 0 + for b in reversed(acc): + num = (num << 7) | b + return num + + def _build(self, obj, stream, context, path): + if not isinstance(obj, integertypes): + raise IntegerError("value is not an integer", path=path) + if obj < 0: + raise IntegerError("varint cannot build from negative number: %r" % (obj,), path=path) + x = obj + while x > 0b01111111: + stream_write(stream, int2byte(0b10000000 | (x & 0b01111111)), 1, path) + x >>= 7 + stream_write(stream, int2byte(x), 1, path) + return obj + + def _emitprimitivetype(self, ksy, bitwise): + return "vlq_base128_le" + + +#=============================================================================== +# strings +#=============================================================================== + +#: Explicitly supported encodings (by PaddedString and CString classes). +#: +possiblestringencodings = dict( + ascii=1, + utf8=1, utf_8=1, u8=1, + utf16=2, utf_16=2, u16=2, utf_16_be=2, utf_16_le=2, + utf32=4, utf_32=4, u32=4, utf_32_be=4, utf_32_le=4, +) + + +def encodingunit(encoding): + """Used internally.""" + encoding = encoding.replace("-","_").lower() + if encoding not in possiblestringencodings: + raise StringError("encoding %r not found among %r" % (encoding, possiblestringencodings,)) + return bytes(possiblestringencodings[encoding]) + + +class StringEncoded(Adapter): + """Used internally.""" + + def __init__(self, subcon, encoding): + super(StringEncoded, self).__init__(subcon) + if not encoding: + raise StringError("String* classes require explicit encoding") + self.encoding = encoding + + def _decode(self, obj, context, path): + return obj.decode(self.encoding) + + def _encode(self, obj, context, path): + if not isinstance(obj, unicodestringtype): + raise StringError("string encoding failed, expected unicode string", path=path) + if obj == u"": + return b"" + return obj.encode(self.encoding) + + def _emitparse(self, code): + return "(%s).decode(%r)" % (self.subcon._compileparse(code), self.encoding, ) + + +def PaddedString(length, encoding): + r""" + Configurable, fixed-length or variable-length string field. + + When parsing, the byte string is stripped of null bytes (per encoding unit), then decoded. Length is an integer or context lambda. When building, the string is encoded and then padded to specified length. If encoded string is larger than the specified length, it fails with PaddingError. Size is same as length parameter. + + .. warning:: PaddedString and CString only support encodings explicitly listed in :class:`~construct.core.possiblestringencodings` . + + :param length: integer or context lambda, length in bytes (not unicode characters) + :param encoding: string like: utf8 utf16 utf32 ascii + + :raises StringError: building a non-unicode string + :raises StringError: selected encoding is not on supported list + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = PaddedString(10, "utf8") + >>> d.build(u"Афон") + b'\xd0\x90\xd1\x84\xd0\xbe\xd0\xbd\x00\x00' + >>> d.parse(_) + u'Афон' + """ + macro = StringEncoded(FixedSized(length, NullStripped(GreedyBytes, pad=encodingunit(encoding))), encoding) + def _emitfulltype(ksy, bitwise): + return dict(size=length, type="strz", encoding=encoding) + macro._emitfulltype = _emitfulltype + return macro + + +def PascalString(lengthfield, encoding): + r""" + Length-prefixed string. The length field can be variable length (such as VarInt) or fixed length (such as Int64ub). :class:`~construct.core.VarInt` is recommended when designing new protocols. Stored length is in bytes, not characters. Size is not defined. + + :param lengthfield: Construct instance, field used to parse and build the length (like VarInt Int64ub) + :param encoding: string like: utf8 utf16 utf32 ascii + + :raises StringError: building a non-unicode string + + Example:: + + >>> d = PascalString(VarInt, "utf8") + >>> d.build(u"Афон") + b'\x08\xd0\x90\xd1\x84\xd0\xbe\xd0\xbd' + >>> d.parse(_) + u'Афон' + """ + macro = StringEncoded(Prefixed(lengthfield, GreedyBytes), encoding) + def _emitseq(ksy, bitwise): + return [ + dict(id="lengthfield", type=lengthfield._compileprimitivetype(ksy, bitwise)), + dict(id="data", size="lengthfield", type="str", encoding=encoding), + ] + macro._emitseq = _emitseq + return macro + + +def CString(encoding): + r""" + String ending in a terminating null byte (or null bytes in case of UTF16 UTF32). + + .. warning:: String and CString only support encodings explicitly listed in :class:`~construct.core.possiblestringencodings` . + + :param encoding: string like: utf8 utf16 utf32 ascii + + :raises StringError: building a non-unicode string + :raises StringError: selected encoding is not on supported list + + Example:: + + >>> d = CString("utf8") + >>> d.build(u"Афон") + b'\xd0\x90\xd1\x84\xd0\xbe\xd0\xbd\x00' + >>> d.parse(_) + u'Афон' + """ + macro = StringEncoded(NullTerminated(GreedyBytes, term=encodingunit(encoding)), encoding) + def _emitfulltype(ksy, bitwise): + return dict(type="strz", encoding=encoding) + macro._emitfulltype = _emitfulltype + return macro + + +def GreedyString(encoding): + r""" + String that reads entire stream until EOF, and writes a given string as-is. Analog to :class:`~construct.core.GreedyBytes` but also applies unicode-to-bytes encoding. + + :param encoding: string like: utf8 utf16 utf32 ascii + + :raises StringError: building a non-unicode string + :raises StreamError: stream failed when reading until EOF + + Example:: + + >>> d = GreedyString("utf8") + >>> d.build(u"Афон") + b'\xd0\x90\xd1\x84\xd0\xbe\xd0\xbd' + >>> d.parse(_) + u'Афон' + """ + macro = StringEncoded(GreedyBytes, encoding) + def _emitfulltype(ksy, bitwise): + return dict(size_eos=True, type="str", encoding=encoding) + macro._emitfulltype = _emitfulltype + return macro + + +#=============================================================================== +# mappings +#=============================================================================== +@singleton +class Flag(Construct): + r""" + One byte (or one bit) field that maps to True or False. Other non-zero bytes are also considered True. Size is defined as 1. + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + + Example:: + + >>> Flag.parse(b"\x01") + True + >>> Flag.build(True) + b'\x01' + """ + + def _parse(self, stream, context, path): + return stream_read(stream, 1, path) != b"\x00" + + def _build(self, obj, stream, context, path): + stream_write(stream, b"\x01" if obj else b"\x00", 1, path) + return obj + + def _sizeof(self, context, path): + return 1 + + def _emitparse(self, code): + return "(read_bytes(io, 1) != b'\\x00')" + + def _emitfulltype(self, ksy, bitwise): + return dict(type=("b1" if bitwise else "u1"), _construct_render="Flag") + + +class EnumInteger(int): + """Used internally.""" + pass + + +class EnumIntegerString(str): + """Used internally.""" + + def __repr__(self): + return "EnumIntegerString.new(%s, %s)" % (self.intvalue, str.__repr__(self), ) + + def __int__(self): + return self.intvalue + + @staticmethod + def new(intvalue, stringvalue): + ret = EnumIntegerString(stringvalue) + ret.intvalue = intvalue + return ret + + +class Enum(Adapter): + r""" + Translates unicode label names to subcon values, and vice versa. + + Parses integer subcon, then uses that value to lookup mapping dictionary. Returns an integer-convertible string (if mapping found) or an integer (otherwise). Building is a reversed process. Can build from an integer flag or string label. Size is same as subcon, unless it raises SizeofError. + + There is no default parameter, because if no mapping is found, it parses into an integer without error. + + This class supports enum34 module. See examples. + + This class supports exposing member labels as attributes, as integer-convertible strings. See examples. + + :param subcon: Construct instance, subcon to map to/from + :param \*merge: optional, list of enum.IntEnum and enum.IntFlag instances, to merge labels and values from + :param \*\*mapping: dict, mapping string names to values + + :raises MappingError: building from string but no mapping found + + Example:: + + >>> d = Enum(Byte, one=1, two=2, four=4, eight=8) + >>> d.parse(b"\x01") + 'one' + >>> int(d.parse(b"\x01")) + 1 + >>> d.parse(b"\xff") + 255 + >>> int(d.parse(b"\xff")) + 255 + + >>> d.build(d.one or "one" or 1) + b'\x01' + >>> d.one + 'one' + + import enum + class E(enum.IntEnum or enum.IntFlag): + one = 1 + two = 2 + + Enum(Byte, E) <--> Enum(Byte, one=1, two=2) + FlagsEnum(Byte, E) <--> FlagsEnum(Byte, one=1, two=2) + """ + + def __init__(self, subcon, *merge, **mapping): + super(Enum, self).__init__(subcon) + for enum in merge: + for enumentry in enum: + mapping[enumentry.name] = enumentry.value + self.encmapping = {EnumIntegerString.new(v,k):v for k,v in mapping.items()} + self.decmapping = {v:EnumIntegerString.new(v,k) for k,v in mapping.items()} + self.ksymapping = {v:k for k,v in mapping.items()} + + def __getattr__(self, name): + if name in self.encmapping: + return self.decmapping[self.encmapping[name]] + raise AttributeError + + def _decode(self, obj, context, path): + try: + return self.decmapping[obj] + except KeyError: + return EnumInteger(obj) + + def _encode(self, obj, context, path): + try: + if isinstance(obj, integertypes): + return obj + return self.encmapping[obj] + except KeyError: + raise MappingError("building failed, no mapping for %r" % (obj,), path=path) + + def _emitparse(self, code): + fname = "factory_%s" % code.allocateId() + code.append("%s = %r" % (fname, self.decmapping, )) + return "reuse(%s, lambda x: %s.get(x, EnumInteger(x)))" % (self.subcon._compileparse(code), fname, ) + + def _emitprimitivetype(self, ksy, bitwise): + name = "enum_%s" % ksy.allocateId() + ksy.enums[name] = self.ksymapping + return name + + +class BitwisableString(str): + """Used internally.""" + + # def __repr__(self): + # return "BitwisableString(%s)" % (str.__repr__(self), ) + + def __or__(self, other): + return BitwisableString("{}|{}".format(self, other)) + + +class FlagsEnum(Adapter): + r""" + Translates unicode label names to subcon integer (sub)values, and vice versa. + + Parses integer subcon, then creates a Container, where flags define each key. Builds from a container by bitwise-oring of each flag if it matches a set key. Can build from an integer flag or string label directly, as well as | concatenations thereof (see examples). Size is same as subcon, unless it raises SizeofError. + + This class supports enum34 module. See examples. + + This class supports exposing member labels as attributes, as bitwisable strings. See examples. + + :param subcon: Construct instance, must operate on integers + :param \*merge: optional, list of enum.IntEnum and enum.IntFlag instances, to merge labels and values from + :param \*\*flags: dict, mapping string names to integer values + + :raises MappingError: building from object not like: integer string dict + :raises MappingError: building from string but no mapping found + + Can raise arbitrary exceptions when computing | and & and value is non-integer. + + Example:: + + >>> d = FlagsEnum(Byte, one=1, two=2, four=4, eight=8) + >>> d.parse(b"\x03") + Container(one=True, two=True, four=False, eight=False) + >>> d.build(dict(one=True,two=True)) + b'\x03' + + >>> d.build(d.one|d.two or "one|two" or 1|2) + b'\x03' + + import enum + class E(enum.IntEnum or enum.IntFlag): + one = 1 + two = 2 + + Enum(Byte, E) <--> Enum(Byte, one=1, two=2) + FlagsEnum(Byte, E) <--> FlagsEnum(Byte, one=1, two=2) + """ + + def __init__(self, subcon, *merge, **flags): + super(FlagsEnum, self).__init__(subcon) + for enum in merge: + for enumentry in enum: + flags[enumentry.name] = enumentry.value + self.flags = flags + self.reverseflags = {v:k for k,v in flags.items()} + + def __getattr__(self, name): + if name in self.flags: + return BitwisableString(name) + raise AttributeError + + def _decode(self, obj, context, path): + obj2 = Container() + obj2._flagsenum = True + for name,value in self.flags.items(): + obj2[BitwisableString(name)] = (obj & value == value) + return obj2 + + def _encode(self, obj, context, path): + try: + if isinstance(obj, integertypes): + return obj + if isinstance(obj, stringtypes): + flags = 0 + for name in obj.split("|"): + name = name.strip() + if name: + flags |= self.flags[name] # KeyError + return flags + if isinstance(obj, dict): + flags = 0 + for name,value in obj.items(): + if not name.startswith("_"): # assumes key is a string + if value: + flags |= self.flags[name] # KeyError + return flags + raise MappingError("building failed, unknown object: %r" % (obj,), path=path) + except KeyError: + raise MappingError("building failed, unknown label: %r" % (obj,), path=path) + + def _emitparse(self, code): + return "reuse(%s, lambda x: Container(%s))" % (self.subcon._compileparse(code), ", ".join("%s=bool(x & %s)" % (k,v) for k,v in self.flags.items()), ) + + def _emitseq(self, ksy, bitwise): + bitstotal = self.subcon.sizeof() * 8 + seq = [] + for i in range(bitstotal): + value = 1<>> x = object + >>> d = Mapping(Byte, {x:0}) + >>> d.parse(b"\x00") + x + >>> d.build(x) + b'\x00' + """ + + def __init__(self, subcon, mapping): + super(Mapping, self).__init__(subcon) + self.decmapping = {v:k for k,v in mapping.items()} + self.encmapping = mapping + + def _decode(self, obj, context, path): + try: + return self.decmapping[obj] # KeyError + except (KeyError, TypeError): + raise MappingError("parsing failed, no decoding mapping for %r" % (obj,), path=path) + + def _encode(self, obj, context, path): + try: + return self.encmapping[obj] # KeyError + except (KeyError, TypeError): + raise MappingError("building failed, no encoding mapping for %r" % (obj,), path=path) + + def _emitparse(self, code): + fname = "factory_%s" % code.allocateId() + code.append("%s = %r" % (fname, self.decmapping, )) + return "%s[%s]" % (fname, self.subcon._compileparse(code), ) + + +#=============================================================================== +# structures and sequences +#=============================================================================== +class Struct(Construct): + r""" + Sequence of usually named constructs, similar to structs in C. The members are parsed and build in the order they are defined. If a member is anonymous (its name is None) then it gets parsed and the value discarded, or it gets build from nothing (from None). + + Some fields do not need to be named, since they are built without value anyway. See: Const Padding Check Error Pass Terminated Seek Tell for examples of such fields. + + Operator + can also be used to make Structs (although not recommended). + + Parses into a Container (dict with attribute and key access) where keys match subcon names. Builds from a dict (not necessarily a Container) where each member gets a value from the dict matching the subcon name. If field has build-from-none flag, it gets build even when there is no matching entry in the dict. Size is the sum of all subcon sizes, unless any subcon raises SizeofError. + + This class does context nesting, meaning its members are given access to a new dictionary where the "_" entry points to the outer context. When parsing, each member gets parsed and subcon parse return value is inserted into context under matching key only if the member was named. When building, the matching entry gets inserted into context before subcon gets build, and if subcon build returns a new value (not None) that gets replaced in the context. + + This class exposes subcons as attributes. You can refer to subcons that were inlined (and therefore do not exist as variable in the namespace) by accessing the struct attributes, under same name. Also note that compiler does not support this feature. See examples. + + This class exposes subcons in the context. You can refer to subcons that were inlined (and therefore do not exist as variable in the namespace) within other inlined fields using the context. Note that you need to use a lambda (`this` expression is not supported). Also note that compiler does not support this feature. See examples. + + This class supports stopping. If :class:`~construct.core.StopIf` field is a member, and it evaluates its lambda as positive, this class ends parsing or building as successful without processing further fields. + + :param \*subcons: Construct instances, list of members, some can be anonymous + :param \*\*subconskw: Construct instances, list of members (requires Python 3.6) + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises KeyError: building a subcon but found no corresponding key in dictionary + + Example:: + + >>> d = Struct("num"/Int8ub, "data"/Bytes(this.num)) + >>> d.parse(b"\x04DATA") + Container(num=4)(data=b"DATA") + >>> d.build(dict(num=4, data=b"DATA")) + b"\x04DATA" + + >>> d = Struct(Const(b"MZ"), Padding(2), Pass, Terminated) + >>> d.build({}) + b'MZ\x00\x00' + >>> d.parse(_) + Container() + >>> d.sizeof() + 4 + + >>> d = Struct( + ... "animal" / Enum(Byte, giraffe=1), + ... ) + >>> d.animal.giraffe + 'giraffe' + >>> d = Struct( + ... "count" / Byte, + ... "data" / Bytes(lambda this: this.count - this._subcons.count.sizeof()), + ... ) + >>> d.build(dict(count=3, data=b"12")) + b'\x0312' + + Alternative syntax (not recommended): + >>> ("a"/Byte + "b"/Byte + "c"/Byte + "d"/Byte) + + Alternative syntax, but requires Python 3.6 or any PyPy: + >>> Struct(a=Byte, b=Byte, c=Byte, d=Byte) + """ + + def __init__(self, *subcons, **subconskw): + super(Struct, self).__init__() + self.subcons = list(subcons) + list(k/v for k,v in subconskw.items()) + self._subcons = Container((sc.name,sc) for sc in self.subcons if sc.name) + self.flagbuildnone = all(sc.flagbuildnone for sc in self.subcons) + + def __getattr__(self, name): + if name in self._subcons: + return self._subcons[name] + raise AttributeError + + def _parse(self, stream, context, path): + obj = Container() + obj._io = stream + context = Container(_ = context, _params = context._params, _root = None, _parsing = context._parsing, _building = context._building, _sizing = context._sizing, _subcons = self._subcons, _io = stream, _index = context.get("_index", None)) + context._root = context._.get("_root", context) + for sc in self.subcons: + try: + subobj = sc._parsereport(stream, context, path) + if sc.name: + obj[sc.name] = subobj + context[sc.name] = subobj + except StopFieldError: + break + return obj + + def _build(self, obj, stream, context, path): + if obj is None: + obj = Container() + context = Container(_ = context, _params = context._params, _root = None, _parsing = context._parsing, _building = context._building, _sizing = context._sizing, _subcons = self._subcons, _io = stream, _index = context.get("_index", None)) + context._root = context._.get("_root", context) + context.update(obj) + for sc in self.subcons: + try: + if sc.flagbuildnone: + subobj = obj.get(sc.name, None) + else: + subobj = obj[sc.name] # raises KeyError + + if sc.name: + context[sc.name] = subobj + + buildret = sc._build(subobj, stream, context, path) + if sc.name: + context[sc.name] = buildret + except StopFieldError: + break + return context + + def _sizeof(self, context, path): + context = Container(_ = context, _params = context._params, _root = None, _parsing = context._parsing, _building = context._building, _sizing = context._sizing, _subcons = self._subcons, _io = None, _index = context.get("_index", None)) + context._root = context._.get("_root", context) + try: + return sum(sc._sizeof(context, path) for sc in self.subcons) + except (KeyError, AttributeError): + raise SizeofError("cannot calculate size, key not found in context", path=path) + + def _emitparse(self, code): + fname = "parse_struct_%s" % code.allocateId() + block = """ + def %s(io, this): + result = Container() + this = Container(_ = this, _params = this['_params'], _root = None, _parsing = True, _building = False, _sizing = False, _subcons = None, _io = io, _index = this.get('_index', None)) + this['_root'] = this['_'].get('_root', this) + try: + """ % (fname, ) + for sc in self.subcons: + block += """ + %s%s + """ % ("result[%r] = this[%r] = " % (sc.name, sc.name) if sc.name else "", sc._compileparse(code)) + block += """ + pass + except StopFieldError: + pass + return result + """ + code.append(block) + return "%s(io, this)" % (fname,) + + def _emitseq(self, ksy, bitwise): + return [sc._compilefulltype(ksy, bitwise) for sc in self.subcons] + + +class Sequence(Construct): + r""" + Sequence of usually un-named constructs. The members are parsed and build in the order they are defined. If a member is named, its parsed value gets inserted into the context. This allows using members that refer to previous members. + + Operator >> can also be used to make Sequences (although not recommended). + + Parses into a ListContainer (list with pretty-printing) where values are in same order as subcons. Builds from a list (not necessarily a ListContainer) where each subcon is given the element at respective position. Size is the sum of all subcon sizes, unless any subcon raises SizeofError. + + This class does context nesting, meaning its members are given access to a new dictionary where the "_" entry points to the outer context. When parsing, each member gets parsed and subcon parse return value is inserted into context under matching key only if the member was named. When building, the matching entry gets inserted into context before subcon gets build, and if subcon build returns a new value (not None) that gets replaced in the context. + + This class exposes subcons as attributes. You can refer to subcons that were inlined (and therefore do not exist as variable in the namespace) by accessing the struct attributes, under same name. Also note that compiler does not support this feature. See examples. + + This class exposes subcons in the context. You can refer to subcons that were inlined (and therefore do not exist as variable in the namespace) within other inlined fields using the context. Note that you need to use a lambda (`this` expression is not supported). Also note that compiler does not support this feature. See examples. + + This class supports stopping. If :class:`~construct.core.StopIf` field is a member, and it evaluates its lambda as positive, this class ends parsing or building as successful without processing further fields. + + :param \*subcons: Construct instances, list of members, some can be named + :param \*\*subconskw: Construct instances, list of members (requires Python 3.6) + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises KeyError: building a subcon but found no corresponding key in dictionary + + Example:: + + >>> d = Sequence(Byte, Float32b) + >>> d.build([0, 1.23]) + b'\x00?\x9dp\xa4' + >>> d.parse(_) + [0, 1.2300000190734863] # a ListContainer + + >>> d = Sequence( + ... "animal" / Enum(Byte, giraffe=1), + ... ) + >>> d.animal.giraffe + 'giraffe' + >>> d = Sequence( + ... "count" / Byte, + ... "data" / Bytes(lambda this: this.count - this._subcons.count.sizeof()), + ... ) + >>> d.build([3, b"12"]) + b'\x0312' + + Alternative syntax (not recommended): + >>> (Byte >> "Byte >> "c"/Byte >> "d"/Byte) + + Alternative syntax, but requires Python 3.6 or any PyPy: + >>> Sequence(a=Byte, b=Byte, c=Byte, d=Byte) + """ + + def __init__(self, *subcons, **subconskw): + super(Sequence, self).__init__() + self.subcons = list(subcons) + list(k/v for k,v in subconskw.items()) + self._subcons = Container((sc.name,sc) for sc in self.subcons if sc.name) + self.flagbuildnone = all(sc.flagbuildnone for sc in self.subcons) + + def __getattr__(self, name): + if name in self._subcons: + return self._subcons[name] + raise AttributeError + + def _parse(self, stream, context, path): + obj = ListContainer() + context = Container(_ = context, _params = context._params, _root = None, _parsing = context._parsing, _building = context._building, _sizing = context._sizing, _subcons = self._subcons, _io = stream, _index = context.get("_index", None)) + context._root = context._.get("_root", context) + for i,sc in enumerate(self.subcons): + try: + subobj = sc._parsereport(stream, context, path) + obj.append(subobj) + if sc.name: + context[sc.name] = subobj + except StopFieldError: + break + return obj + + def _build(self, obj, stream, context, path): + if obj is None: + obj = ListContainer([None for sc in self.subcons]) + context = Container(_ = context, _params = context._params, _root = None, _parsing = context._parsing, _building = context._building, _sizing = context._sizing, _subcons = self._subcons, _io = stream, _index = context.get("_index", None)) + context._root = context._.get("_root", context) + retlist = ListContainer() + for i,(sc,subobj) in enumerate(zip(self.subcons, obj)): + try: + if sc.name: + context[sc.name] = subobj + + buildret = sc._build(subobj, stream, context, path) + retlist.append(buildret) + if sc.name: + context[sc.name] = buildret + except StopFieldError: + break + return retlist + + def _sizeof(self, context, path): + context = Container(_ = context, _params = context._params, _root = None, _parsing = context._parsing, _building = context._building, _sizing = context._sizing, _subcons = self._subcons, _io = None, _index = context.get("_index", None)) + context._root = context._.get("_root", context) + try: + return sum(sc._sizeof(context, path) for sc in self.subcons) + except (KeyError, AttributeError): + raise SizeofError("cannot calculate size, key not found in context", path=path) + + def _emitparse(self, code): + fname = "parse_sequence_%s" % code.allocateId() + block = """ + def %s(io, this): + result = ListContainer() + this = Container(_ = this, _params = this['_params'], _root = None, _parsing = True, _building = False, _sizing = False, _subcons = None, _io = io, _index = this.get('_index', None)) + this['_root'] = this['_'].get('_root', this) + try: + """ % (fname,) + for sc in self.subcons: + block += """ + result.append(%s) + """ % (sc._compileparse(code)) + if sc.name: + block += """ + this[%r] = result[-1] + """ % (sc.name, ) + block += """ + pass + except StopFieldError: + pass + return result + """ + code.append(block) + return "%s(io, this)" % (fname,) + + def _emitseq(self, ksy, bitwise): + return [sc._compilefulltype(ksy, bitwise) for sc in self.subcons] + + +#=============================================================================== +# arrays ranges and repeaters +#=============================================================================== +class Array(Subconstruct): + r""" + Homogenous array of elements, similar to C# generic T[]. + + Parses into a ListContainer (a list). Parsing and building processes an exact amount of elements. If given list has more or less than count elements, raises RangeError. Size is defined as count multiplied by subcon size, but only if subcon is fixed size. + + Operator [] can be used to make Array instances (recommended syntax). + + :param count: integer or context lambda, strict amount of elements + :param subcon: Construct instance, subcon to process individual elements + :param discard: optional, bool, if set then parsing returns empty list + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises RangeError: specified count is not valid + :raises RangeError: given object has different length than specified count + + Can propagate any exception from the lambdas, possibly non-ConstructError. + + Example:: + + >>> d = Array(5, Byte) or Byte[5] + >>> d.build(range(5)) + b'\x00\x01\x02\x03\x04' + >>> d.parse(_) + [0, 1, 2, 3, 4] + """ + + def __init__(self, count, subcon, discard=False): + super(Array, self).__init__(subcon) + self.count = count + self.discard = discard + + def _parse(self, stream, context, path): + count = self.count + if callable(count): + count = count(context) + if not 0 <= count: + raise RangeError("invalid count %s" % (count,), path=path) + obj = ListContainer() + for i in range(count): + context._index = i + e = self.subcon._parsereport(stream, context, path) + if not self.discard: + obj.append(e) + return obj + + def _build(self, obj, stream, context, path): + count = self.count + if callable(count): + count = count(context) + if not 0 <= count: + raise RangeError("invalid count %s" % (count,), path=path) + if not len(obj) == count: + raise RangeError("expected %d elements, found %d" % (count, len(obj)), path=path) + retlist = ListContainer() + for i,e in enumerate(obj): + context._index = i + buildret = self.subcon._build(e, stream, context, path) + retlist.append(buildret) + return retlist + + def _sizeof(self, context, path): + try: + count = self.count + if callable(count): + count = count(context) + except (KeyError, AttributeError): + raise SizeofError("cannot calculate size, key not found in context", path=path) + return count * self.subcon._sizeof(context, path) + + def _emitparse(self, code): + return "ListContainer((this.__setitem__('_index',i),(%s))[1] for i in range(%s))" % (self.subcon._compileparse(code), self.count, ) + + def _emitfulltype(self, ksy, bitwise): + return dict(type=self.subcon._compileprimitivetype(ksy, bitwise), repeat="expr", repeat_expr=self.count) + + +class GreedyRange(Subconstruct): + r""" + Homogenous array of elements, similar to C# generic IEnumerable, but works with unknown count of elements by parsing until end of stream. + + Parses into a ListContainer (a list). Parsing stops when an exception occured when parsing the subcon, either due to EOF or subcon format not being able to parse the data. Either way, when GreedyRange encounters either failure it seeks the stream back to a position after last successful subcon parsing. Builds from enumerable, each element as-is. Size is undefined. + + This class supports stopping. If :class:`~construct.core.StopIf` field is a member, and it evaluates its lambda as positive, this class ends parsing or building as successful without processing further fields. + + :param subcon: Construct instance, subcon to process individual elements + :param discard: optional, bool, if set then parsing returns empty list + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises StreamError: stream is not seekable and tellable + + Can propagate any exception from the lambdas, possibly non-ConstructError. + + Example:: + + >>> d = GreedyRange(Byte) + >>> d.build(range(8)) + b'\x00\x01\x02\x03\x04\x05\x06\x07' + >>> d.parse(_) + [0, 1, 2, 3, 4, 5, 6, 7] + """ + + def __init__(self, subcon, discard=False): + super(GreedyRange, self).__init__(subcon) + self.discard = discard + + def _parse(self, stream, context, path): + obj = ListContainer() + try: + for i in itertools.count(): + context._index = i + fallback = stream_tell(stream, path) + e = self.subcon._parsereport(stream, context, path) + if not self.discard: + obj.append(e) + except StopFieldError: + pass + except ExplicitError: + raise + except Exception: + stream_seek(stream, fallback, 0, path) + return obj + + def _build(self, obj, stream, context, path): + try: + retlist = ListContainer() + for i,e in enumerate(obj): + context._index = i + buildret = self.subcon._build(e, stream, context, path) + retlist.append(buildret) + return retlist + except StopFieldError: + pass + + def _sizeof(self, context, path): + raise SizeofError(path=path) + + def _emitfulltype(self, ksy, bitwise): + return dict(type=self.subcon._compileprimitivetype(ksy, bitwise), repeat="eos") + + +class RepeatUntil(Subconstruct): + r""" + Homogenous array of elements, similar to C# generic IEnumerable, that repeats until the predicate indicates it to stop. Note that the last element (that predicate indicated as True) is included in the return list. + + Parse iterates indefinately until last element passed the predicate. Build iterates indefinately over given list, until an element passed the precicate (or raises RepeatError if no element passed it). Size is undefined. + + :param predicate: lambda that takes (obj, list, context) and returns True to break or False to continue (or a truthy value) + :param subcon: Construct instance, subcon used to parse and build each element + :param discard: optional, bool, if set then parsing returns empty list + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises RepeatError: consumed all elements in the stream but neither passed the predicate + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = RepeatUntil(lambda x,lst,ctx: x > 7, Byte) + >>> d.build(range(20)) + b'\x00\x01\x02\x03\x04\x05\x06\x07\x08' + >>> d.parse(b"\x01\xff\x02") + [1, 255] + + >>> d = RepeatUntil(lambda x,lst,ctx: lst[-2:] == [0,0], Byte) + >>> d.parse(b"\x01\x00\x00\xff") + [1, 0, 0] + """ + + def __init__(self, predicate, subcon, discard=False): + super(RepeatUntil, self).__init__(subcon) + self.predicate = predicate + self.discard = discard + + def _parse(self, stream, context, path): + predicate = self.predicate + if not callable(predicate): + predicate = lambda _1,_2,_3: predicate + obj = ListContainer() + for i in itertools.count(): + context._index = i + e = self.subcon._parsereport(stream, context, path) + if not self.discard: + obj.append(e) + if predicate(e, obj, context): + return obj + + def _build(self, obj, stream, context, path): + predicate = self.predicate + if not callable(predicate): + predicate = lambda _1,_2,_3: predicate + partiallist = ListContainer() + retlist = ListContainer() + for i,e in enumerate(obj): + context._index = i + buildret = self.subcon._build(e, stream, context, path) + retlist.append(buildret) + partiallist.append(buildret) + if predicate(e, partiallist, context): + break + else: + raise RepeatError("expected any item to match predicate, when building", path=path) + return retlist + + def _sizeof(self, context, path): + raise SizeofError("cannot calculate size, amount depends on actual data", path=path) + + def _emitparse(self, code): + fname = "parse_repeatuntil_%s" % code.allocateId() + block = """ + def %s(io, this): + list_ = ListContainer() + for i in itertools.count(): + this['_index'] = i + obj_ = %s + list_.append(obj_) + if (%s): + return list_ + """ % (fname, self.subcon._compileparse(code), self.predicate, ) + code.append(block) + return "%s(io, this)" % (fname,) + + def _emitfulltype(self, ksy, bitwise): + return dict(type=self.subcon._compileprimitivetype(ksy, bitwise), repeat="until", repeat_until=repr(self.predicate).replace("obj_","_")) + + +#=============================================================================== +# specials +#=============================================================================== +class Renamed(Subconstruct): + r""" + Special wrapper that allows a Struct (or other similar class) to see a field as having a name (or a different name) or having a parsed hook. Library classes do not have names (its None). Renamed does not change a field, only wraps it like a candy with a label. Used internally by / and * operators. + + Also this wrapper is responsible for building a path info (a chain of names) that gets attached to error message when parsing, building, or sizeof fails. Fields that are not named do not appear in the path string. + + Parsing building and size are deferred to subcon. + + :param subcon: Construct instance + :param newname: optional, string + :param newdocs: optional, string + :param newparsed: optional, lambda + + Example:: + + >>> "number" / Int32ub + + """ + + def __init__(self, subcon, newname=None, newdocs=None, newparsed=None): + super(Renamed, self).__init__(subcon) + self.name = newname if newname else subcon.name + self.docs = newdocs if newdocs else subcon.docs + self.parsed = newparsed if newparsed else subcon.parsed + + def __getattr__(self, name): + return getattr(self.subcon, name) + + def _parse(self, stream, context, path): + path += " -> %s" % (self.name,) + return self.subcon._parsereport(stream, context, path) + + def _build(self, obj, stream, context, path): + path += " -> %s" % (self.name,) + return self.subcon._build(obj, stream, context, path) + + def _sizeof(self, context, path): + path += " -> %s" % (self.name,) + return self.subcon._sizeof(context, path) + + def _emitparse(self, code): + return self.subcon._compileparse(code) + + def _emitseq(self, ksy, bitwise): + return self.subcon._compileseq(ksy, bitwise) + + def _emitprimitivetype(self, ksy, bitwise): + return self.subcon._compileprimitivetype(ksy, bitwise) + + def _emitfulltype(self, ksy, bitwise): + r = dict() + if self.name: + r.update(id=self.name) + r.update(self.subcon._compilefulltype(ksy, bitwise)) + if self.docs: + r.update(doc=self.docs) + return r + + +#=============================================================================== +# miscellaneous +#=============================================================================== +class Const(Subconstruct): + r""" + Field enforcing a constant. It is used for file signatures, to validate that the given pattern exists. Data in the stream must strictly match the specified value. + + Note that a variable sized subcon may still provide positive verification. Const does not consume a precomputed amount of bytes, but depends on the subcon to read the appropriate amount (eg. VarInt is acceptable). Whatever subcon parses into, gets compared against the specified value. + + Parses using subcon and return its value (after checking). Builds using subcon from nothing (or given object, if not None). Size is the same as subcon, unless it raises SizeofError. + + :param value: expected value, usually a bytes literal + :param subcon: optional, Construct instance, subcon used to build value from, assumed to be Bytes if value parameter was a bytes literal + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises ConstError: parsed data does not match specified value, or building from wrong value + :raises StringError: building from non-bytes value, perhaps unicode + + Example:: + + >>> d = Const(b"IHDR") + >>> d.build(None) + b'IHDR' + >>> d.parse(b"JPEG") + construct.core.ConstError: expected b'IHDR' but parsed b'JPEG' + + >>> d = Const(255, Int32ul) + >>> d.build(None) + b'\xff\x00\x00\x00' + """ + + def __init__(self, value, subcon=None): + if subcon is None: + if not isinstance(value, bytestringtype): + raise StringError("given non-bytes value, perhaps unicode? %r" % (value,)) + subcon = Bytes(len(value)) + super(Const, self).__init__(subcon) + self.value = value + self.flagbuildnone = True + + def _parse(self, stream, context, path): + obj = self.subcon._parsereport(stream, context, path) + if obj != self.value: + raise ConstError("parsing expected %r but parsed %r" % (self.value, obj), path=path) + return obj + + def _build(self, obj, stream, context, path): + if obj not in (None, self.value): + raise ConstError("building expected None or %r but got %r" % (self.value, obj), path=path) + return self.subcon._build(self.value, stream, context, path) + + def _sizeof(self, context, path): + return self.subcon._sizeof(context, path) + + def _emitparse(self, code): + code.append(""" + def parse_const(value, expected): + if not value == expected: raise ConstError + return value + """) + return "parse_const(%s, %r)" % (self.subcon._compileparse(code), self.value,) + + def _emitfulltype(self, ksy, bitwise): + data = self.subcon.build(self.value) + return dict(contents=list(iterateints(data))) + + +class Computed(Construct): + r""" + Field computing a value from the context dictionary or some outer source like os.urandom or random module. Underlying byte stream is unaffected. The source can be non-deterministic. + + Parsing and Building return the value returned by the context lambda (although a constant value can also be used). Size is defined as 0 because parsing and building does not consume or produce bytes into the stream. + + :param func: context lambda or constant value + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + >>> d = Struct( + ... "width" / Byte, + ... "height" / Byte, + ... "total" / Computed(this.width * this.height), + ... ) + >>> d.build(dict(width=4,height=5)) + b'\x04\x05' + >>> d.parse(b"12") + Container(width=49, height=50, total=2450) + + >>> d = Computed(7) + >>> d.parse(b"") + 7 + >>> d = Computed(lambda ctx: 7) + >>> d.parse(b"") + 7 + + >>> import os + >>> d = Computed(lambda ctx: os.urandom(10)) + >>> d.parse(b"") + b'\x98\xc2\xec\x10\x07\xf5\x8e\x98\xc2\xec' + """ + + def __init__(self, func): + super(Computed, self).__init__() + self.func = func + self.flagbuildnone = True + + def _parse(self, stream, context, path): + return self.func(context) if callable(self.func) else self.func + + def _build(self, obj, stream, context, path): + return self.func(context) if callable(self.func) else self.func + + def _sizeof(self, context, path): + return 0 + + def _emitparse(self, code): + return "%r" % (self.func,) + + +@singleton +class Index(Construct): + r""" + Indexes a field inside outer :class:`~construct.core.Array` :class:`~construct.core.GreedyRange` :class:`~construct.core.RepeatUntil` context. + + Note that you can use this class, or use `this._index` expression instead, depending on how its used. See the examples. + + Parsing and building pulls _index key from the context. Size is 0 because stream is unaffected. + + :raises IndexFieldError: did not find either key in context + + Example:: + + >>> d = Array(3, Index) + >>> d.parse(b"") + [0, 1, 2] + >>> d = Array(3, Struct("i" / Index)) + >>> d.parse(b"") + [Container(i=0), Container(i=1), Container(i=2)] + + >>> d = Array(3, Computed(this._index+1)) + >>> d.parse(b"") + [1, 2, 3] + >>> d = Array(3, Struct("i" / Computed(this._._index+1))) + >>> d.parse(b"") + [Container(i=1), Container(i=2), Container(i=3)] + """ + + def __init__(self): + super(self.__class__, self).__init__() + self.flagbuildnone = True + + def _parse(self, stream, context, path): + return context.get("_index", None) + raise IndexFieldError("did not find either key in context", path=path) + + def _build(self, obj, stream, context, path): + return context.get("_index", None) + raise IndexFieldError("did not find either key in context", path=path) + + def _sizeof(self, context, path): + return 0 + + +class Rebuild(Subconstruct): + r""" + Field where building does not require a value, because the value gets recomputed when needed. Comes handy when building a Struct from a dict with missing keys. Useful for length and count fields when :class:`~construct.core.Prefixed` and :class:`~construct.core.PrefixedArray` cannot be used. + + Parsing defers to subcon. Building is defered to subcon, but it builds from a value provided by the context lambda (or constant). Size is the same as subcon, unless it raises SizeofError. + + Difference between Default and Rebuild, is that in first the build value is optional and in second the build value is ignored. + + :param subcon: Construct instance + :param func: context lambda or constant value + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = Struct( + ... "count" / Rebuild(Byte, len_(this.items)), + ... "items" / Byte[this.count], + ... ) + >>> d.build(dict(items=[1,2,3])) + b'\x03\x01\x02\x03' + """ + + def __init__(self, subcon, func): + super(Rebuild, self).__init__(subcon) + self.func = func + self.flagbuildnone = True + + def _build(self, obj, stream, context, path): + obj = self.func(context) if callable(self.func) else self.func + return self.subcon._build(obj, stream, context, path) + + def _emitparse(self, code): + return self.subcon._compileparse(code) + + def _emitseq(self, ksy, bitwise): + return self.subcon._compileseq(ksy, bitwise) + + def _emitprimitivetype(self, ksy, bitwise): + return self.subcon._compileprimitivetype(ksy, bitwise) + + def _emitfulltype(self, ksy, bitwise): + return self.subcon._compilefulltype(ksy, bitwise) + + +class Default(Subconstruct): + r""" + Field where building does not require a value, because the value gets taken from default. Comes handy when building a Struct from a dict with missing keys. + + Parsing defers to subcon. Building is defered to subcon, but it builds from a default (if given object is None) or from given object. Building does not require a value, but can accept one. Size is the same as subcon, unless it raises SizeofError. + + Difference between Default and Rebuild, is that in first the build value is optional and in second the build value is ignored. + + :param subcon: Construct instance + :param value: context lambda or constant value + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = Struct( + ... "a" / Default(Byte, 0), + ... ) + >>> d.build(dict(a=1)) + b'\x01' + >>> d.build(dict()) + b'\x00' + """ + + def __init__(self, subcon, value): + super(Default, self).__init__(subcon) + self.value = value + self.flagbuildnone = True + + def _build(self, obj, stream, context, path): + obj = (self.value(context) if callable(self.value) else self.value) if obj is None else obj + return self.subcon._build(obj, stream, context, path) + + def _emitparse(self, code): + return self.subcon._compileparse(code) + + def _emitseq(self, ksy, bitwise): + return self.subcon._compileseq(ksy, bitwise) + + def _emitprimitivetype(self, ksy, bitwise): + return self.subcon._compileprimitivetype(ksy, bitwise) + + def _emitfulltype(self, ksy, bitwise): + return self.subcon._compilefulltype(ksy, bitwise) + + +class Check(Construct): + r""" + Checks for a condition, and raises CheckError if the check fails. + + Parsing and building return nothing (but check the condition). Size is 0 because stream is unaffected. + + :param func: bool or context lambda, that gets run on parsing and building + + :raises CheckError: lambda returned false + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + Check(lambda ctx: len(ctx.payload.data) == ctx.payload_len) + Check(len_(this.payload.data) == this.payload_len) + """ + + def __init__(self, func): + super(Check, self).__init__() + self.func = func + self.flagbuildnone = True + + def _parse(self, stream, context, path): + passed = self.func(context) if callable(self.func) else self.func + if not passed: + raise CheckError("check failed during parsing", path=path) + + def _build(self, obj, stream, context, path): + passed = self.func(context) if callable(self.func) else self.func + if not passed: + raise CheckError("check failed during building", path=path) + + def _sizeof(self, context, path): + return 0 + + def _emitparse(self, code): + code.append(""" + def parse_check(condition): + if not condition: raise CheckError + """) + return "parse_check(%s)" % (self.func,) + + +@singleton +class Error(Construct): + r""" + Raises ExplicitError, unconditionally. + + Parsing and building always raise ExplicitError. Size is undefined. + + :raises ExplicitError: unconditionally, on parsing and building + + Example:: + + >>> d = Struct("num"/Byte, Error) + >>> d.parse(b"data...") + construct.core.ExplicitError: Error field was activated during parsing + """ + + def __init__(self): + super(self.__class__, self).__init__() + self.flagbuildnone = True + + def _parse(self, stream, context, path): + raise ExplicitError("Error field was activated during parsing", path=path) + + def _build(self, obj, stream, context, path): + raise ExplicitError("Error field was activated during building", path=path) + + def _sizeof(self, context, path): + raise SizeofError("Error does not have size, because it interrupts parsing and building", path=path) + + def _emitparse(self, code): + code.append(""" + def parse_error(): + raise ExplicitError + """) + return "parse_error()" + + +class FocusedSeq(Construct): + r""" + Allows constructing more elaborate "adapters" than Adapter class. + + Parse does parse all subcons in sequence, but returns only the element that was selected (discards other values). Build does build all subcons in sequence, where each gets build from nothing (except the selected subcon which is given the object). Size is the sum of all subcon sizes, unless any subcon raises SizeofError. + + This class does context nesting, meaning its members are given access to a new dictionary where the "_" entry points to the outer context. When parsing, each member gets parsed and subcon parse return value is inserted into context under matching key only if the member was named. When building, the matching entry gets inserted into context before subcon gets build, and if subcon build returns a new value (not None) that gets replaced in the context. + + This class exposes subcons as attributes. You can refer to subcons that were inlined (and therefore do not exist as variable in the namespace) by accessing the struct attributes, under same name. Also note that compiler does not support this feature. See examples. + + This class exposes subcons in the context. You can refer to subcons that were inlined (and therefore do not exist as variable in the namespace) within other inlined fields using the context. Note that you need to use a lambda (`this` expression is not supported). Also note that compiler does not support this feature. See examples. + + This class is used internally to implement :class:`~construct.core.PrefixedArray`. + + :param parsebuildfrom: string name or context lambda, selects a subcon + :param \*subcons: Construct instances, list of members, some can be named + :param \*\*subconskw: Construct instances, list of members (requires Python 3.6) + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises UnboundLocalError: selector does not match any subcon + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Excample:: + + >>> d = FocusedSeq("num", Const(b"SIG"), "num"/Byte, Terminated) + >>> d.parse(b"SIG\xff") + 255 + >>> d.build(255) + b'SIG\xff' + + >>> d = FocusedSeq("animal", + ... "animal" / Enum(Byte, giraffe=1), + ... ) + >>> d.animal.giraffe + 'giraffe' + >>> d = FocusedSeq("count", + ... "count" / Byte, + ... "data" / Padding(lambda this: this.count - this._subcons.count.sizeof()), + ... ) + >>> d.build(4) + b'\x04\x00\x00\x00' + + PrefixedArray <--> FocusedSeq("items", + "count" / Rebuild(lengthfield, len_(this.items)), + "items" / subcon[this.count], + ) + """ + + def __init__(self, parsebuildfrom, *subcons, **subconskw): + super(FocusedSeq, self).__init__() + self.parsebuildfrom = parsebuildfrom + self.subcons = list(subcons) + list(k/v for k,v in subconskw.items()) + self._subcons = Container((sc.name,sc) for sc in self.subcons if sc.name) + + def __getattr__(self, name): + if name in self._subcons: + return self._subcons[name] + raise AttributeError + + def _parse(self, stream, context, path): + context = Container(_ = context, _params = context._params, _root = None, _parsing = context._parsing, _building = context._building, _sizing = context._sizing, _subcons = self._subcons, _io = stream, _index = context.get("_index", None)) + context._root = context._.get("_root", context) + parsebuildfrom = evaluate(self.parsebuildfrom, context) + for i,sc in enumerate(self.subcons): + parseret = sc._parsereport(stream, context, path) + if sc.name: + context[sc.name] = parseret + if sc.name == parsebuildfrom: + finalret = parseret + return finalret + + def _build(self, obj, stream, context, path): + context = Container(_ = context, _params = context._params, _root = None, _parsing = context._parsing, _building = context._building, _sizing = context._sizing, _subcons = self._subcons, _io = stream, _index = context.get("_index", None)) + context._root = context._.get("_root", context) + parsebuildfrom = evaluate(self.parsebuildfrom, context) + context[parsebuildfrom] = obj + for i,sc in enumerate(self.subcons): + buildret = sc._build(obj if sc.name == parsebuildfrom else None, stream, context, path) + if sc.name: + context[sc.name] = buildret + if sc.name == parsebuildfrom: + finalret = buildret + return finalret + + def _sizeof(self, context, path): + context = Container(_ = context, _params = context._params, _root = None, _parsing = context._parsing, _building = context._building, _sizing = context._sizing, _subcons = self._subcons, _io = None, _index = context.get("_index", None)) + context._root = context._.get("_root", context) + try: + return sum(sc._sizeof(context, path) for sc in self.subcons) + except (KeyError, AttributeError): + raise SizeofError("cannot calculate size, key not found in context", path=path) + + def _emitparse(self, code): + fname = "parse_focusedseq_%s" % code.allocateId() + block = """ + def %s(io, this): + result = [] + this = Container(_ = this, _params = this['_params'], _root = None, _parsing = True, _building = False, _sizing = False, _subcons = None, _io = io, _index = this.get('_index', None)) + this['_root'] = this['_'].get('_root', this) + """ % (fname, ) + for sc in self.subcons: + block += """ + result.append(%s) + """ % (sc._compileparse(code), ) + if sc.name: + block += """ + this[%r] = result[-1] + """ % (sc.name, ) + block += """ + return this[%r] + """ % (self.parsebuildfrom, ) + code.append(block) + return "%s(io, this)" % (fname,) + + def _emitseq(self, ksy, bitwise): + return [sc._compilefulltype(ksy, bitwise) for sc in self.subcons] + + +@singleton +class Pickled(Construct): + r""" + Preserves arbitrary Python objects. + + Parses using `pickle.load() `_ and builds using `pickle.dump() `_ functions, using default Pickle binary protocol. Size is undefined. + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + + Can propagate pickle.load() and pickle.dump() exceptions. + + Example:: + + >>> x = [1, 2.3, {}] + >>> Pickled.build(x) + b'\x80\x03]q\x00(K\x01G@\x02ffffff}q\x01e.' + >>> Pickled.parse(_) + [1, 2.3, {}] + """ + + def _parse(self, stream, context, path): + return pickle.load(stream) + + def _build(self, obj, stream, context, path): + pickle.dump(obj, stream) + return obj + + +@singleton +class Numpy(Construct): + r""" + Preserves numpy arrays (both shape, dtype and values). + + Parses using `numpy.load() `_ and builds using `numpy.save() `_ functions, using Numpy binary protocol. Size is undefined. + + :raises ImportError: numpy could not be imported during parsing or building + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + + Can propagate numpy.load() and numpy.save() exceptions. + + Example:: + + >>> import numpy + >>> a = numpy.asarray([1,2,3]) + >>> Numpy.build(a) + b"\x93NUMPY\x01\x00F\x00{'descr': '>> Numpy.parse(_) + array([1, 2, 3]) + """ + + def _parse(self, stream, context, path): + import numpy + return numpy.load(stream) + + def _build(self, obj, stream, context, path): + import numpy + numpy.save(stream, obj) + return obj + + +class NamedTuple(Adapter): + r""" + Both arrays, structs, and sequences can be mapped to a namedtuple from `collections module `_. To create a named tuple, you need to provide a name and a sequence of fields, either a string with space-separated names or a list of string names, like the standard namedtuple. + + Parses into a collections.namedtuple instance, and builds from such instance (although it also builds from lists and dicts). Size is undefined. + + :param tuplename: string + :param tuplefields: string or list of strings + :param subcon: Construct instance, either Struct Sequence Array GreedyRange + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises NamedTupleError: subcon is neither Struct Sequence Array GreedyRange + + Can propagate collections exceptions. + + Example:: + + >>> d = NamedTuple("coord", "x y z", Byte[3]) + >>> d = NamedTuple("coord", "x y z", Byte >> Byte >> Byte) + >>> d = NamedTuple("coord", "x y z", "x"/Byte + "y"/Byte + "z"/Byte) + >>> d.parse(b"123") + coord(x=49, y=50, z=51) + """ + + def __init__(self, tuplename, tuplefields, subcon): + if not isinstance(subcon, (Struct,Sequence,Array,GreedyRange)): + raise NamedTupleError("subcon is neither Struct Sequence Array GreedyRange") + super(NamedTuple, self).__init__(subcon) + self.tuplename = tuplename + self.tuplefields = tuplefields + self.factory = collections.namedtuple(tuplename, tuplefields) + + def _decode(self, obj, context, path): + if isinstance(self.subcon, Struct): + del obj["_io"] + return self.factory(**obj) + if isinstance(self.subcon, (Sequence,Array,GreedyRange)): + return self.factory(*obj) + raise NamedTupleError("subcon is neither Struct Sequence Array GreedyRangeGreedyRange", path=path) + + def _encode(self, obj, context, path): + if isinstance(self.subcon, Struct): + return Container({sc.name:getattr(obj,sc.name) for sc in self.subcon.subcons if sc.name}) + if isinstance(self.subcon, (Sequence,Array,GreedyRange)): + return list(obj) + raise NamedTupleError("subcon is neither Struct Sequence Array GreedyRange", path=path) + + def _emitparse(self, code): + fname = "factory_%s" % code.allocateId() + code.append(""" + %s = collections.namedtuple(%r, %r) + """ % (fname, self.tuplename, self.tuplefields, )) + if isinstance(self.subcon, Struct): + return "%s(**(%s))" % (fname, self.subcon._compileparse(code), ) + if isinstance(self.subcon, (Sequence,Array,GreedyRange)): + return "%s(*(%s))" % (fname, self.subcon._compileparse(code), ) + raise NamedTupleError("subcon is neither Struct Sequence Array GreedyRange") + + def _emitseq(self, ksy, bitwise): + return self.subcon._compileseq(ksy, bitwise) + + def _emitprimitivetype(self, ksy, bitwise): + return self.subcon._compileprimitivetype(ksy, bitwise) + + def _emitfulltype(self, ksy, bitwise): + return self.subcon._compilefulltype(ksy, bitwise) + + +def Timestamp(subcon, unit, epoch): + r""" + Datetime, represented as `Arrow `_ object. + + Note that accuracy is not guaranteed, because building rounds the value to integer (even when Float subcon is used), due to floating-point errors in general, and because MSDOS scheme has only 5-bit (32 values) seconds field (seconds are rounded to multiple of 2). + + Unit is a fraction of a second. 1 is second resolution, 10**-3 is milliseconds resolution, 10**-6 is microseconds resolution, etc. Usually its 1 on Unix and MacOSX, 10**-7 on Windows. Epoch is a year (if integer) or a specific day (if Arrow object). Usually its 1970 on Unix, 1904 on MacOSX, 1600 on Windows. MSDOS format doesnt support custom unit or epoch, it uses 2-seconds resolution and 1980 epoch. + + :param subcon: Construct instance like Int* Float*, or Int32ub with msdos format + :param unit: integer or float, or msdos string + :param epoch: integer, or Arrow instance, or msdos string + + :raises ImportError: arrow could not be imported during ctor + :raises TimestampError: subcon is not a Construct instance + :raises TimestampError: unit or epoch is a wrong type + + Example:: + + >>> d = Timestamp(Int64ub, 1., 1970) + >>> d.parse(b'\x00\x00\x00\x00ZIz\x00') + + >>> d = Timestamp(Int32ub, "msdos", "msdos") + >>> d.parse(b'H9\x8c"') + + """ + import arrow + + if not isinstance(subcon, Construct): + raise TimestampError("subcon should be Int*, experimentally Float*, or Int32ub when using msdos format") + if not isinstance(unit, (integertypes, float, stringtypes)): + raise TimestampError("unit must be one of: int float string") + if not isinstance(epoch, (integertypes, arrow.Arrow, stringtypes)): + raise TimestampError("epoch must be one of: int Arrow string") + + if unit == "msdos" or epoch == "msdos": + st = BitStruct( + "year" / BitsInteger(7), + "month" / BitsInteger(4), + "day" / BitsInteger(5), + "hour" / BitsInteger(5), + "minute" / BitsInteger(6), + "second" / BitsInteger(5), + ) + class MsdosTimestampAdapter(Adapter): + def _decode(self, obj, context, path): + return arrow.Arrow(1980,1,1).shift(years=obj.year, months=obj.month-1, days=obj.day-1, hours=obj.hour, minutes=obj.minute, seconds=obj.second*2) + def _encode(self, obj, context, path): + t = obj.timetuple() + return Container(year=t.tm_year-1980, month=t.tm_mon, day=t.tm_mday, hour=t.tm_hour, minute=t.tm_min, second=t.tm_sec//2) + macro = MsdosTimestampAdapter(st) + + else: + if isinstance(epoch, integertypes): + epoch = arrow.Arrow(epoch, 1, 1) + class TimestampAdapter(Adapter): + def _decode(self, obj, context, path): + return epoch.shift(seconds=obj*unit) + def _encode(self, obj, context, path): + return int((obj-epoch).total_seconds()/unit) + macro = TimestampAdapter(subcon) + + def _emitfulltype(ksy, bitwise): + return subcon._compilefulltype(ksy, bitwise) + def _emitprimitivetype(ksy, bitwise): + return subcon._compileprimitivetype(ksy, bitwise) + macro._emitfulltype = _emitfulltype + macro._emitprimitivetype = _emitprimitivetype + return macro + + +class Hex(Adapter): + r""" + Adapter for displaying hexadecimal/hexlified representation of integers/bytes/RawCopy dictionaries. + + Parsing results in int-alike bytes-alike or dict-alike object, whose only difference from original is pretty-printing. If you look at the result, you will be presented with its `repr` which remains as-is. If you print it, then you will see its `str` whic is a hexlified representation. Building and sizeof defer to subcon. + + To obtain a hexlified string (like before Hex HexDump changed semantics) use binascii.(un)hexlify on parsed results. + + Example:: + + >>> d = Hex(Int32ub) + >>> obj = d.parse(b"\x00\x00\x01\x02") + >>> obj + 258 + >>> print(obj) + 0x00000102 + + >>> d = Hex(GreedyBytes) + >>> obj = d.parse(b"\x00\x00\x01\x02") + >>> obj + b'\x00\x00\x01\x02' + >>> print(obj) + unhexlify('00000102') + + >>> d = Hex(RawCopy(Int32ub)) + >>> obj = d.parse(b"\x00\x00\x01\x02") + >>> obj + {'data': b'\x00\x00\x01\x02', + 'length': 4, + 'offset1': 0, + 'offset2': 4, + 'value': 258} + >>> print(obj) + unhexlify('00000102') + """ + def _decode(self, obj, context, path): + if isinstance(obj, integertypes): + return HexDisplayedInteger.new(obj, "0%sX" % (2 * self.subcon._sizeof(context, path))) + if isinstance(obj, bytestringtype): + return HexDisplayedBytes(obj) + if isinstance(obj, dict): + return HexDisplayedDict(obj) + return obj + + def _encode(self, obj, context, path): + return obj + + def _emitparse(self, code): + return self.subcon._compileparse(code) + + def _emitseq(self, ksy, bitwise): + return self.subcon._compileseq(ksy, bitwise) + + def _emitprimitivetype(self, ksy, bitwise): + return self.subcon._compileprimitivetype(ksy, bitwise) + + def _emitfulltype(self, ksy, bitwise): + return self.subcon._compilefulltype(ksy, bitwise) + + +class HexDump(Adapter): + r""" + Adapter for displaying hexlified representation of bytes/RawCopy dictionaries. + + Parsing results in bytes-alike or dict-alike object, whose only difference from original is pretty-printing. If you look at the result, you will be presented with its `repr` which remains as-is. If you print it, then you will see its `str` whic is a hexlified representation. Building and sizeof defer to subcon. + + To obtain a hexlified string (like before Hex HexDump changed semantics) use construct.lib.hexdump on parsed results. + + Example:: + + >>> d = HexDump(GreedyBytes) + >>> obj = d.parse(b"\x00\x00\x01\x02") + >>> obj + b'\x00\x00\x01\x02' + >>> print(obj) + hexundump(''' + 0000 00 00 01 02 .... + ''') + + >>> d = HexDump(RawCopy(Int32ub)) + >>> obj = d.parse(b"\x00\x00\x01\x02") + >>> obj + {'data': b'\x00\x00\x01\x02', + 'length': 4, + 'offset1': 0, + 'offset2': 4, + 'value': 258} + >>> print(obj) + hexundump(''' + 0000 00 00 01 02 .... + ''') + """ + def _decode(self, obj, context, path): + if isinstance(obj, bytestringtype): + return HexDumpDisplayedBytes(obj) + if isinstance(obj, dict): + return HexDumpDisplayedDict(obj) + return obj + + def _encode(self, obj, context, path): + return obj + + def _emitparse(self, code): + return self.subcon._compileparse(code) + + def _emitseq(self, ksy, bitwise): + return self.subcon._compileseq(ksy, bitwise) + + def _emitprimitivetype(self, ksy, bitwise): + return self.subcon._compileprimitivetype(ksy, bitwise) + + def _emitfulltype(self, ksy, bitwise): + return self.subcon._compilefulltype(ksy, bitwise) + + +#=============================================================================== +# conditional +#=============================================================================== +class Union(Construct): + r""" + Treats the same data as multiple constructs (similar to C union) so you can look at the data in multiple views. Fields are usually named (so parsed values are inserted into dictionary under same name). + + Parses subcons in sequence, and reverts the stream back to original position after each subcon. Afterwards, advances the stream by selected subcon. Builds from first subcon that has a matching key in given dict. Size is undefined (because parsefrom is not used for building). + + This class does context nesting, meaning its members are given access to a new dictionary where the "_" entry points to the outer context. When parsing, each member gets parsed and subcon parse return value is inserted into context under matching key only if the member was named. When building, the matching entry gets inserted into context before subcon gets build, and if subcon build returns a new value (not None) that gets replaced in the context. + + This class exposes subcons as attributes. You can refer to subcons that were inlined (and therefore do not exist as variable in the namespace) by accessing the struct attributes, under same name. Also note that compiler does not support this feature. See examples. + + This class exposes subcons in the context. You can refer to subcons that were inlined (and therefore do not exist as variable in the namespace) within other inlined fields using the context. Note that you need to use a lambda (`this` expression is not supported). Also note that compiler does not support this feature. See examples. + + .. warning:: If you skip `parsefrom` parameter then stream will be left back at starting offset, not seeked to any common denominator. + + :param parsefrom: how to leave stream after parsing, can be integer index or string name selecting a subcon, or None (leaves stream at initial offset, the default), or context lambda + :param \*subcons: Construct instances, list of members, some can be anonymous + :param \*\*subconskw: Construct instances, list of members (requires Python 3.6) + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises StreamError: stream is not seekable and tellable + :raises UnionError: selector does not match any subcon, or dict given to build does not contain any keys matching any subcon + :raises IndexError: selector does not match any subcon + :raises KeyError: selector does not match any subcon + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = Union(0, + ... "raw" / Bytes(8), + ... "ints" / Int32ub[2], + ... "shorts" / Int16ub[4], + ... "chars" / Byte[8], + ... ) + >>> d.parse(b"12345678") + Container(raw=b'12345678', ints=[825373492, 892745528], shorts=[12594, 13108, 13622, 14136], chars=[49, 50, 51, 52, 53, 54, 55, 56]) + >>> d.build(dict(chars=range(8))) + b'\x00\x01\x02\x03\x04\x05\x06\x07' + + >>> d = Union(None, + ... "animal" / Enum(Byte, giraffe=1), + ... ) + >>> d.animal.giraffe + 'giraffe' + >>> d = Union(None, + ... "chars" / Byte[4], + ... "data" / Bytes(lambda this: this._subcons.chars.sizeof()), + ... ) + >>> d.parse(b"\x01\x02\x03\x04") + Container(chars=[1, 2, 3, 4])(data=b'\x01\x02\x03\x04') + + Alternative syntax, but requires Python 3.6 or any PyPy: + >>> Union(0, raw=Bytes(8), ints=Int32ub[2], shorts=Int16ub[4], chars=Byte[8]) + """ + + def __init__(self, parsefrom, *subcons, **subconskw): + if isinstance(parsefrom, Construct): + raise UnionError("parsefrom should be either: None int str context-function") + super(Union, self).__init__() + self.parsefrom = parsefrom + self.subcons = list(subcons) + list(k/v for k,v in subconskw.items()) + self._subcons = Container((sc.name,sc) for sc in self.subcons if sc.name) + + def __getattr__(self, name): + if name in self._subcons: + return self._subcons[name] + raise AttributeError + + def _parse(self, stream, context, path): + obj = Container() + context = Container(_ = context, _params = context._params, _root = None, _parsing = context._parsing, _building = context._building, _sizing = context._sizing, _subcons = self._subcons, _io = stream, _index = context.get("_index", None)) + context._root = context._.get("_root", context) + fallback = stream_tell(stream, path) + forwards = {} + for i,sc in enumerate(self.subcons): + subobj = sc._parsereport(stream, context, path) + if sc.name: + obj[sc.name] = subobj + context[sc.name] = subobj + forwards[i] = stream_tell(stream, path) + if sc.name: + forwards[sc.name] = stream_tell(stream, path) + stream_seek(stream, fallback, 0, path) + parsefrom = self.parsefrom + if callable(parsefrom): + parsefrom = parsefrom(context) + if parsefrom is not None: + stream_seek(stream, forwards[parsefrom], 0, path) # raises KeyError + return obj + + def _build(self, obj, stream, context, path): + context = Container(_ = context, _params = context._params, _root = None, _parsing = context._parsing, _building = context._building, _sizing = context._sizing, _subcons = self._subcons, _io = stream, _index = context.get("_index", None)) + context._root = context._.get("_root", context) + context.update(obj) + for sc in self.subcons: + if sc.flagbuildnone: + subobj = obj.get(sc.name, None) + elif sc.name in obj: + subobj = obj[sc.name] + else: + continue + + if sc.name: + context[sc.name] = subobj + + buildret = sc._build(subobj, stream, context, path) + if sc.name: + context[sc.name] = buildret + return Container({sc.name:buildret}) + else: + raise UnionError("cannot build, none of subcons were found in the dictionary %r" % (obj, ), path=path) + + def _sizeof(self, context, path): + raise SizeofError("Union builds depending on actual object dict, size is unknown", path=path) + + def _emitparse(self, code): + if callable(self.parsefrom): + raise NotImplementedError("Union does not compile non-constant parsefrom") + fname = "parse_union_%s" % code.allocateId() + block = """ + def %s(io, this): + this = Container(_ = this, _params = this['_params'], _root = None, _parsing = True, _building = False, _sizing = False, _subcons = None, _io = io, _index = this.get('_index', None)) + this['_root'] = this['_'].get('_root', this) + fallback = io.tell() + """ % (fname, ) + if isinstance(self.parsefrom, type(None)): + index = -1 + skipfallback = False + skipforward = True + if isinstance(self.parsefrom, int): + index = self.parsefrom + self.subcons[index] # raises IndexError + skipfallback = True + skipforward = self.subcons[index].sizeof() == self.subcons[-1].sizeof() + if isinstance(self.parsefrom, str): + index = {sc.name:i for i,sc in enumerate(self.subcons) if sc.name}[self.parsefrom] # raises KeyError + skipfallback = True + skipforward = self.subcons[index].sizeof() == self.subcons[-1].sizeof() + + for i,sc in enumerate(self.subcons): + block += """ + %s%s + """ % ("this[%r] = " % sc.name if sc.name else "", sc._compileparse(code)) + if i == index and not skipforward: + block += """ + forward = io.tell() + """ + if i < len(self.subcons)-1: + block += """ + io.seek(fallback) + """ + if not skipfallback: + block += """ + io.seek(fallback) + """ + if not skipforward: + block += """ + io.seek(forward) + """ + block += """ + del this['_'] + del this['_index'] + return this + """ + code.append(block) + return "%s(io, this)" % (fname,) + + +class Select(Construct): + r""" + Selects the first matching subconstruct. + + Parses and builds by literally trying each subcon in sequence until one of them parses or builds without exception. Stream gets reverted back to original position after each failed attempt, but not if parsing succeeds. Size is not defined. + + :param \*subcons: Construct instances, list of members, some can be anonymous + :param \*\*subconskw: Construct instances, list of members (requires Python 3.6) + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises StreamError: stream is not seekable and tellable + :raises SelectError: neither subcon succeded when parsing or building + + Example:: + + >>> d = Select(Int32ub, CString("utf8")) + >>> d.build(1) + b'\x00\x00\x00\x01' + >>> d.build(u"Афон") + b'\xd0\x90\xd1\x84\xd0\xbe\xd0\xbd\x00' + + Alternative syntax, but requires Python 3.6 or any PyPy: + >>> Select(num=Int32ub, text=CString("utf8")) + """ + + def __init__(self, *subcons, **subconskw): + super(Select, self).__init__() + self.subcons = list(subcons) + list(k/v for k,v in subconskw.items()) + self.flagbuildnone = any(sc.flagbuildnone for sc in self.subcons) + + def _parse(self, stream, context, path): + for sc in self.subcons: + fallback = stream_tell(stream, path) + try: + obj = sc._parsereport(stream, context, path) + except ExplicitError: + raise + except ConstructError: + stream_seek(stream, fallback, 0, path) + else: + return obj + raise SelectError("no subconstruct matched", path=path) + + def _build(self, obj, stream, context, path): + for sc in self.subcons: + try: + data = sc.build(obj, **context) + except ExplicitError: + raise + except Exception: + pass + else: + stream_write(stream, data, len(data), path) + return obj + raise SelectError("no subconstruct matched: %s" % (obj,), path=path) + + +def Optional(subcon): + r""" + Makes an optional field. + + Parsing attempts to parse subcon. If sub-parsing fails, returns None and reports success. Building attempts to build subcon. If sub-building fails, writes nothing and reports success. Size is undefined, because whether bytes would be consumed or produced depends on actual data and actual context. + + :param subcon: Construct instance + + Example:: + + Optional <--> Select(subcon, Pass) + + >>> d = Optional(Int64ul) + >>> d.parse(b"12345678") + 4050765991979987505 + >>> d.parse(b"") + None + >>> d.build(1) + b'\x01\x00\x00\x00\x00\x00\x00\x00' + >>> d.build(None) + b'' + """ + return Select(subcon, Pass) + + +def If(condfunc, subcon): + r""" + If-then conditional construct. + + Parsing evaluates condition, if True then subcon is parsed, otherwise just returns None. Building also evaluates condition, if True then subcon gets build from, otherwise does nothing. Size is either same as subcon or 0, depending how condfunc evaluates. + + :param condfunc: bool or context lambda (or a truthy value) + :param subcon: Construct instance, used if condition indicates True + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + If <--> IfThenElse(condfunc, subcon, Pass) + + >>> d = If(this.x > 0, Byte) + >>> d.build(255, x=1) + b'\xff' + >>> d.build(255, x=0) + b'' + """ + macro = IfThenElse(condfunc, subcon, Pass) + def _emitfulltype(ksy, bitwise): + return dict(type=subcon._compileprimitivetype(ksy, bitwise), if_=repr(condfunc).replace("this.","")) + macro._emitfulltype = _emitfulltype + return macro + + +class IfThenElse(Construct): + r""" + If-then-else conditional construct, similar to ternary operator. + + Parsing and building evaluates condition, and defers to either subcon depending on the value. Size is computed the same way. + + :param condfunc: bool or context lambda (or a truthy value) + :param thensubcon: Construct instance, used if condition indicates True + :param elsesubcon: Construct instance, used if condition indicates False + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = IfThenElse(this.x > 0, VarInt, Byte) + >>> d.build(255, dict(x=1)) + b'\xff\x01' + >>> d.build(255, dict(x=0)) + b'\xff' + """ + + def __init__(self, condfunc, thensubcon, elsesubcon): + super(IfThenElse, self).__init__() + self.condfunc = condfunc + self.thensubcon = thensubcon + self.elsesubcon = elsesubcon + self.flagbuildnone = thensubcon.flagbuildnone and elsesubcon.flagbuildnone + + def _parse(self, stream, context, path): + condfunc = self.condfunc + if callable(condfunc): + condfunc = condfunc(context) + sc = self.thensubcon if condfunc else self.elsesubcon + return sc._parsereport(stream, context, path) + + def _build(self, obj, stream, context, path): + condfunc = self.condfunc + if callable(condfunc): + condfunc = condfunc(context) + sc = self.thensubcon if condfunc else self.elsesubcon + return sc._build(obj, stream, context, path) + + def _sizeof(self, context, path): + condfunc = self.condfunc + if callable(condfunc): + condfunc = condfunc(context) + sc = self.thensubcon if condfunc else self.elsesubcon + return sc._sizeof(context, path) + + def _emitparse(self, code): + return "((%s) if (%s) else (%s))" % (self.thensubcon._compileparse(code), self.condfunc, self.elsesubcon._compileparse(code), ) + + def _emitseq(self, ksy, bitwise): + return [ + dict(id="thenvalue", type=self.thensubcon._compileprimitivetype(ksy, bitwise), if_=repr(self.condfunc).replace("this.","")), + dict(id="elsesubcon", type=self.elsesubcon._compileprimitivetype(ksy, bitwise), if_=repr(~self.condfunc).replace("this.","")), + ] + + +class Switch(Construct): + r""" + A conditional branch. + + Parsing and building evaluate keyfunc and select a subcon based on the value and dictionary entries. Dictionary (cases) maps values into subcons. If no case matches then `default` is used (that is Pass by default). Note that `default` is a Construct instance, not a dictionary key. Size is evaluated in same way as parsing and building, by evaluating keyfunc and selecting a field accordingly. + + :param keyfunc: context lambda or constant, that matches some key in cases + :param cases: dict mapping keys to Construct instances + :param default: optional, Construct instance, used when keyfunc is not found in cases, Pass is default value for this parameter, Error is a possible value for this parameter + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = Switch(this.n, { 1:Int8ub, 2:Int16ub, 4:Int32ub }) + >>> d.build(5, n=1) + b'\x05' + >>> d.build(5, n=4) + b'\x00\x00\x00\x05' + + >>> d = Switch(this.n, {}, default=Byte) + >>> d.parse(b"\x01", n=255) + 1 + >>> d.build(1, n=255) + b"\x01" + """ + + def __init__(self, keyfunc, cases, default=None): + if default is None: + default = Pass + super(Switch, self).__init__() + self.keyfunc = keyfunc + self.cases = cases + self.default = default + allcases = list(cases.values()) + [default] + self.flagbuildnone = all(sc.flagbuildnone for sc in allcases) + + def _parse(self, stream, context, path): + keyfunc = self.keyfunc + if callable(keyfunc): + keyfunc = keyfunc(context) + sc = self.cases.get(keyfunc, self.default) + return sc._parsereport(stream, context, path) + + def _build(self, obj, stream, context, path): + keyfunc = self.keyfunc + if callable(keyfunc): + keyfunc = keyfunc(context) + sc = self.cases.get(keyfunc, self.default) + return sc._build(obj, stream, context, path) + + def _sizeof(self, context, path): + try: + keyfunc = self.keyfunc + if callable(keyfunc): + keyfunc = keyfunc(context) + sc = self.cases.get(keyfunc, self.default) + return sc._sizeof(context, path) + + except (KeyError, AttributeError): + raise SizeofError("cannot calculate size, key not found in context", path=path) + + def _emitparse(self, code): + fname = "factory_%s" % code.allocateId() + code.append("%s = {%s}" % (fname, ", ".join("%r : lambda io,this: %s" % (key, sc._compileparse(code)) for key,sc in self.cases.items()), )) + + defaultfname = "compiled_%s" % code.allocateId() + code.append("%s = lambda io,this: %s" % (defaultfname, self.default._compileparse(code), )) + return "%s.get(%s, %s)(io, this)" % (fname, self.keyfunc, defaultfname) + + +class StopIf(Construct): + r""" + Checks for a condition, and stops certain classes (:class:`~construct.core.Struct` :class:`~construct.core.Sequence` :class:`~construct.core.GreedyRange`) from parsing or building further. + + Parsing and building check the condition, and raise StopFieldError if indicated. Size is undefined. + + :param condfunc: bool or context lambda (or truthy value) + + :raises StopFieldError: used internally + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> Struct('x'/Byte, StopIf(this.x == 0), 'y'/Byte) + >>> Sequence('x'/Byte, StopIf(this.x == 0), 'y'/Byte) + >>> GreedyRange(FocusedSeq(0, 'x'/Byte, StopIf(this.x == 0))) + """ + + def __init__(self, condfunc): + super(StopIf, self).__init__() + self.condfunc = condfunc + self.flagbuildnone = True + + def _parse(self, stream, context, path): + condfunc = self.condfunc + if callable(condfunc): + condfunc = condfunc(context) + if condfunc: + raise StopFieldError(path=path) + + def _build(self, obj, stream, context, path): + condfunc = self.condfunc + if callable(condfunc): + condfunc = condfunc(context) + if condfunc: + raise StopFieldError(path=path) + + def _sizeof(self, context, path): + raise SizeofError("StopIf cannot determine size because it depends on actual context which then depends on actual data and outer constructs", path=path) + + def _emitparse(self, code): + code.append(""" + def parse_stopif(condition): + if condition: + raise StopFieldError + """) + return "parse_stopif(%s)" % (self.condfunc,) + + +#=============================================================================== +# alignment and padding +#=============================================================================== +def Padding(length, pattern=b"\x00"): + r""" + Appends null bytes. + + Parsing consumes specified amount of bytes and discards it. Building writes specified pattern byte multiplied into specified length. Size is same as specified. + + :param length: integer or context lambda, length of the padding + :param pattern: b-character, padding pattern, default is \\x00 + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises PaddingError: length was negative + :raises PaddingError: pattern was not bytes (b-character) + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = Padding(4) or Padded(4, Pass) + >>> d.build(None) + b'\x00\x00\x00\x00' + >>> d.parse(b"****") + None + >>> d.sizeof() + 4 + """ + macro = Padded(length, Pass, pattern=pattern) + def _emitprimitivetype(ksy, bitwise): + if not bitwise: + raise NotImplementedError + return "b%s" % (length, ) + def _emitfulltype(ksy, bitwise): + if bitwise: + raise NotImplementedError + return dict(size=length) + macro._emitprimitivetype = _emitprimitivetype + macro._emitfulltype = _emitfulltype + return macro + + +class Padded(Subconstruct): + r""" + Appends additional null bytes to achieve a length. + + Parsing first parses the subcon, then uses stream.tell() to measure how many bytes were read and consumes additional bytes accordingly. Building first builds the subcon, then uses stream.tell() to measure how many bytes were written and produces additional bytes accordingly. Size is same as `length`, but negative amount results in error. Note that subcon can actually be variable size, it is the eventual amount of bytes that is read or written during parsing or building that determines actual padding. + + :param length: integer or context lambda, length of the padding + :param subcon: Construct instance + :param pattern: optional, b-character, padding pattern, default is \\x00 + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises PaddingError: length is negative + :raises PaddingError: subcon read or written more than the length (would cause negative pad) + :raises PaddingError: pattern is not bytes of length 1 + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = Padded(4, Byte) + >>> d.build(255) + b'\xff\x00\x00\x00' + >>> d.parse(_) + 255 + >>> d.sizeof() + 4 + + >>> d = Padded(4, VarInt) + >>> d.build(1) + b'\x01\x00\x00\x00' + >>> d.build(70000) + b'\xf0\xa2\x04\x00' + """ + + def __init__(self, length, subcon, pattern=b"\x00"): + if not isinstance(pattern, bytestringtype) or len(pattern) != 1: + raise PaddingError("pattern expected to be bytes of length 1") + super(Padded, self).__init__(subcon) + self.length = length + self.pattern = pattern + + def _parse(self, stream, context, path): + length = evaluate(self.length, context) + if length < 0: + raise PaddingError("length cannot be negative", path=path) + position1 = stream_tell(stream, path) + obj = self.subcon._parsereport(stream, context, path) + position2 = stream_tell(stream, path) + pad = length - (position2 - position1) + if pad < 0: + raise PaddingError("subcon parsed %d bytes but was allowed only %d" % (position2-position1, length), path=path) + stream_read(stream, pad, path) + return obj + + def _build(self, obj, stream, context, path): + length = evaluate(self.length, context) + if length < 0: + raise PaddingError("length cannot be negative", path=path) + position1 = stream_tell(stream, path) + buildret = self.subcon._build(obj, stream, context, path) + position2 = stream_tell(stream, path) + pad = length - (position2 - position1) + if pad < 0: + raise PaddingError("subcon build %d bytes but was allowed only %d" % (position2-position1, length), path=path) + stream_write(stream, self.pattern * pad, pad, path) + return buildret + + def _sizeof(self, context, path): + try: + length = evaluate(self.length, context) + if length < 0: + raise PaddingError("length cannot be negative", path=path) + return length + except (KeyError, AttributeError): + raise SizeofError("cannot calculate size, key not found in context", path=path) + + def _emitparse(self, code): + return "(%s, read_bytes(io, (%s)-(%s) ))[0]" % (self.subcon._compileparse(code), self.length, self.subcon.sizeof()) + + def _emitfulltype(self, ksy, bitwise): + return dict(size=self.length, type=self.subcon._compileprimitivetype(ksy, bitwise)) + + +class Aligned(Subconstruct): + r""" + Appends additional null bytes to achieve a length that is shortest multiple of a modulus. + + Note that subcon can actually be variable size, it is the eventual amount of bytes that is read or written during parsing or building that determines actual padding. + + Parsing first parses subcon, then consumes an amount of bytes to sum up to specified length, and discards it. Building first builds subcon, then writes specified pattern byte to sum up to specified length. Size is subcon size plus modulo remainder, unless SizeofError was raised. + + :param modulus: integer or context lambda, modulus to final length + :param subcon: Construct instance + :param pattern: optional, b-character, padding pattern, default is \\x00 + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises PaddingError: modulus was less than 2 + :raises PaddingError: pattern was not bytes (b-character) + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = Aligned(4, Int16ub) + >>> d.parse(b'\x00\x01\x00\x00') + 1 + >>> d.sizeof() + 4 + """ + + def __init__(self, modulus, subcon, pattern=b"\x00"): + if not isinstance(pattern, bytestringtype) or len(pattern) != 1: + raise PaddingError("pattern expected to be bytes character") + super(Aligned, self).__init__(subcon) + self.modulus = modulus + self.pattern = pattern + + def _parse(self, stream, context, path): + modulus = self.modulus(context) if callable(self.modulus) else self.modulus + if modulus < 2: + raise PaddingError("expected modulo 2 or greater", path=path) + position1 = stream_tell(stream, path) + obj = self.subcon._parsereport(stream, context, path) + position2 = stream_tell(stream, path) + pad = -(position2 - position1) % modulus + stream_read(stream, pad, path) + return obj + + def _build(self, obj, stream, context, path): + modulus = self.modulus(context) if callable(self.modulus) else self.modulus + if modulus < 2: + raise PaddingError("expected modulo 2 or greater", path=path) + position1 = stream_tell(stream, path) + buildret = self.subcon._build(obj, stream, context, path) + position2 = stream_tell(stream, path) + pad = -(position2 - position1) % modulus + stream_write(stream, self.pattern * pad, pad, path) + return buildret + + def _sizeof(self, context, path): + try: + modulus = self.modulus(context) if callable(self.modulus) else self.modulus + if modulus < 2: + raise PaddingError("expected modulo 2 or greater", path=path) + subconlen = self.subcon._sizeof(context, path) + return subconlen + (-subconlen % modulus) + except (KeyError, AttributeError): + raise SizeofError("cannot calculate size, key not found in context", path=path) + + def _emitparse(self, code): + return "(%s, read_bytes(io, -(%s) %% (%s) ))[0]" % (self.subcon._compileparse(code), self.subcon.sizeof(), self.modulus, ) + + +def AlignedStruct(modulus, *subcons, **subconskw): + r""" + Makes a structure where each field is aligned to the same modulus (it is a struct of aligned fields, NOT an aligned struct). + + See :class:`~construct.core.Aligned` and :class:`~construct.core.Struct` for semantics and raisable exceptions. + + :param modulus: integer or context lambda, passed to each member + :param \*subcons: Construct instances, list of members, some can be anonymous + :param \*\*subconskw: Construct instances, list of members (requires Python 3.6) + + Example:: + + >>> d = AlignedStruct(4, "a"/Int8ub, "b"/Int16ub) + >>> d.build(dict(a=0xFF,b=0xFFFF)) + b'\xff\x00\x00\x00\xff\xff\x00\x00' + """ + subcons = list(subcons) + list(k/v for k,v in subconskw.items()) + return Struct(*[sc.name / Aligned(modulus, sc) for sc in subcons]) + + +def BitStruct(*subcons, **subconskw): + r""" + Makes a structure inside a Bitwise. + + See :class:`~construct.core.Bitwise` and :class:`~construct.core.Struct` for semantics and raisable exceptions. + + :param \*subcons: Construct instances, list of members, some can be anonymous + :param \*\*subconskw: Construct instances, list of members (requires Python 3.6) + + Example:: + + BitStruct <--> Bitwise(Struct(...)) + + >>> d = BitStruct( + ... "a" / Flag, + ... "b" / Nibble, + ... "c" / BitsInteger(10), + ... "d" / Padding(1), + ... ) + >>> d.parse(b"\xbe\xef") + Container(a=True)(b=7)(c=887)(d=None) + >>> d.sizeof() + 2 + """ + return Bitwise(Struct(*subcons, **subconskw)) + + +#=============================================================================== +# stream manipulation +#=============================================================================== +class Pointer(Subconstruct): + r""" + Jumps in the stream forth and back for one field. + + Parsing and building seeks the stream to new location, processes subcon, and seeks back to original location. Size is defined as 0 but that does not mean no bytes are written into the stream. + + Offset can be positive, indicating a position from stream beginning forward, or negative, indicating a position from EOF backwards. + + :param offset: integer or context lambda, positive or negative + :param subcon: Construct instance + :param stream: None to use original stream (default), or context lambda to provide a different stream + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises StreamError: stream is not seekable and tellable + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = Pointer(8, Bytes(1)) + >>> d.parse(b"abcdefghijkl") + b'i' + >>> d.build(b"Z") + b'\x00\x00\x00\x00\x00\x00\x00\x00Z' + """ + + def __init__(self, offset, subcon, stream=None): + super(Pointer, self).__init__(subcon) + self.offset = offset + self.stream = stream + + def _parse(self, stream, context, path): + offset = evaluate(self.offset, context) + stream = evaluate(self.stream, context) or stream + fallback = stream_tell(stream, path) + stream_seek(stream, offset, 2 if offset < 0 else 0, path) + obj = self.subcon._parsereport(stream, context, path) + stream_seek(stream, fallback, 0, path) + return obj + + def _build(self, obj, stream, context, path): + offset = evaluate(self.offset, context) + stream = evaluate(self.stream, context) or stream + fallback = stream_tell(stream, path) + stream_seek(stream, offset, 2 if offset < 0 else 0, path) + buildret = self.subcon._build(obj, stream, context, path) + stream_seek(stream, fallback, 0, path) + return buildret + + def _sizeof(self, context, path): + return 0 + + def _emitparse(self, code): + code.append(""" + def parse_pointer(io, offset, func): + fallback = io.tell() + io.seek(offset, 2 if offset < 0 else 0) + obj = func() + io.seek(fallback) + return obj + """) + return "parse_pointer(io, %s, lambda: %s)" % (self.offset, self.subcon._compileparse(code),) + + def _emitprimitivetype(self, ksy, bitwise): + offset = self.offset.__getfield__() if callable(self.offset) else self.offset + name = "instance_%s" % ksy.allocateId() + ksy.instances[name] = dict(pos=offset, **self.subcon._compilefulltype(ksy, bitwise)) + return name + + +class Peek(Subconstruct): + r""" + Peeks at the stream. + + Parsing sub-parses (and returns None if failed), then reverts stream to original position. Building does nothing (its NOT deferred). Size is defined as 0 because there is no building. + + This class is used in :class:`~construct.core.Union` class to parse each member. + + :param subcon: Construct instance + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises StreamError: stream is not seekable and tellable + + Example:: + + >>> d = Sequence(Peek(Int8ub), Peek(Int16ub)) + >>> d.parse(b"\x01\x02") + [1, 258] + >>> d.sizeof() + 0 + """ + + def __init__(self, subcon): + super(Peek, self).__init__(subcon) + self.flagbuildnone = True + + def _parse(self, stream, context, path): + fallback = stream_tell(stream, path) + try: + return self.subcon._parsereport(stream, context, path) + except ExplicitError: + raise + except ConstructError: + pass + finally: + stream_seek(stream, fallback, 0, path) + + def _build(self, obj, stream, context, path): + return obj + + def _sizeof(self, context, path): + return 0 + + def _emitparse(self, code): + code.append(""" + def parse_peek(io, func): + fallback = io.tell() + try: + return func() + except ExplicitError: + raise + except ConstructError: + pass + finally: + io.seek(fallback) + """) + return "parse_peek(io, lambda: %s)" % (self.subcon._compileparse(code),) + + +class Seek(Construct): + r""" + Seeks the stream. + + Parsing and building seek the stream to given location (and whence), and return stream.seek() return value. Size is not defined. + + .. seealso:: Analog :class:`~construct.core.Pointer` wrapper that has same side effect but also processes a subcon, and also seeks back. + + :param at: integer or context lambda, where to jump to + :param whence: optional, integer or context lambda, is the offset from beginning (0) or from current position (1) or from EOF (2), default is 0 + + :raises StreamError: stream is not seekable + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = (Seek(5) >> Byte) + >>> d.parse(b"01234x") + [5, 120] + + >>> d = (Bytes(10) >> Seek(5) >> Byte) + >>> d.build([b"0123456789", None, 255]) + b'01234\xff6789' + """ + + def __init__(self, at, whence=0): + super(Seek, self).__init__() + self.at = at + self.whence = whence + self.flagbuildnone = True + + def _parse(self, stream, context, path): + at = self.at(context) if callable(self.at) else self.at + whence = self.whence(context) if callable(self.whence) else self.whence + return stream_seek(stream, at, whence, path) + + def _build(self, obj, stream, context, path): + at = self.at(context) if callable(self.at) else self.at + whence = self.whence(context) if callable(self.whence) else self.whence + return stream_seek(stream, at, whence, path) + + def _sizeof(self, context, path): + raise SizeofError("Seek only moves the stream, size is not meaningful", path=path) + + def _emitparse(self, code): + return "io.seek(%s, %s)" % (self.at, self.whence, ) + + +@singleton +class Tell(Construct): + r""" + Tells the stream. + + Parsing and building return current stream offset using using stream.tell(). Size is defined as 0 because parsing and building does not consume or add into the stream. + + Tell is useful for adjusting relative offsets to absolute positions, or to measure sizes of Constructs. To get an absolute pointer, use a Tell plus a relative offset. To get a size, place two Tells and measure their difference using a Compute field. However, its recommended to use :class:`~construct.core.RawCopy` instead of manually extracting two positions and computing difference. + + :raises StreamError: stream is not tellable + + Example:: + + >>> d = Struct("num"/VarInt, "offset"/Tell) + >>> d.parse(b"X") + Container(num=88)(offset=1) + >>> d.build(dict(num=88)) + b'X' + """ + + def __init__(self): + super(self.__class__, self).__init__() + self.flagbuildnone = True + + def _parse(self, stream, context, path): + return stream_tell(stream, path) + + def _build(self, obj, stream, context, path): + return stream_tell(stream, path) + + def _sizeof(self, context, path): + return 0 + + def _emitparse(self, code): + return "io.tell()" + + +@singleton +class Pass(Construct): + r""" + No-op construct, useful as default cases for Switch and Enum. + + Parsing returns None. Building does nothing. Size is 0 by definition. + + Example:: + + >>> Pass.parse(b"") + None + >>> Pass.build(None) + b'' + >>> Pass.sizeof() + 0 + """ + + def __init__(self): + super(self.__class__, self).__init__() + self.flagbuildnone = True + + def _parse(self, stream, context, path): + return None + + def _build(self, obj, stream, context, path): + return obj + + def _sizeof(self, context, path): + return 0 + + def _emitparse(self, code): + return "None" + + def _emitfulltype(self, ksy, bitwise): + return dict(size=0) + + +@singleton +class Terminated(Construct): + r""" + Asserts end of stream (EOF). You can use it to ensure no more unparsed data follows in the stream. + + Parsing checks if stream reached EOF, and raises TerminatedError if not. Building does nothing. Size is defined as 0 because parsing and building does not consume or add into the stream, as far as other constructs see it. + + :raises TerminatedError: stream not at EOF when parsing + + Example:: + + >>> Terminated.parse(b"") + None + >>> Terminated.parse(b"remaining") + construct.core.TerminatedError: expected end of stream + """ + + def __init__(self): + super(self.__class__, self).__init__() + self.flagbuildnone = True + + def _parse(self, stream, context, path): + if stream.read(1): + raise TerminatedError("expected end of stream", path=path) + + def _build(self, obj, stream, context, path): + return obj + + def _sizeof(self, context, path): + raise SizeofError(path=path) + + +#=============================================================================== +# tunneling and byte/bit swapping +#=============================================================================== +class RawCopy(Subconstruct): + r""" + Used to obtain byte representation of a field (aside of object value). + + Returns a dict containing both parsed subcon value, the raw bytes that were consumed by subcon, starting and ending offset in the stream, and amount in bytes. Builds either from raw bytes representation or a value used by subcon. Size is same as subcon. + + Object is a dictionary with either "data" or "value" keys, or both. + + :param subcon: Construct instance + + :raises StreamError: stream is not seekable and tellable + :raises RawCopyError: building and neither data or value was given + :raises StringError: building from non-bytes value, perhaps unicode + + Example:: + + >>> d = RawCopy(Byte) + >>> d.parse(b"\xff") + Container(data=b'\xff')(value=255)(offset1=0)(offset2=1)(length=1) + >>> d.build(dict(data=b"\xff")) + '\xff' + >>> d.build(dict(value=255)) + '\xff' + """ + + def _parse(self, stream, context, path): + offset1 = stream_tell(stream, path) + obj = self.subcon._parsereport(stream, context, path) + offset2 = stream_tell(stream, path) + stream_seek(stream, offset1, 0, path) + data = stream_read(stream, offset2-offset1, path) + return Container(data=data, value=obj, offset1=offset1, offset2=offset2, length=(offset2-offset1)) + + def _build(self, obj, stream, context, path): + if obj is None and self.subcon.flagbuildnone: + obj = dict(value=None) + if 'data' in obj: + data = obj['data'] + offset1 = stream_tell(stream, path) + stream_write(stream, data, len(data), path) + offset2 = stream_tell(stream, path) + return Container(obj, data=data, offset1=offset1, offset2=offset2, length=(offset2-offset1)) + if 'value' in obj: + value = obj['value'] + offset1 = stream_tell(stream, path) + buildret = self.subcon._build(value, stream, context, path) + value = value if buildret is None else buildret + offset2 = stream_tell(stream, path) + stream_seek(stream, offset1, 0, path) + data = stream_read(stream, offset2-offset1, path) + return Container(obj, data=data, value=value, offset1=offset1, offset2=offset2, length=(offset2-offset1)) + raise RawCopyError('RawCopy cannot build, both data and value keys are missing', path=path) + + +def ByteSwapped(subcon): + r""" + Swaps the byte order within boundaries of given subcon. Requires a fixed sized subcon. + + :param subcon: Construct instance, subcon on top of byte swapped bytes + + :raises SizeofError: ctor or compiler could not compute subcon size + + See :class:`~construct.core.Transformed` and :class:`~construct.core.Restreamed` for raisable exceptions. + + Example:: + + Int24ul <--> ByteSwapped(Int24ub) <--> BytesInteger(3, swapped=True) <--> ByteSwapped(BytesInteger(3)) + """ + + size = subcon.sizeof() + return Transformed(subcon, swapbytes, size, swapbytes, size) + + +def BitsSwapped(subcon): + r""" + Swaps the bit order within each byte within boundaries of given subcon. Does NOT require a fixed sized subcon. + + :param subcon: Construct instance, subcon on top of bit swapped bytes + + :raises SizeofError: compiler could not compute subcon size + + See :class:`~construct.core.Transformed` and :class:`~construct.core.Restreamed` for raisable exceptions. + + Example:: + + >>> d = Bitwise(Bytes(8)) + >>> d.parse(b"\x01") + '\x00\x00\x00\x00\x00\x00\x00\x01' + >>>> BitsSwapped(d).parse(b"\x01") + '\x01\x00\x00\x00\x00\x00\x00\x00' + """ + + try: + size = subcon.sizeof() + return Transformed(subcon, swapbitsinbytes, size, swapbitsinbytes, size) + except SizeofError: + return Restreamed(subcon, swapbitsinbytes, 1, swapbitsinbytes, 1, lambda n: n) + + +class Prefixed(Subconstruct): + r""" + Prefixes a field with byte count. + + Parses the length field. Then reads that amount of bytes, and parses subcon using only those bytes. Constructs that consume entire remaining stream are constrained to consuming only the specified amount of bytes (a substream). When building, data gets prefixed by its length. Optionally, length field can include its own size. Size is the sum of both fields sizes, unless either raises SizeofError. + + Analog to :class:`~construct.core.PrefixedArray` which prefixes with an element count, instead of byte count. Semantics is similar but implementation is different. + + :class:`~construct.core.VarInt` is recommended for new protocols, as it is more compact and never overflows. + + :param lengthfield: Construct instance, field used for storing the length + :param subcon: Construct instance, subcon used for storing the value + :param includelength: optional, bool, whether length field should include its own size, default is False + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + + Example:: + + >>> d = Prefixed(VarInt, GreedyRange(Int32ul)) + >>> d.parse(b"\x08abcdefgh") + [1684234849, 1751606885] + + >>> d = PrefixedArray(VarInt, Int32ul) + >>> d.parse(b"\x02abcdefgh") + [1684234849, 1751606885] + """ + + def __init__(self, lengthfield, subcon, includelength=False): + super(Prefixed, self).__init__(subcon) + self.lengthfield = lengthfield + self.includelength = includelength + + def _parse(self, stream, context, path): + length = self.lengthfield._parsereport(stream, context, path) + if self.includelength: + length -= self.lengthfield._sizeof(context, path) + data = stream_read(stream, length, path) + if self.subcon is GreedyBytes: + return data + if type(self.subcon) is GreedyString: + return data.decode(self.subcon.encoding) + return self.subcon._parsereport(io.BytesIO(data), context, path) + + def _build(self, obj, stream, context, path): + stream2 = io.BytesIO() + buildret = self.subcon._build(obj, stream2, context, path) + data = stream2.getvalue() + length = len(data) + if self.includelength: + length += self.lengthfield._sizeof(context, path) + self.lengthfield._build(length, stream, context, path) + stream_write(stream, data, len(data), path) + return buildret + + def _sizeof(self, context, path): + return self.lengthfield._sizeof(context, path) + self.subcon._sizeof(context, path) + + def _actualsize(self, stream, context, path): + position1 = stream_tell(stream, path) + length = self.lengthfield._parse(stream, context, path) + if self.includelength: + length -= self.lengthfield._sizeof(context, path) + position2 = stream_tell(stream, path) + return (position2-position1) + length + + def _emitparse(self, code): + sub = self.lengthfield.sizeof() if self.includelength else 0 + return "restream(read_bytes(io, (%s)-(%s)), lambda io: %s)" % (self.lengthfield._compileparse(code), sub, self.subcon._compileparse(code), ) + + def _emitseq(self, ksy, bitwise): + return [ + dict(id="lengthfield", type=self.lengthfield._compileprimitivetype(ksy, bitwise)), + dict(id="data", size="lengthfield", type=self.subcon._compileprimitivetype(ksy, bitwise)), + ] + + +def PrefixedArray(countfield, subcon): + r""" + Prefixes an array with item count (as opposed to prefixed by byte count, see :class:`~construct.core.Prefixed`). + + :class:`~construct.core.VarInt` is recommended for new protocols, as it is more compact and never overflows. + + :param countfield: Construct instance, field used for storing the element count + :param subcon: Construct instance, subcon used for storing each element + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises RangeError: consumed or produced too little elements + + Example:: + + >>> d = Prefixed(VarInt, GreedyRange(Int32ul)) + >>> d.parse(b"\x08abcdefgh") + [1684234849, 1751606885] + + >>> d = PrefixedArray(VarInt, Int32ul) + >>> d.parse(b"\x02abcdefgh") + [1684234849, 1751606885] + """ + macro = FocusedSeq("items", + "count" / Rebuild(countfield, len_(this.items)), + "items" / subcon[this.count], + ) + def _emitparse(code): + return "ListContainer((%s) for i in range(%s))" % (subcon._compileparse(code), countfield._compileparse(code), ) + macro._emitparse = _emitparse + def _actualsize(self, stream, context, path): + position1 = stream_tell(stream, path) + count = countfield._parse(stream, context, path) + position2 = stream_tell(stream, path) + return (position2-position1) + count * subcon._sizeof(context, path) + macro._actualsize = _actualsize + def _emitseq(ksy, bitwise): + return [ + dict(id="countfield", type=countfield._compileprimitivetype(ksy, bitwise)), + dict(id="data", type=subcon._compileprimitivetype(ksy, bitwise), repeat="expr", repeat_expr="countfield"), + ] + macro._emitseq = _emitseq + return macro + + +class FixedSized(Subconstruct): + r""" + Restricts parsing to specified amount of bytes. + + Parsing reads `length` bytes, then defers to subcon using new BytesIO with said bytes. Building builds the subcon using new BytesIO, then writes said data and additional null bytes accordingly. Size is same as `length`, although negative amount raises an error as well. + + :param length: integer or context lambda, total amount of bytes (both data and padding) + :param subcon: Construct instance + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises PaddingError: length is negative + :raises PaddingError: subcon written more bytes than entire length (negative padding) + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = FixedSized(10, Byte) + >>> d.parse(b'\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00') + 255 + >>> d.build(255) + b'\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00' + >>> d.sizeof() + 10 + """ + + def __init__(self, length, subcon): + super(FixedSized, self).__init__(subcon) + self.length = length + + def _parse(self, stream, context, path): + length = evaluate(self.length, context) + if length < 0: + raise PaddingError("length cannot be negative", path=path) + data = stream_read(stream, length, path) + if self.subcon is GreedyBytes: + return data + if type(self.subcon) is GreedyString: + return data.decode(self.subcon.encoding) + return self.subcon._parsereport(io.BytesIO(data), context, path) + + def _build(self, obj, stream, context, path): + length = evaluate(self.length, context) + if length < 0: + raise PaddingError("length cannot be negative", path=path) + stream2 = io.BytesIO() + buildret = self.subcon._build(obj, stream2, context, path) + data = stream2.getvalue() + pad = length - len(data) + if pad < 0: + raise PaddingError("subcon build %d bytes but was allowed only %d" % (len(data), length), path=path) + stream_write(stream, data, len(data), path) + stream_write(stream, bytes(pad), pad, path) + return buildret + + def _sizeof(self, context, path): + length = evaluate(self.length, context) + if length < 0: + raise PaddingError("length cannot be negative", path=path) + return length + + def _emitparse(self, code): + return "restream(read_bytes(io, %s), lambda io: %s)" % (self.length, self.subcon._compileparse(code), ) + + def _emitfulltype(self, ksy, bitwise): + return dict(size=repr(self.length).replace("this.",""), **self.subcon._compilefulltype(ksy, bitwise)) + + +class NullTerminated(Subconstruct): + r""" + Restricts parsing to bytes preceding a null byte. + + Parsing reads one byte at a time and accumulates it with previous bytes. When term was found, (by default) consumes but discards the term. When EOF was found, (by default) raises same StreamError exception. Then subcon is parsed using new BytesIO made with said data. Building builds the subcon and then writes the term. Size is undefined. + + The term can be multiple bytes, to support string classes with UTF16/32 encodings. + + :param subcon: Construct instance + :param term: optional, bytes, terminator byte-string, default is \x00 single null byte + :param include: optional, bool, if to include terminator in resulting data, default is False + :param consume: optional, bool, if to consume terminator or leave it in the stream, default is True + :param require: optional, bool, if EOF results in failure or not, default is True + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises StreamError: encountered EOF but require is not disabled + :raises PaddingError: terminator is less than 1 bytes in length + + Example:: + + >>> d = NullTerminated(Byte) + >>> d.parse(b'\xff\x00') + 255 + >>> d.build(255) + b'\xff\x00' + """ + + def __init__(self, subcon, term=b"\x00", include=False, consume=True, require=True): + super(NullTerminated, self).__init__(subcon) + self.term = term + self.include = include + self.consume = consume + self.require = require + + def _parse(self, stream, context, path): + term = self.term + unit = len(term) + if unit < 1: + raise PaddingError("NullTerminated term must be at least 1 byte", path=path) + data = b'' + while True: + try: + b = stream_read(stream, unit, path) + except StreamError: + if self.require: + raise + else: + break + if b == term: + if self.include: + data += b + if not self.consume: + stream_seek(stream, -unit, 1, path) + break + data += b + if self.subcon is GreedyBytes: + return data + if type(self.subcon) is GreedyString: + return data.decode(self.subcon.encoding) + return self.subcon._parsereport(io.BytesIO(data), context, path) + + def _build(self, obj, stream, context, path): + buildret = self.subcon._build(obj, stream, context, path) + stream_write(stream, self.term, len(self.term), path) + return buildret + + def _sizeof(self, context, path): + raise SizeofError(path=path) + + def _emitfulltype(self, ksy, bitwise): + if len(self.term) > 1: + raise NotImplementedError + return dict(terminator=byte2int(self.term), include=self.include, consume=self.consume, eos_error=self.require, **self.subcon._compilefulltype(ksy, bitwise)) + + +class NullStripped(Subconstruct): + r""" + Restricts parsing to bytes except padding left of EOF. + + Parsing reads entire stream, then strips the data from right to left of null bytes, then parses subcon using new BytesIO made of said data. Building defers to subcon as-is. Size is undefined, because it reads till EOF. + + The pad can be multiple bytes, to support string classes with UTF16/32 encodings. + + :param subcon: Construct instance + :param pad: optional, bytes, padding byte-string, default is \x00 single null byte + + :raises PaddingError: pad is less than 1 bytes in length + + Example:: + + >>> d = NullStripped(Byte) + >>> d.parse(b'\xff\x00\x00') + 255 + >>> d.build(255) + b'\xff' + """ + + def __init__(self, subcon, pad=b"\x00"): + super(NullStripped, self).__init__(subcon) + self.pad = pad + + def _parse(self, stream, context, path): + pad = self.pad + unit = len(pad) + if unit < 1: + raise PaddingError("NullStripped pad must be at least 1 byte", path=path) + data = stream_read_entire(stream, path) + if unit == 1: + data = data.rstrip(pad) + else: + tailunit = len(data) % unit + end = len(data) + if tailunit and data[-tailunit:] == pad[:tailunit]: + end -= tailunit + while end-unit >= 0 and data[end-unit:end] == pad: + end -= unit + data = data[:end] + if self.subcon is GreedyBytes: + return data + if type(self.subcon) is GreedyString: + return data.decode(self.subcon.encoding) + return self.subcon._parsereport(io.BytesIO(data), context, path) + + def _build(self, obj, stream, context, path): + return self.subcon._build(obj, stream, context, path) + + def _sizeof(self, context, path): + raise SizeofError(path=path) + + def _emitfulltype(self, ksy, bitwise): + if len(self.pad) > 1: + raise NotImplementedError + return dict(pad_right=byte2int(self.pad), **self.subcon._compilefulltype(ksy, bitwise)) + + +class RestreamData(Subconstruct): + r""" + Parses a field on external data (but does not build). + + Parsing defers to subcon, but provides it a separate BytesIO stream based on data provided by datafunc (a bytes literal or another BytesIO stream or Construct instances that returns bytes or context lambda). Building does nothing. Size is 0 because as far as other fields see it, this field does not produce or consume any bytes from the stream. + + :param datafunc: bytes or BytesIO or Construct instance (that parses into bytes) or context lambda, provides data for subcon to parse from + :param subcon: Construct instance + + Can propagate any exception from the lambdas, possibly non-ConstructError. + + Example:: + + >>> d = RestreamData(b"\x01", Int8ub) + >>> d.parse(b"") + 1 + >>> d.build(0) + b'' + + >>> d = RestreamData(NullTerminated(GreedyBytes), Int16ub) + >>> d.parse(b"\x01\x02\x00") + 0x0102 + >>> d = RestreamData(FixedSized(2, GreedyBytes), Int16ub) + >>> d.parse(b"\x01\x02\x00") + 0x0102 + """ + + def __init__(self, datafunc, subcon): + super(RestreamData, self).__init__(subcon) + self.datafunc = datafunc + self.flagbuildnone = True + + def _parse(self, stream, context, path): + data = evaluate(self.datafunc, context) + if isinstance(data, bytestringtype): + stream2 = io.BytesIO(data) + if isinstance(data, io.BytesIO): + stream2 = data + if isinstance(data, Construct): + stream2 = io.BytesIO(data._parsereport(stream, context, path)) + return self.subcon._parsereport(stream2, context, path) + + def _build(self, obj, stream, context, path): + return obj + + def _sizeof(self, context, path): + return 0 + + def _emitparse(self, code): + return "restream(%r, lambda io: %s)" % (self.datafunc, self.subcon._compileparse(code), ) + + +class Transformed(Subconstruct): + r""" + Transforms bytes between the underlying stream and the (fixed-sized) subcon. + + Parsing reads a specified amount (or till EOF), processes data using a bytes-to-bytes decoding function, then parses subcon using those data. Building does build subcon into separate bytes, then processes it using encoding bytes-to-bytes function, then writes those data into main stream. Size is reported as `decodeamount` or `encodeamount` if those are equal, otherwise its SizeofError. + + Used internally to implement :class:`~construct.core.Bitwise` :class:`~construct.core.Bytewise` :class:`~construct.core.ByteSwapped` :class:`~construct.core.BitsSwapped` . + + Possible use-cases include encryption, obfuscation, byte-level encoding. + + .. warning:: Remember that subcon must consume (or produce) an amount of bytes that is same as `decodeamount` (or `encodeamount`). + + .. warning:: Do NOT use seeking/telling classes inside Transformed context. + + :param subcon: Construct instance + :param decodefunc: bytes-to-bytes function, applied before parsing subcon + :param decodeamount: integer, amount of bytes to read + :param encodefunc: bytes-to-bytes function, applied after building subcon + :param encodeamount: integer, amount of bytes to write + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises StreamError: subcon build and encoder transformed more or less than `encodeamount` bytes, if amount is specified + :raises StringError: building from non-bytes value, perhaps unicode + + Can propagate any exception from the lambdas, possibly non-ConstructError. + + Example:: + + >>> d = Transformed(Bytes(16), bytes2bits, 2, bits2bytes, 2) + >>> d.parse(b"\x00\x00") + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + + >>> d = Transformed(GreedyBytes, bytes2bits, None, bits2bytes, None) + >>> d.parse(b"\x00\x00") + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + """ + + def __init__(self, subcon, decodefunc, decodeamount, encodefunc, encodeamount): + super(Transformed, self).__init__(subcon) + self.decodefunc = decodefunc + self.decodeamount = decodeamount + self.encodefunc = encodefunc + self.encodeamount = encodeamount + + def _parse(self, stream, context, path): + if isinstance(self.decodeamount, type(None)): + data = stream_read_entire(stream, path) + if isinstance(self.decodeamount, integertypes): + data = stream_read(stream, self.decodeamount, path) + data = self.decodefunc(data) + if self.subcon is GreedyBytes: + return data + if type(self.subcon) is GreedyString: + return data.decode(self.subcon.encoding) + return self.subcon._parsereport(io.BytesIO(data), context, path) + + def _build(self, obj, stream, context, path): + stream2 = io.BytesIO() + buildret = self.subcon._build(obj, stream2, context, path) + data = stream2.getvalue() + data = self.encodefunc(data) + if isinstance(self.encodeamount, integertypes): + if len(data) != self.encodeamount: + raise StreamError("encoding transformation produced wrong amount of bytes, %s instead of expected %s" % (len(data), self.encodeamount, ), path=path) + stream_write(stream, data, len(data), path) + return buildret + + def _sizeof(self, context, path): + if self.decodeamount is None or self.encodeamount is None: + raise SizeofError(path=path) + if self.decodeamount == self.encodeamount: + return self.encodeamount + raise SizeofError(path=path) + + +class Restreamed(Subconstruct): + r""" + Transforms bytes between the underlying stream and the (variable-sized) subcon. + + Used internally to implement :class:`~construct.core.Bitwise` :class:`~construct.core.Bytewise` :class:`~construct.core.ByteSwapped` :class:`~construct.core.BitsSwapped` . + + .. warning:: Remember that subcon must consume or produce an amount of bytes that is a multiple of encoding or decoding units. For example, in a Bitwise context you should process a multiple of 8 bits or the stream will fail during parsing/building. + + .. warning:: Do NOT use seeking/telling classes inside Restreamed context. + + :param subcon: Construct instance + :param decoder: bytes-to-bytes function, used on data chunks when parsing + :param decoderunit: integer, decoder takes chunks of this size + :param encoder: bytes-to-bytes function, used on data chunks when building + :param encoderunit: integer, encoder takes chunks of this size + :param sizecomputer: function that computes amount of bytes outputed + + Can propagate any exception from the lambda, possibly non-ConstructError. + Can also raise arbitrary exceptions in RestreamedBytesIO implementation. + + Example:: + + Bitwise <--> Restreamed(subcon, bits2bytes, 8, bytes2bits, 1, lambda n: n//8) + Bytewise <--> Restreamed(subcon, bytes2bits, 1, bits2bytes, 8, lambda n: n*8) + """ + + def __init__(self, subcon, decoder, decoderunit, encoder, encoderunit, sizecomputer): + super(Restreamed, self).__init__(subcon) + self.decoder = decoder + self.decoderunit = decoderunit + self.encoder = encoder + self.encoderunit = encoderunit + self.sizecomputer = sizecomputer + + def _parse(self, stream, context, path): + stream2 = RestreamedBytesIO(stream, self.decoder, self.decoderunit, self.encoder, self.encoderunit) + obj = self.subcon._parsereport(stream2, context, path) + stream2.close() + return obj + + def _build(self, obj, stream, context, path): + stream2 = RestreamedBytesIO(stream, self.decoder, self.decoderunit, self.encoder, self.encoderunit) + buildret = self.subcon._build(obj, stream2, context, path) + stream2.close() + return obj + + def _sizeof(self, context, path): + if self.sizecomputer is None: + raise SizeofError("Restreamed cannot calculate size without a sizecomputer", path=path) + else: + return self.sizecomputer(self.subcon._sizeof(context, path)) + + +class ProcessXor(Subconstruct): + r""" + Transforms bytes between the underlying stream and the subcon. + + Used internally by KaitaiStruct compiler, when translating `process: xor` tags. + + Parsing reads till EOF, xors data with the pad, then feeds that data into subcon. Building first builds the subcon into separate BytesIO stream, xors data with the pad, then writes that data into the main stream. Size is the same as subcon, unless it raises SizeofError. + + :param padfunc: integer or bytes or context lambda, single or multiple bytes to xor data with + :param subcon: Construct instance + + :raises StringError: pad is not integer or bytes + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = ProcessXor(0xf0 or b'\xf0', Int16ub) + >>> d.parse(b"\x00\xff") + 0xf00f + >>> d.sizeof() + 2 + """ + + def __init__(self, padfunc, subcon): + super(ProcessXor, self).__init__(subcon) + self.padfunc = padfunc + + def _parse(self, stream, context, path): + pad = evaluate(self.padfunc, context) + if not isinstance(pad, (integertypes, bytestringtype)): + raise StringError("ProcessXor needs integer or bytes pad", path=path) + if isinstance(pad, bytestringtype) and len(pad) == 1: + pad = byte2int(pad) + data = stream_read_entire(stream, path) + if isinstance(pad, integertypes): + if not (pad == 0): + data = integers2bytes( (b ^ pad) for b in iterateints(data) ) + if isinstance(pad, bytestringtype): + if not (len(pad) <= 64 and pad == bytes(len(pad))): + data = integers2bytes( (b ^ p) for b,p in zip(iterateints(data), itertools.cycle(iterateints(pad))) ) + if self.subcon is GreedyBytes: + return data + if type(self.subcon) is GreedyString: + return data.decode(self.subcon.encoding) + return self.subcon._parsereport(io.BytesIO(data), context, path) + + def _build(self, obj, stream, context, path): + pad = evaluate(self.padfunc, context) + if not isinstance(pad, (integertypes, bytestringtype)): + raise StringError("ProcessXor needs integer or bytes pad", path=path) + if isinstance(pad, bytestringtype) and len(pad) == 1: + pad = byte2int(pad) + stream2 = io.BytesIO() + buildret = self.subcon._build(obj, stream2, context, path) + data = stream2.getvalue() + if isinstance(pad, integertypes): + if not (pad == 0): + data = integers2bytes( (b ^ pad) for b in iterateints(data) ) + if isinstance(pad, bytestringtype): + if not (len(pad) <= 64 and pad == bytes(len(pad))): + data = integers2bytes( (b ^ p) for b,p in zip(iterateints(data), itertools.cycle(iterateints(pad))) ) + stream_write(stream, data, len(data), path) + return buildret + + def _sizeof(self, context, path): + return self.subcon._sizeof(context, path) + + +class ProcessRotateLeft(Subconstruct): + r""" + Transforms bytes between the underlying stream and the subcon. + + Used internally by KaitaiStruct compiler, when translating `process: rol/ror` tags. + + Parsing reads till EOF, rotates (shifts) the data *left* by amount in bits, then feeds that data into subcon. Building first builds the subcon into separate BytesIO stream, rotates *right* by negating amount, then writes that data into the main stream. Size is the same as subcon, unless it raises SizeofError. + + :param amount: integer or context lambda, shift by this amount in bits, treated modulo (group x 8) + :param group: integer or context lambda, shifting is applied to chunks of this size in bytes + :param subcon: Construct instance + + :raises RotationError: group is less than 1 + :raises RotationError: data length is not a multiple of group size + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = ProcessRotateLeft(4, 1, Int16ub) + >>> d.parse(b'\x0f\xf0') + 0xf00f + >>> d = ProcessRotateLeft(4, 2, Int16ub) + >>> d.parse(b'\x0f\xf0') + 0xff00 + >>> d.sizeof() + 2 + """ + + # formula taken from: http://stackoverflow.com/a/812039 + precomputed_single_rotations = {amount: [(i << amount) & 0xff | (i >> (8-amount)) for i in range(256)] for amount in range(1,8)} + + def __init__(self, amount, group, subcon): + super(ProcessRotateLeft, self).__init__(subcon) + self.amount = amount + self.group = group + + def _parse(self, stream, context, path): + amount = evaluate(self.amount, context) + group = evaluate(self.group, context) + if group < 1: + raise RotationError("group size must be at least 1 to be valid", path=path) + + amount = amount % (group * 8) + amount_bytes = amount // 8 + data = stream_read_entire(stream, path) + data_ints = bytes2integers(data) + + if len(data) % group != 0: + raise RotationError("data length must be a multiple of group size", path=path) + + if amount == 0: + pass + + elif group == 1: + translate = ProcessRotateLeft.precomputed_single_rotations[amount] + data = integers2bytes( translate[a] for a in data_ints ) + + elif amount % 8 == 0: + indices = [(i + amount_bytes) % group for i in range(group)] + data = integers2bytes( data_ints[i+k] for i in range(0,len(data),group) for k in indices ) + + else: + amount1 = amount % 8 + amount2 = 8 - amount1 + indices_pairs = [ ((i+amount_bytes) % group, (i+1+amount_bytes) % group) for i in range(group)] + data = integers2bytes( (data_ints[i+k1] << amount1) & 0xff | (data_ints[i+k2] >> amount2) for i in range(0,len(data),group) for k1,k2 in indices_pairs ) + + if self.subcon is GreedyBytes: + return data + if type(self.subcon) is GreedyString: + return data.decode(self.subcon.encoding) + return self.subcon._parsereport(io.BytesIO(data), context, path) + + def _build(self, obj, stream, context, path): + amount = evaluate(self.amount, context) + group = evaluate(self.group, context) + if group < 1: + raise RotationError("group size must be at least 1 to be valid", path=path) + + amount = -amount % (group * 8) + amount_bytes = amount // 8 + stream2 = io.BytesIO() + buildret = self.subcon._build(obj, stream2, context, path) + data = stream2.getvalue() + data_ints = bytes2integers(data) + + if len(data) % group != 0: + raise RotationError("data length must be a multiple of group size", path=path) + + if amount == 0: + pass + + elif group == 1: + translate = ProcessRotateLeft.precomputed_single_rotations[amount] + data = integers2bytes( translate[a] for a in data_ints ) + + elif amount % 8 == 0: + indices = [(i + amount_bytes) % group for i in range(group)] + data = integers2bytes( data_ints[i+k] for i in range(0,len(data),group) for k in indices ) + + else: + amount1 = amount % 8 + amount2 = 8 - amount1 + indices_pairs = [ ((i+amount_bytes) % group, (i+1+amount_bytes) % group) for i in range(group)] + data = integers2bytes( (data_ints[i+k1] << amount1) & 0xff | (data_ints[i+k2] >> amount2) for i in range(0,len(data),group) for k1,k2 in indices_pairs ) + + stream_write(stream, data, len(data), path) + return buildret + + def _sizeof(self, context, path): + return self.subcon._sizeof(context, path) + + +class Checksum(Construct): + r""" + Field that is build or validated by a hash of a given byte range. Usually used with :class:`~construct.core.RawCopy` . + + Parsing compares parsed subcon `checksumfield` with a context entry provided by `bytesfunc` and transformed by `hashfunc`. Building fetches the contect entry, transforms it, then writes is using subcon. Size is same as subcon. + + :param checksumfield: a subcon field that reads the checksum, usually Bytes(int) + :param hashfunc: function that takes bytes and returns whatever checksumfield takes when building, usually from hashlib module + :param bytesfunc: context lambda that returns bytes (or object) to be hashed, usually like this.rawcopy1.data + + :raises ChecksumError: parsing and actual checksum does not match actual data + + Can propagate any exception from the lambdas, possibly non-ConstructError. + + Example:: + + import hashlib + d = Struct( + "fields" / RawCopy(Struct( + Padding(1000), + )), + "checksum" / Checksum(Bytes(64), + lambda data: hashlib.sha512(data).digest(), + this.fields.data), + ) + d.build(dict(fields=dict(value={}))) + + :: + + import hashlib + d = Struct( + "offset" / Tell, + "checksum" / Padding(64), + "fields" / RawCopy(Struct( + Padding(1000), + )), + "checksum" / Pointer(this.offset, Checksum(Bytes(64), + lambda data: hashlib.sha512(data).digest(), + this.fields.data)), + ) + d.build(dict(fields=dict(value={}))) + """ + + def __init__(self, checksumfield, hashfunc, bytesfunc): + super(Checksum, self).__init__() + self.checksumfield = checksumfield + self.hashfunc = hashfunc + self.bytesfunc = bytesfunc + self.flagbuildnone = True + + def _parse(self, stream, context, path): + hash1 = self.checksumfield._parsereport(stream, context, path) + hash2 = self.hashfunc(self.bytesfunc(context)) + if hash1 != hash2: + raise ChecksumError( + "wrong checksum, read %r, computed %r" % ( + hash1 if not isinstance(hash1,bytestringtype) else binascii.hexlify(hash1), + hash2 if not isinstance(hash2,bytestringtype) else binascii.hexlify(hash2), ), + path=path + ) + return hash1 + + def _build(self, obj, stream, context, path): + hash2 = self.hashfunc(self.bytesfunc(context)) + self.checksumfield._build(hash2, stream, context, path) + return hash2 + + def _sizeof(self, context, path): + return self.checksumfield._sizeof(context, path) + + +class Compressed(Tunnel): + r""" + Compresses and decompresses underlying stream when processing subcon. When parsing, entire stream is consumed. When building, puts compressed bytes without marking the end. This construct should be used with :class:`~construct.core.Prefixed` . + + Parsing and building transforms all bytes using a specified codec. Since data is processed until EOF, it behaves similar to `GreedyBytes`. Size is undefined. + + :param subcon: Construct instance, subcon used for storing the value + :param encoding: string, any of module names like zlib/gzip/bzip2/lzma, otherwise any of codecs module bytes<->bytes encodings, each codec usually requires some Python version + :param level: optional, integer between 0..9, although lzma discards it, some encoders allow different compression levels + + :raises ImportError: needed module could not be imported by ctor + :raises StreamError: stream failed when reading until EOF + + Example:: + + >>> d = Prefixed(VarInt, Compressed(GreedyBytes, "zlib")) + >>> d.build(bytes(100)) + b'\x0cx\x9cc`\xa0=\x00\x00\x00d\x00\x01' + + """ + + def __init__(self, subcon, encoding, level=None): + super(Compressed, self).__init__(subcon) + self.encoding = encoding + self.level = level + if self.encoding == "zlib": + import zlib + self.lib = zlib + elif self.encoding == "gzip": + import gzip + self.lib = gzip + elif self.encoding == "bzip2": + import bz2 + self.lib = bz2 + elif self.encoding == "lzma": + import lzma + self.lib = lzma + else: + import codecs + self.lib = codecs + + def _decode(self, data, context, path): + if self.encoding in ("zlib", "gzip", "bzip2", "lzma"): + return self.lib.decompress(data) + return self.lib.decode(data, self.encoding) + + def _encode(self, data, context, path): + if self.encoding in ("zlib", "gzip", "bzip2", "lzma"): + if self.level is None or self.encoding == "lzma": + return self.lib.compress(data) + else: + return self.lib.compress(data, self.level) + return self.lib.encode(data, self.encoding) + + +class Rebuffered(Subconstruct): + r""" + Caches bytes from underlying stream, so it becomes seekable and tellable, and also becomes blocking on reading. Useful for processing non-file streams like pipes, sockets, etc. + + .. warning:: Experimental implementation. May not be mature enough. + + :param subcon: Construct instance, subcon which will operate on the buffered stream + :param tailcutoff: optional, integer, amount of bytes kept in buffer, by default buffers everything + + Can also raise arbitrary exceptions in its implementation. + + Example:: + + Rebuffered(..., tailcutoff=1024).parse_stream(nonseekable_stream) + """ + + def __init__(self, subcon, tailcutoff=None): + super(Rebuffered, self).__init__(subcon) + self.stream2 = RebufferedBytesIO(None, tailcutoff=tailcutoff) + + def _parse(self, stream, context, path): + self.stream2.substream = stream + return self.subcon._parsereport(self.stream2, context, path) + + def _build(self, obj, stream, context, path): + self.stream2.substream = stream + return self.subcon._build(obj, self.stream2, context, path) + + +#=============================================================================== +# lazy equivalents +#=============================================================================== +class Lazy(Subconstruct): + r""" + Lazyfies a field. + + This wrapper allows you to do lazy parsing of individual fields inside a normal Struct (without using LazyStruct which may not work in every scenario). It is also used by KaitaiStruct compiler to emit `instances` because those are not processed greedily, and they may refer to other not yet parsed fields. Those are 2 entirely different applications but semantics are the same. + + Parsing saves the current stream offset and returns a lambda. If and when that lambda gets evaluated, it seeks the stream to then-current position, parses the subcon, and seeks the stream back to previous position. Building evaluates that lambda into an object (if needed), then defers to subcon. Size also defers to subcon. + + :param subcon: Construct instance + + :raises StreamError: requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes + :raises StreamError: stream is not seekable and tellable + + Example:: + + >>> d = Lazy(Byte) + >>> x = d.parse(b'\x00') + >>> x + .execute> + >>> x() + 0 + >>> d.build(0) + b'\x00' + >>> d.build(x) + b'\x00' + >>> d.sizeof() + 1 + """ + + def __init__(self, subcon): + super(Lazy, self).__init__(subcon) + + def _parse(self, stream, context, path): + offset = stream_tell(stream, path) + def execute(): + fallback = stream_tell(stream, path) + stream_seek(stream, offset, 0, path) + obj = self.subcon._parsereport(stream, context, path) + stream_seek(stream, fallback, 0, path) + return obj + return execute + + def _build(self, obj, stream, context, path): + if callable(obj): + obj = obj() + return self.subcon._build(obj, stream, context, path) + + +class LazyContainer(dict): + """Used internally.""" + + def __init__(self, struct, stream, offsets, values, context, path): + self._struct = struct + self._stream = stream + self._offsets = offsets + self._values = values + self._context = context + self._path = path + + def __getattr__(self, name): + if name in self._struct._subconsindexes: + return self[name] + raise AttributeError + + def __getitem__(self, index): + if isinstance(index, stringtypes): + index = self._struct._subconsindexes[index] # KeyError + if index in self._values: + return self._values[index] + stream_seek(self._stream, self._offsets[index], 0, self._path) # KeyError + parseret = self._struct.subcons[index]._parsereport(self._stream, self._context, self._path) + self._values[index] = parseret + return parseret + + def __len__(self): + return len(self._struct.subcons) + + def keys(self): + return iter(self._struct._subcons) + + def values(self): + return (self[k] for k in self._struct._subcons) + + def items(self): + return ((k, self[k]) for k in self._struct._subcons) + + __iter__ = keys + + def __eq__(self, other): + return Container.__eq__(self, other) + + def __repr__(self): + return "" % (len(self._values), len(self._struct.subcons), ) + + +class LazyStruct(Construct): + r""" + Equivalent to :class:`~construct.core.Struct`, but when this class is parsed, most fields are not parsed (they are skipped if their size can be measured by _actualsize or _sizeof method). See its docstring for details. + + Fields are parsed depending on some factors: + + * Some fields like Int* Float* Bytes(5) Array(5,Byte) Pointer are fixed-size and are therefore skipped. Stream is not read. + * Some fields like Bytes(this.field) are variable-size but their size is known during parsing when there is a corresponding context entry. Those fields are also skipped. Stream is not read. + * Some fields like Prefixed PrefixedArray PascalString are variable-size but their size can be computed by partially reading the stream. Only first few bytes are read (the lengthfield). + * Other fields like VarInt need to be parsed. Stream position that is left after the field was parsed is used. + * Some fields may not work properly, due to the fact that this class attempts to skip fields, and parses them only out of necessity. Miscellaneous fields often have size defined as 0, and fixed sized fields are skippable. + + Note there are restrictions: + + * If a field like Bytes(this.field) references another field in the same struct, you need to access the referenced field first (to trigger its parsing) and then you can access the Bytes field. Otherwise it would fail due to missing context entry. + * If a field references another field within inner (nested) or outer (super) struct, things may break. Context is nested, but this class was not rigorously tested in that manner. + + Building and sizeof are greedy, like in Struct. + + :param \*subcons: Construct instances, list of members, some can be anonymous + :param \*\*subconskw: Construct instances, list of members (requires Python 3.6) + """ + + def __init__(self, *subcons, **subconskw): + super(LazyStruct, self).__init__() + self.subcons = list(subcons) + list(k/v for k,v in subconskw.items()) + self._subcons = Container((sc.name,sc) for sc in self.subcons if sc.name) + self._subconsindexes = Container((sc.name,i) for i,sc in enumerate(self.subcons) if sc.name) + self.flagbuildnone = all(sc.flagbuildnone for sc in self.subcons) + + def __getattr__(self, name): + if name in self._subcons: + return self._subcons[name] + raise AttributeError + + def _parse(self, stream, context, path): + context = Container(_ = context, _params = context._params, _root = None, _parsing = context._parsing, _building = context._building, _sizing = context._sizing, _subcons = self._subcons, _io = stream, _index = context.get("_index", None)) + context._root = context._.get("_root", context) + offset = stream_tell(stream, path) + offsets = {0: offset} + values = {} + for i,sc in enumerate(self.subcons): + try: + offset += sc._actualsize(stream, context, path) + stream_seek(stream, offset, 0, path) + except SizeofError: + parseret = sc._parsereport(stream, context, path) + values[i] = parseret + if sc.name: + context[sc.name] = parseret + offset = stream_tell(stream, path) + offsets[i+1] = offset + return LazyContainer(self, stream, offsets, values, context, path) + + def _build(self, obj, stream, context, path): + # exact copy from Struct class + if obj is None: + obj = Container() + context = Container(_ = context, _params = context._params, _root = None, _parsing = context._parsing, _building = context._building, _sizing = context._sizing, _subcons = self._subcons, _io = stream, _index = context.get("_index", None)) + context._root = context._.get("_root", context) + context.update(obj) + for sc in self.subcons: + try: + if sc.flagbuildnone: + subobj = obj.get(sc.name, None) + else: + subobj = obj[sc.name] # raises KeyError + + if sc.name: + context[sc.name] = subobj + + buildret = sc._build(subobj, stream, context, path) + if sc.name: + context[sc.name] = buildret + except StopFieldError: + break + return context + + def _sizeof(self, context, path): + # exact copy from Struct class + context = Container(_ = context, _params = context._params, _root = None, _parsing = context._parsing, _building = context._building, _sizing = context._sizing, _subcons = self._subcons, _io = None, _index = context.get("_index", None)) + context._root = context._.get("_root", context) + try: + return sum(sc._sizeof(context, path) for sc in self.subcons) + except (KeyError, AttributeError): + raise SizeofError("cannot calculate size, key not found in context", path=path) + + +class LazyListContainer(list): + """Used internally.""" + + def __init__(self, subcon, stream, count, offsets, values, context, path): + self._subcon = subcon + self._stream = stream + self._count = count + self._offsets = offsets + self._values = values + self._context = context + self._path = path + + def __getitem__(self, index): + if isinstance(index, slice): + return [self[i] for i in range(*index.indices(self._count))] + if index in self._values: + return self._values[index] + stream_seek(self._stream, self._offsets[index], 0, self._path) # KeyError + parseret = self._subcon._parsereport(self._stream, self._context, self._path) + self._values[index] = parseret + return parseret + + def __getslice__(self, start, stop): + if stop == sys.maxsize: + stop = self._count + return self.__getitem__(slice(start, stop)) + + def __len__(self): + return self._count + + def __iter__(self): + return (self[i] for i in range(self._count)) + + def __eq__(self, other): + return len(self) == len(other) and all(self[i] == other[i] for i in range(self._count)) + + def __repr__(self): + return "" % (len(self._values), self._count, ) + + +class LazyArray(Subconstruct): + r""" + Equivalent to :class:`~construct.core.Array`, but the subcon is not parsed when possible (it gets skipped if the size can be measured by _actualsize or _sizeof method). See its docstring for details. + + Fields are parsed depending on some factors: + + * Some fields like Int* Float* Bytes(5) Array(5,Byte) Pointer are fixed-size and are therefore skipped. Stream is not read. + * Some fields like Bytes(this.field) are variable-size but their size is known during parsing when there is a corresponding context entry. Those fields are also skipped. Stream is not read. + * Some fields like Prefixed PrefixedArray PascalString are variable-size but their size can be computed by partially reading the stream. Only first few bytes are read (the lengthfield). + * Other fields like VarInt need to be parsed. Stream position that is left after the field was parsed is used. + * Some fields may not work properly, due to the fact that this class attempts to skip fields, and parses them only out of necessity. Miscellaneous fields often have size defined as 0, and fixed sized fields are skippable. + + Note there are restrictions: + + * If a field references another field within inner (nested) or outer (super) struct, things may break. Context is nested, but this class was not rigorously tested in that manner. + + Building and sizeof are greedy, like in Array. + + :param count: integer or context lambda, strict amount of elements + :param subcon: Construct instance, subcon to process individual elements + """ + + def __init__(self, count, subcon): + super(LazyArray, self).__init__(subcon) + self.count = count + + def _parse(self, stream, context, path): + sc = self.subcon + count = self.count + if callable(count): + count = count(context) + if not 0 <= count: + raise RangeError("invalid count %s" % (count,), path=path) + offset = stream_tell(stream, path) + offsets = {0: offset} + values = {} + for i in range(count): + try: + offset += sc._actualsize(stream, context, path) + stream_seek(stream, offset, 0, path) + except SizeofError: + parseret = sc._parsereport(stream, context, path) + values[i] = parseret + offset = stream_tell(stream, path) + offsets[i+1] = offset + return LazyListContainer(sc, stream, count, offsets, values, context, path) + + def _build(self, obj, stream, context, path): + # exact copy from Array class + count = self.count + if callable(count): + count = count(context) + if not 0 <= count: + raise RangeError("invalid count %s" % (count,), path=path) + if not len(obj) == count: + raise RangeError("expected %d elements, found %d" % (count, len(obj)), path=path) + retlist = ListContainer() + for i,e in enumerate(obj): + context._index = i + buildret = self.subcon._build(e, stream, context, path) + retlist.append(buildret) + return retlist + + def _sizeof(self, context, path): + # exact copy from Array class + try: + count = self.count + if callable(count): + count = count(context) + except (KeyError, AttributeError): + raise SizeofError("cannot calculate size, key not found in context", path=path) + return count * self.subcon._sizeof(context, path) + + +class LazyBound(Construct): + r""" + Field that binds to the subcon only at runtime (during parsing and building, not ctor). Useful for recursive data structures, like linked-lists and trees, where a construct needs to refer to itself (while it does not exist yet in the namespace). + + Note that it is possible to obtain same effect without using this class, using a loop. However there are usecases where that is not possible (if remaining nodes cannot be sized-up, and there is data following the recursive structure). There is also a significant difference, namely that LazyBound actually does greedy parsing while the loop does lazy parsing. See examples. + + To break recursion, use `If` field. See examples. + + :param subconfunc: parameter-less lambda returning Construct instance, can also return itself + + Example:: + + d = Struct( + "value" / Byte, + "next" / If(this.value > 0, LazyBound(lambda: d)), + ) + >>> print(d.parse(b"\x05\x09\x00")) + Container: + value = 5 + next = Container: + value = 9 + next = Container: + value = 0 + next = None + + :: + + d = Struct( + "value" / Byte, + "next" / GreedyBytes, + ) + data = b"\x05\x09\x00" + while data: + x = d.parse(data) + data = x.next + print(x) + # print outputs + Container: + value = 5 + next = \t\x00 (total 2) + # print outputs + Container: + value = 9 + next = \x00 (total 1) + # print outputs + Container: + value = 0 + next = (total 0) + """ + + def __init__(self, subconfunc): + super(LazyBound, self).__init__() + self.subconfunc = subconfunc + + def _parse(self, stream, context, path): + sc = self.subconfunc() + return sc._parsereport(stream, context, path) + + def _build(self, obj, stream, context, path): + sc = self.subconfunc() + return sc._build(obj, stream, context, path) + + +#=============================================================================== +# adapters and validators +#=============================================================================== +class ExprAdapter(Adapter): + r""" + Generic adapter that takes `decoder` and `encoder` lambdas as parameters. You can use ExprAdapter instead of writing a full-blown class deriving from Adapter when only a simple lambda is needed. + + :param subcon: Construct instance, subcon to adapt + :param decoder: lambda that takes (obj, context) and returns an decoded version of obj + :param encoder: lambda that takes (obj, context) and returns an encoded version of obj + + Example:: + + >>> d = ExprAdapter(Byte, obj_+1, obj_-1) + >>> d.parse(b'\x04') + 5 + >>> d.build(5) + b'\x04' + """ + def __init__(self, subcon, decoder, encoder): + super(ExprAdapter, self).__init__(subcon) + self._decode = lambda obj,ctx,path: decoder(obj,ctx) + self._encode = lambda obj,ctx,path: encoder(obj,ctx) + + +class ExprSymmetricAdapter(ExprAdapter): + """ + Macro around :class:`~construct.core.ExprAdapter`. + + :param subcon: Construct instance, subcon to adapt + :param encoder: lambda that takes (obj, context) and returns both encoded version and decoded version of obj + + Example:: + + >>> d = ExprSymmetricAdapter(Byte, obj_ & 0b00001111) + >>> d.parse(b"\xff") + 15 + >>> d.build(255) + b'\x0f' + """ + def __init__(self, subcon, encoder): + super(ExprAdapter, self).__init__(subcon) + self._decode = lambda obj,ctx,path: encoder(obj,ctx) + self._encode = lambda obj,ctx,path: encoder(obj,ctx) + + +class ExprValidator(Validator): + r""" + Generic adapter that takes `validator` lambda as parameter. You can use ExprValidator instead of writing a full-blown class deriving from Validator when only a simple lambda is needed. + + :param subcon: Construct instance, subcon to adapt + :param validator: lambda that takes (obj, context) and returns a bool + + Example:: + + >>> d = ExprValidator(Byte, obj_ & 0b11111110 == 0) + >>> d.build(1) + b'\x01' + >>> d.build(88) + ValidationError: object failed validation: 88 + + """ + def __init__(self, subcon, validator): + super(ExprValidator, self).__init__(subcon) + self._validate = lambda obj,ctx,path: validator(obj,ctx) + + +def OneOf(subcon, valids): + r""" + Validates that the object is one of the listed values, both during parsing and building. + + .. note:: For performance, `valids` should be a set/frozenset. + + :param subcon: Construct instance, subcon to validate + :param valids: collection implementing __contains__, usually a list or set + + :raises ValidationError: parsed or build value is not among valids + + Example:: + + >>> d = OneOf(Byte, [1,2,3]) + >>> d.parse(b"\x01") + 1 + >>> d.parse(b"\xff") + construct.core.ValidationError: object failed validation: 255 + """ + return ExprValidator(subcon, lambda obj,ctx: obj in valids) + + +def NoneOf(subcon, invalids): + r""" + Validates that the object is none of the listed values, both during parsing and building. + + .. note:: For performance, `valids` should be a set/frozenset. + + :param subcon: Construct instance, subcon to validate + :param invalids: collection implementing __contains__, usually a list or set + + :raises ValidationError: parsed or build value is among invalids + + """ + return ExprValidator(subcon, lambda obj,ctx: obj not in invalids) + + +def Filter(predicate, subcon): + r""" + Filters a list leaving only the elements that passed through the predicate. + + :param subcon: Construct instance, usually Array GreedyRange Sequence + :param predicate: lambda that takes (obj, context) and returns a bool + + Can propagate any exception from the lambda, possibly non-ConstructError. + + Example:: + + >>> d = Filter(obj_ != 0, Byte[:]) + >>> d.parse(b"\x00\x02\x00") + [2] + >>> d.build([0,1,0,2,0]) + b'\x01\x02' + """ + return ExprSymmetricAdapter(subcon, lambda obj,ctx: [x for x in obj if predicate(x,ctx)]) + + +class Slicing(Adapter): + r""" + Adapter for slicing a list. Works with GreedyRange and Sequence. + + :param subcon: Construct instance, subcon to slice + :param count: integer, expected number of elements, needed during building + :param start: integer for start index (or None for entire list) + :param stop: integer for stop index (or None for up-to-end) + :param step: integer, step (or 1 for every element) + :param empty: object, value to fill the list with, during building + + Example:: + + d = Slicing(Array(4,Byte), 4, 1, 3, empty=0) + assert d.parse(b"\x01\x02\x03\x04") == [2,3] + assert d.build([2,3]) == b"\x00\x02\x03\x00" + assert d.sizeof() == 4 + """ + def __init__(self, subcon, count, start, stop, step=1, empty=None): + super(Slicing, self).__init__(subcon) + self.count = count + self.start = start + self.stop = stop + self.step = step + self.empty = empty + def _decode(self, obj, context, path): + return obj[self.start:self.stop:self.step] + def _encode(self, obj, context, path): + if self.start is None: + return obj + elif self.stop is None: + output = [self.empty] * self.count + output[self.start::self.step] = obj + else: + output = [self.empty] * self.count + output[self.start:self.stop:self.step] = obj + return output + + +class Indexing(Adapter): + r""" + Adapter for indexing a list (getting a single item from that list). Works with Range and Sequence and their lazy equivalents. + + :param subcon: Construct instance, subcon to index + :param count: integer, expected number of elements, needed during building + :param index: integer, index of the list to get + :param empty: object, value to fill the list with, during building + + Example:: + + d = Indexing(Array(4,Byte), 4, 2, empty=0) + assert d.parse(b"\x01\x02\x03\x04") == 3 + assert d.build(3) == b"\x00\x00\x03\x00" + assert d.sizeof() == 4 + """ + def __init__(self, subcon, count, index, empty=None): + super(Indexing, self).__init__(subcon) + self.count = count + self.index = index + self.empty = empty + def _decode(self, obj, context, path): + return obj[self.index] + def _encode(self, obj, context, path): + output = [self.empty] * self.count + output[self.index] = obj + return output + + +#=============================================================================== +# end of file +#=============================================================================== diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/debug.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/debug.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/debug.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/debug.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,154 @@ +from checkbox_support.vendor.construct import * +from checkbox_support.vendor.construct.lib import * +import sys, traceback, pdb, inspect + + +class Probe(Construct): + r""" + Probe that dumps the context, and some stream content (peeks into it) to the screen to aid the debugging process. It can optionally limit itself to a single context entry, instead of printing entire context. + + :param into: optional, None by default, or context lambda + :param lookahead: optional, integer, number of bytes to dump from the stream + + Example:: + + >>> d = Struct( + ... "count" / Byte, + ... "items" / Byte[this.count], + ... Probe(lookahead=32), + ... ) + >>> d.parse(b"\x05abcde\x01\x02\x03") + + -------------------------------------------------- + Probe, path is (parsing), into is None + Stream peek: (hexlified) b'010203'... + Container: + count = 5 + items = ListContainer: + 97 + 98 + 99 + 100 + 101 + -------------------------------------------------- + + :: + + >>> d = Struct( + ... "count" / Byte, + ... "items" / Byte[this.count], + ... Probe(this.count), + ... ) + >>> d.parse(b"\x05abcde\x01\x02\x03") + + -------------------------------------------------- + Probe, path is (parsing), into is this.count + 5 + -------------------------------------------------- + + """ + + def __init__(self, into=None, lookahead=None): + super(Probe, self).__init__() + self.flagbuildnone = True + self.into = into + self.lookahead = lookahead + + def _parse(self, stream, context, path): + self.printout(stream, context, path) + + def _build(self, obj, stream, context, path): + self.printout(stream, context, path) + + def _sizeof(self, context, path): + self.printout(None, context, path) + return 0 + + def _emitparse(self, code): + return "print(%s)" % (self.into,) if self.into else "print(this)" + + def printout(self, stream, context, path): + print("--------------------------------------------------") + print("Probe, path is %s, into is %r" % (path, self.into, )) + + if self.lookahead and stream is not None: + fallback = stream.tell() + datafollows = stream.read(self.lookahead) + stream.seek(fallback) + if datafollows: + print("Stream peek: (hexlified) %s..." % (hexlify(datafollows), )) + else: + print("Stream peek: EOF reached") + + if context is not None: + if self.into: + try: + subcontext = self.into(context) + print(subcontext) + except Exception: + print("Failed to compute %r on the context %r" % (self.into, context, )) + else: + print(context) + print("--------------------------------------------------") + + +class Debugger(Subconstruct): + r""" + PDB-based debugger. When an exception occurs in the subcon, a debugger will appear and allow you to debug the error (and even fix it on-the-fly). + + :param subcon: Construct instance, subcon to debug + + Example:: + + >>> Debugger(Byte[3]).build([]) + + -------------------------------------------------- + Debugging exception of + path is (building) + File "/media/arkadiusz/MAIN/GitHub/construct/construct/debug.py", line 192, in _build + return self.subcon._build(obj, stream, context, path) + File "/media/arkadiusz/MAIN/GitHub/construct/construct/core.py", line 2149, in _build + raise RangeError("expected %d elements, found %d" % (count, len(obj))) + construct.core.RangeError: expected 3 elements, found 0 + + > /media/arkadiusz/MAIN/GitHub/construct/construct/core.py(2149)_build() + -> raise RangeError("expected %d elements, found %d" % (count, len(obj))) + (Pdb) q + -------------------------------------------------- + """ + + def _parse(self, stream, context, path): + try: + return self.subcon._parse(stream, context, path) + except Exception: + self.retval = NotImplemented + self.handle_exc(path, msg="(you can set self.retval, which will be returned from method)") + if self.retval is NotImplemented: + raise + else: + return self.retval + + def _build(self, obj, stream, context, path): + try: + return self.subcon._build(obj, stream, context, path) + except Exception: + self.handle_exc(path) + + def _sizeof(self, context, path): + try: + return self.subcon._sizeof(context, path) + except Exception: + self.handle_exc(path) + + def _emitparse(self, code): + return self.subcon._compileparse(code) + + def handle_exc(self, path, msg=None): + print("--------------------------------------------------") + print("Debugging exception of %r" % (self.subcon, )) + print("path is %s" % (path, )) + print("".join(traceback.format_exception(*sys.exc_info())[1:])) + if msg: + print(msg) + pdb.post_mortem(sys.exc_info()[2]) + print("--------------------------------------------------") diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/expr.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/expr.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/expr.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/expr.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,256 @@ +import operator +if not hasattr(operator, "div"): + operator.div = operator.truediv + + +opnames = { + operator.add : "+", + operator.sub : "-", + operator.mul : "*", + operator.div : "/", + operator.floordiv : "//", + operator.mod : "%", + operator.pow : "**", + operator.xor : "^", + operator.lshift : "<<", + operator.rshift : ">>", + operator.and_ : "and", + operator.or_ : "or", + operator.not_ : "not", + operator.neg : "-", + operator.pos : "+", + operator.contains : "in", + operator.gt : ">", + operator.ge : ">=", + operator.lt : "<", + operator.le : "<=", + operator.eq : "==", + operator.ne : "!=", +} + + +class ExprMixin(object): + + def __add__(self, other): + return BinExpr(operator.add, self, other) + def __sub__(self, other): + return BinExpr(operator.sub, self, other) + def __mul__(self, other): + return BinExpr(operator.mul, self, other) + def __floordiv__(self, other): + return BinExpr(operator.floordiv, self, other) + def __truediv__(self, other): + return BinExpr(operator.div, self, other) + __div__ = __floordiv__ + def __mod__(self, other): + return BinExpr(operator.mod, self, other) + def __pow__(self, other): + return BinExpr(operator.pow, self, other) + def __xor__(self, other): + return BinExpr(operator.xor, self, other) + def __rshift__(self, other): + return BinExpr(operator.rshift, self, other) + def __lshift__(self, other): + return BinExpr(operator.lshift, self, other) + def __and__(self, other): + return BinExpr(operator.and_, self, other) + def __or__(self, other): + return BinExpr(operator.or_, self, other) + + def __radd__(self, other): + return BinExpr(operator.add, other, self) + def __rsub__(self, other): + return BinExpr(operator.sub, other, self) + def __rmul__(self, other): + return BinExpr(operator.mul, other, self) + def __rfloordiv__(self, other): + return BinExpr(operator.floordiv, other, self) + def __rtruediv__(self, other): + return BinExpr(operator.div, other, self) + __rdiv__ = __rfloordiv__ + def __rmod__(self, other): + return BinExpr(operator.mod, other, self) + def __rpow__(self, other): + return BinExpr(operator.pow, other, self) + def __rxor__(self, other): + return BinExpr(operator.xor, other, self) + def __rrshift__(self, other): + return BinExpr(operator.rshift, other, self) + def __rlshift__(self, other): + return BinExpr(operator.lshift, other, self) + def __rand__(self, other): + return BinExpr(operator.and_, other, self) + def __ror__(self, other): + return BinExpr(operator.or_, other, self) + + def __neg__(self): + return UniExpr(operator.neg, self) + def __pos__(self): + return UniExpr(operator.pos, self) + def __invert__(self): + return UniExpr(operator.not_, self) + __inv__ = __invert__ + + def __contains__(self, other): + return BinExpr(operator.contains, self, other) + def __gt__(self, other): + return BinExpr(operator.gt, self, other) + def __ge__(self, other): + return BinExpr(operator.ge, self, other) + def __lt__(self, other): + return BinExpr(operator.lt, self, other) + def __le__(self, other): + return BinExpr(operator.le, self, other) + def __eq__(self, other): + return BinExpr(operator.eq, self, other) + def __ne__(self, other): + return BinExpr(operator.ne, self, other) + + def __getstate__(self): + attrs = {} + if hasattr(self, "__dict__"): + attrs.update(self.__dict__) + slots = [] + c = self.__class__ + while c is not None: + if hasattr(c, "__slots__"): + slots.extend(c.__slots__) + c = c.__base__ + for name in slots: + if hasattr(self, name): + attrs[name] = getattr(self, name) + return attrs + + def __setstate__(self, attrs): + for name, value in attrs.items(): + setattr(self, name, value) + + +class UniExpr(ExprMixin): + + def __init__(self, op, operand): + self.op = op + self.operand = operand + + def __repr__(self): + return "%s %r" % (opnames[self.op], self.operand) + + def __str__(self): + return "%s %s" % (opnames[self.op], self.operand) + + def __call__(self, obj, *args): + operand = self.operand(obj) if callable(self.operand) else self.operand + return self.op(operand) + + +class BinExpr(ExprMixin): + + def __init__(self, op, lhs, rhs): + self.op = op + self.lhs = lhs + self.rhs = rhs + + def __repr__(self): + return "(%r %s %r)" % (self.lhs, opnames[self.op], self.rhs) + + def __str__(self): + return "(%s %s %s)" % (self.lhs, opnames[self.op], self.rhs) + + def __call__(self, obj, *args): + lhs = self.lhs(obj) if callable(self.lhs) else self.lhs + rhs = self.rhs(obj) if callable(self.rhs) else self.rhs + return self.op(lhs, rhs) + + +class Path(ExprMixin): + + def __init__(self, name, field=None, parent=None): + self.__name = name + self.__field = field + self.__parent = parent + + def __repr__(self): + if self.__parent is None: + return self.__name + else: + return "%r.%s" % (self.__parent, self.__field) + + def __str__(self): + if self.__parent is None: + return self.__name + else: + return "%s[%r]" % (self.__parent, self.__field) + + def __call__(self, obj, *args): + if self.__parent is None: + return obj + else: + return self.__parent(obj)[self.__field] + + def __getfield__(self): + return self.__field + + def __getattr__(self, name): + return Path(self.__name, name, self) + + def __getitem__(self, name): + return Path(self.__name, name, self) + + +class Path2(ExprMixin): + + def __init__(self, name, index=None, parent=None): + self.__name = name + self.__index = index + self.__parent = parent + + def __repr__(self): + if self.__parent is None: + return self.__name + else: + return "%r[%r]" % (self.__parent, self.__index) + + def __call__(self, *args): + if self.__parent is None: + return args[1] + else: + return self.__parent(*args)[self.__index] + + def __getitem__(self, index): + return Path2(self.__name, index, self) + + +class FuncPath(ExprMixin): + + def __init__(self, func, operand=None): + self.__func = func + self.__operand = operand + + def __repr__(self): + if self.__operand is None: + return "%s_" % (self.__func.__name__) + else: + return "%s_(%r)" % (self.__func.__name__, self.__operand) + + def __str__(self): + if self.__operand is None: + return "%s_" % (self.__func.__name__) + else: + return "%s_(%s)" % (self.__func.__name__, self.__operand) + + def __call__(self, operand, *args): + if self.__operand is None: + return FuncPath(self.__func, operand) if callable(operand) else operand + else: + return self.__func(self.__operand(operand) if callable(self.__operand) else self.__operand) + + +this = Path("this") +obj_ = Path("obj_") +list_ = Path2("list_") + +len_ = FuncPath(len) +sum_ = FuncPath(sum) +min_ = FuncPath(min) +max_ = FuncPath(max) +abs_ = FuncPath(abs) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/__init__.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/__init__.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/__init__.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,208 @@ +r""" +Construct 2 -- Parsing Made Fun + +Homepage: + https://github.com/construct/construct + http://construct.readthedocs.org + +Hands-on example: + >>> from checkbox_support.vendor.construct import * + >>> s = Struct( + ... "a" / Byte, + ... "b" / Short, + ... ) + >>> print s.parse(b"\x01\x02\x03") + Container: + a = 1 + b = 515 + >>> s.build(Container(a=1, b=0x0203)) + b"\x01\x02\x03" +""" + +from checkbox_support.vendor.construct.core import * +from checkbox_support.vendor.construct.expr import * +from checkbox_support.vendor.construct.debug import * +from checkbox_support.vendor.construct.version import * +from checkbox_support.vendor.construct import lib + + +#=============================================================================== +# metadata +#=============================================================================== +__author__ = "Arkadiusz Bulski , Tomer Filiba , Corbin Simpson " +__version__ = version_string + +#=============================================================================== +# exposed names +#=============================================================================== +__all__ = [ + '__author__', + '__version__', + 'abs_', + 'AdaptationError', + 'Adapter', + 'Aligned', + 'AlignedStruct', + 'Array', + 'Bit', + 'BitsInteger', + 'BitsSwapped', + 'BitStruct', + 'BitwisableString', + 'Bitwise', + 'Byte', + 'Bytes', + 'BytesInteger', + 'ByteSwapped', + 'Bytewise', + 'CancelParsing', + 'Check', + 'CheckError', + 'Checksum', + 'ChecksumError', + 'Compiled', + 'Compressed', + 'Computed', + 'Const', + 'ConstError', + 'Construct', + 'ConstructError', + 'Container', + 'CString', + 'Debugger', + 'Default', + 'Double', + 'Enum', + 'EnumInteger', + 'EnumIntegerString', + 'Error', + 'ExplicitError', + 'ExprAdapter', + 'ExprSymmetricAdapter', + 'ExprValidator', + 'Filter', + 'FixedSized', + 'Flag', + 'FlagsEnum', + 'FocusedSeq', + 'FormatField', + 'FormatFieldError', + 'FuncPath', + 'globalPrintFalseFlags', + 'globalPrintFullStrings', + 'GreedyBytes', + 'GreedyRange', + 'GreedyString', + 'Half', + 'Hex', + 'HexDump', + 'If', + 'IfThenElse', + 'Index', + 'IndexFieldError', + 'Indexing', + 'Int', + 'IntegerError', + 'Lazy', + 'LazyArray', + 'LazyBound', + 'LazyContainer', + 'LazyListContainer', + 'LazyStruct', + 'len_', + 'lib', + 'list_', + 'ListContainer', + 'Long', + 'Mapping', + 'MappingError', + 'max_', + 'min_', + 'NamedTuple', + 'NamedTupleError', + 'Nibble', + 'NoneOf', + 'NullStripped', + 'NullTerminated', + 'Numpy', + 'obj_', + 'Octet', + 'OneOf', + 'Optional', + 'Padded', + 'PaddedString', + 'Padding', + 'PaddingError', + 'PascalString', + 'Pass', + 'Path', + 'Path2', + 'Peek', + 'Pickled', + 'Pointer', + 'possiblestringencodings', + 'Prefixed', + 'PrefixedArray', + 'Probe', + 'ProcessRotateLeft', + 'ProcessXor', + 'RangeError', + 'RawCopy', + 'Rebuffered', + 'RebufferedBytesIO', + 'Rebuild', + 'release_date', + 'Renamed', + 'RepeatError', + 'RepeatUntil', + 'RestreamData', + 'Restreamed', + 'RestreamedBytesIO', + 'RotationError', + 'Seek', + 'Select', + 'SelectError', + 'Sequence', + 'setGlobalPrintFalseFlags', + 'setGlobalPrintFullStrings', + 'setGlobalPrintPrivateEntries', + 'Short', + 'Single', + 'SizeofError', + 'Slicing', + 'StopFieldError', + 'StopIf', + 'stream_iseof', + 'stream_read', + 'stream_read_entire', + 'stream_seek', + 'stream_size', + 'stream_tell', + 'stream_write', + 'StreamError', + 'StringEncoded', + 'StringError', + 'Struct', + 'Subconstruct', + 'sum_', + 'Switch', + 'SwitchError', + 'SymmetricAdapter', + 'Tell', + 'Terminated', + 'TerminatedError', + 'this', + 'Timestamp', + 'TimestampError', + 'Transformed', + 'Tunnel', + 'Union', + 'UnionError', + 'ValidationError', + 'Validator', + 'VarInt', + 'version', + 'version_string', +] +__all__ += ["Int%s%s%s" % (n,us,bln) for n in (8,16,24,32,64) for us in "us" for bln in "bln"] +__all__ += ["Float%s%s" % (n,bln) for n in (16,32,64) for bln in "bln"] diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/binary.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/binary.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/binary.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/binary.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,165 @@ +from checkbox_support.vendor.construct.lib.py3compat import * +import binascii + + +def integer2bits(number, width): + r""" + Converts an integer into its binary representation in a bit-string. Width is the amount of bits to generate. If width is larger than the actual amount of bits required to represent number in binary, sign-extension is used. If it's smaller, the representation is trimmed to width bits. Each bit is represented as either \\x00 or \\x01. The most significant is first, big-endian. This is reverse to `bits2integer`. + + Examples: + + >>> integer2bits(19, 8) + b'\x00\x00\x00\x01\x00\x00\x01\x01' + """ + if width < 0: + raise ValueError("width must be non-negative") + number = int(number) + if number < 0: + number += 1 << width + bits = [b"\x00"] * width + i = width - 1 + while number and i >= 0: + bits[i] = int2byte(number & 1) + number >>= 1 + i -= 1 + return b"".join(bits) + + +def integer2bytes(number, width): + r""" + Converts a bytes-string into an integer. This is reverse to `bytes2integer`. + + Examples: + + >>> integer2bytes(19,4) + '\x00\x00\x00\x13' + """ + if width < 0: + raise ValueError("width must be non-negative") + number = int(number) + if number < 0: + number += 1 << (width * 8) + acc = [b"\x00"] * width + i = width - 1 + while number > 0: + acc[i] = int2byte(number & 255) + number >>= 8 + i -= 1 + return b"".join(acc) + + +def bits2integer(data, signed=False): + r""" + Converts a bit-string into an integer. Set sign to interpret the number as a 2-s complement signed integer. This is reverse to `integer2bits`. + + Examples: + + >>> bits2integer(b"\x01\x00\x00\x01\x01") + 19 + """ + number = 0 + for b in iterateints(data): + number = (number << 1) | b + + if signed and byte2int(data[0:1]): + bias = 1 << len(data) + return number - bias + else: + return number + + +def bytes2integer(data, signed=False): + r""" + Converts a byte-string into an integer. This is reverse to `integer2bytes`. + + Examples: + + >>> bytes2integer(b'\x00\x00\x00\x13') + 19 + """ + number = 0 + for b in iterateints(data): + number = (number << 8) | b + + if signed and byte2int(bytes2bits(data[0:1])[0:1]): + bias = 1 << len(data)*8 + return number - bias + else: + return number + + +BYTES2BITS_CACHE = {i:integer2bits(i,8) for i in range(256)} +def bytes2bits(data): + r""" + Converts between bit and byte representations in b-strings. + + Example: + + >>> bytes2bits(b'ab') + b"\x00\x01\x01\x00\x00\x00\x00\x01\x00\x01\x01\x00\x00\x00\x01\x00" + """ + return b"".join(BYTES2BITS_CACHE[b] for b in iterateints(data)) + + +BITS2BYTES_CACHE = {bytes2bits(int2byte(i)):int2byte(i) for i in range(256)} +def bits2bytes(data): + r""" + Converts between bit and byte representations in b-strings. + + Example: + + >>> bits2bytes(b"\x00\x01\x01\x00\x00\x00\x00\x01\x00\x01\x01\x00\x00\x00\x01\x00") + b'ab' + """ + if len(data) & 7: + raise ValueError("data length must be a multiple of 8") + return b"".join(BITS2BYTES_CACHE[data[i:i+8]] for i in range(0,len(data),8)) + + +def swapbytes(data): + r""" + Performs an endianness swap on byte-string. + + Example: + + >>> swapbytes(b'abcd') + b'dcba' + """ + return data[::-1] + + +def swapbytesinbits(data): + r""" + Performs an byte-swap within a bit-string. Its length must be multiple of 8. + + Example: + + >>> swapbytesinbits(b'0000000011111111') + b'1111111100000000' + """ + if len(data) & 7: + raise ValueError("data length must be multiple of 8") + return b"".join(data[i:i+8] for i in reversed(range(0,len(data),8))) + + +SWAPBITSINBYTES_CACHE = {i:bits2bytes(bytes2bits(int2byte(i))[::-1]) for i in range(256)} +def swapbitsinbytes(data): + r""" + Performs a bit-reversal within a byte-string. + + Example: + + >>> swapbits(b'\xf0') + b'\x0f' + """ + return b"".join(SWAPBITSINBYTES_CACHE[b] for b in iterateints(data)) + + +def hexlify(data): + """Returns binascii.hexlify(data).""" + return binascii.hexlify(data) + + +def unhexlify(data): + """Returns binascii.unhexlify(data).""" + return binascii.unhexlify(data) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/bitstream.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/bitstream.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/bitstream.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/bitstream.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,147 @@ +from io import BlockingIOError +from time import sleep +from sys import maxsize + + +class RestreamedBytesIO(object): + + def __init__(self, substream, decoder, decoderunit, encoder, encoderunit): + self.substream = substream + self.encoder = encoder + self.encoderunit = encoderunit + self.decoder = decoder + self.decoderunit = decoderunit + self.rbuffer = b"" + self.wbuffer = b"" + self.sincereadwritten = 0 + + def read(self, count=None): + if count is None: + while True: + data = self.substream.read(self.decoderunit) + if data is None or len(data) == 0: + break + self.rbuffer += self.decoder(data) + data, self.rbuffer = self.rbuffer, b'' + self.sincereadwritten += len(data) + return data + + else: + if count < 0: + raise ValueError("count cannot be negative") + while len(self.rbuffer) < count: + data = self.substream.read(self.decoderunit) + if data is None or len(data) == 0: + return b'' + self.rbuffer += self.decoder(data) + data, self.rbuffer = self.rbuffer[:count], self.rbuffer[count:] + self.sincereadwritten += count + return data + + def write(self, data): + self.wbuffer += data + datalen = len(data) + while len(self.wbuffer) >= self.encoderunit: + data, self.wbuffer = self.wbuffer[:self.encoderunit], self.wbuffer[self.encoderunit:] + self.substream.write(self.encoder(data)) + self.sincereadwritten += datalen + return datalen + + def close(self): + if len(self.rbuffer): + raise ValueError("closing stream but %d unread bytes remain, %d is decoded unit" % (len(self.rbuffer), self.decoderunit)) + if len(self.wbuffer): + raise ValueError("closing stream but %d unwritten bytes remain, %d is encoded unit" % (len(self.wbuffer), self.encoderunit)) + + def seek(self, at, whence=0): + if whence == 0 and at == self.sincereadwritten: + pass + else: + raise IOError + + def seekable(self): + return False + + def tell(self): + """WARNING: tell is correct only on read-only and write-only instances.""" + return self.sincereadwritten + + def tellable(self): + return True + + +class RebufferedBytesIO(object): + + def __init__(self, substream, tailcutoff=None): + self.substream = substream + self.offset = 0 + self.rwbuffer = b"" + self.moved = 0 + self.tailcutoff = tailcutoff + + def read(self, count=None): + if count is None: + raise ValueError("count must be integer, reading until EOF not supported") + startsat = self.offset + endsat = startsat + count + if startsat < self.moved: + raise IOError("could not read because tail was cut off") + while self.moved + len(self.rwbuffer) < endsat: + try: + newdata = self.substream.read(128*1024) + except BlockingIOError: + newdata = None + if not newdata: + sleep(0) + continue + self.rwbuffer += newdata + data = self.rwbuffer[startsat-self.moved:endsat-self.moved] + self.offset += count + if self.tailcutoff is not None and self.moved < self.offset - self.tailcutoff: + removed = self.offset - self.tailcutoff - self.moved + self.moved += removed + self.rwbuffer = self.rwbuffer[removed:] + if len(data) < count: + raise IOError("could not read enough bytes, something went wrong") + return data + + def write(self, data): + startsat = self.offset + endsat = startsat + len(data) + while self.moved + len(self.rwbuffer) < startsat: + newdata = self.substream.read(128*1024) + self.rwbuffer += newdata + if not newdata: + sleep(0) + self.rwbuffer = self.rwbuffer[:startsat-self.moved] + data + self.rwbuffer[endsat-self.moved:] + self.offset = endsat + if self.tailcutoff is not None and self.moved < self.offset - self.tailcutoff: + removed = self.offset - self.tailcutoff - self.moved + self.moved += removed + self.rwbuffer = self.rwbuffer[removed:] + return len(data) + + def seek(self, at, whence=0): + if whence == 0: + self.offset = at + return self.offset + elif whence == 1: + self.offset += at + return self.offset + else: + raise ValueError("this class seeks only with whence: 0 and 1 (excluded 2)") + + def seekable(self): + return True + + def tell(self): + return self.offset + + def tellable(self): + return True + + def cachedfrom(self): + return self.moved + + def cachedto(self): + return self.moved + len(self.rwbuffer) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/containers.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/containers.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/containers.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/containers.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,378 @@ +from checkbox_support.vendor.construct.lib.py3compat import * +import re + + +globalPrintFullStrings = False +globalPrintFalseFlags = False +globalPrintPrivateEntries = False + + +def setGlobalPrintFullStrings(enabled=False): + r""" + When enabled, Container __str__ produces full content of bytes and unicode strings, otherwise and by default, it produces truncated output (16 bytes and 32 characters). + + :param enabled: bool + """ + global globalPrintFullStrings + globalPrintFullStrings = enabled + + +def setGlobalPrintFalseFlags(enabled=False): + r""" + When enabled, Container __str__ that was produced by FlagsEnum parsing prints all values, otherwise and by default, it prints only the values that are True. + + :param enabled: bool + """ + global globalPrintFalseFlags + globalPrintFalseFlags = enabled + + +def setGlobalPrintPrivateEntries(enabled=False): + r""" + When enabled, Container __str__ shows keys like _ _index _etc, otherwise and by default, it hides those keys. __repr__ never shows private entries. + + :param enabled: bool + """ + global globalPrintPrivateEntries + globalPrintPrivateEntries = enabled + + +def recursion_lock(retval="", lock_name="__recursion_lock__"): + """Used internally.""" + def decorator(func): + def wrapper(self, *args, **kw): + if getattr(self, lock_name, False): + return retval + setattr(self, lock_name, True) + try: + return func(self, *args, **kw) + finally: + delattr(self, lock_name) + + wrapper.__name__ = func.__name__ + return wrapper + + return decorator + + +class Container(dict): + r""" + Generic ordered dictionary that allows both key and attribute access, and preserves key order by insertion. Adding keys is preferred using \*\*entrieskw (requires Python 3.6). Equality does NOT check item order. Also provides regex searching. + + Example:: + + # empty dict + >>> Container() + # list of pairs, not recommended + >>> Container([ ("name","anonymous"), ("age",21) ]) + # This syntax requires Python 3.6 + >>> Container(name="anonymous", age=21) + # This syntax is for internal use only + >>> Container(name="anonymous")(age=21) + # copies another dict + >>> Container(dict2) + >>> Container(container2) + + :: + + >>> print(repr(obj)) + Container(text='utf8 decoded string...')(value=123) + >>> print(obj) + Container + text = u'utf8 decoded string...' (total 22) + value = 123 + """ + __slots__ = ["__keys_order__", "__recursion_lock__"] + + def __getattr__(self, name): + try: + if name in self.__slots__: + try: + return object.__getattribute__(self, name) + except AttributeError as e: + if name == "__keys_order__": + r = [] + object.__setattr__(self, "__keys_order__", r) + return r + else: + raise e + else: + return self[name] + except KeyError: + raise AttributeError(name) + + def __setattr__(self, name, value): + try: + if name in self.__slots__: + return object.__setattr__(self, name, value) + else: + self[name] = value + except KeyError: + raise AttributeError(name) + + def __delattr__(self, name): + try: + if name in self.__slots__: + return object.__delattr__(self, name) + else: + del self[name] + except KeyError: + raise AttributeError(name) + + def __setitem__(self, key, value): + if key not in self: + self.__keys_order__.append(key) + dict.__setitem__(self, key, value) + + def __delitem__(self, key): + """Removes an item from the Container in linear time O(n).""" + if key in self: + self.__keys_order__.remove(key) + dict.__delitem__(self, key) + + def __init__(self, *args, **entrieskw): + self.__keys_order__ = [] + for arg in args: + if isinstance(arg, dict): + for k,v in arg.items(): + self[k] = v + else: + for k,v in arg: + self[k] = v + for k,v in entrieskw.items(): + self[k] = v + + def __call__(self, **entrieskw): + """Chains adding new entries to the same container. See ctor.""" + for k,v in entrieskw.items(): + self[k] = v + return self + + def keys(self): + return iter(self.__keys_order__) + + def values(self): + return (self[k] for k in self.__keys_order__) + + def items(self): + return ((k, self[k]) for k in self.__keys_order__) + + __iter__ = keys + + def clear(self): + """Removes all items.""" + dict.clear(self) + self.__keys_order__ = [] + + def pop(self, key): + """Removes and returns the value for a given key, raises KeyError if not found.""" + val = dict.pop(self, key) + self.__keys_order__.remove(key) + return val + + def popitem(self): + """Removes and returns the last key and value from order.""" + k = self.__keys_order__.pop() + v = dict.pop(self, k) + return k, v + + def update(self, seqordict): + """Appends items from another dict/Container or list-of-tuples.""" + if isinstance(seqordict, dict): + seqordict = seqordict.items() + for k,v in seqordict: + self[k] = v + + def __getstate__(self): + return self.__keys_order__ + + def __setstate__(self, state): + self.__keys_order__ = state + + def copy(self): + return Container(self) + + __update__ = update + + __copy__ = copy + + def __dir__(self): + """For auto completion of attributes based on container values.""" + return list(self.keys()) + list(self.__class__.__dict__) + dir(super(Container, self)) + + def __eq__(self, other): + if self is other: + return True + if not isinstance(other, dict): + return False + def isequal(v1, v2): + if v1.__class__.__name__ == "ndarray" or v2.__class__.__name__ == "ndarray": + import numpy + return numpy.array_equal(v1, v2) + return v1 == v2 + for k,v in self.items(): + if isinstance(k, unicodestringtype) and k.startswith(u"_"): + continue + if isinstance(k, bytestringtype) and k.startswith(b"_"): + continue + if k not in other or not isequal(v, other[k]): + return False + for k,v in other.items(): + if isinstance(k, unicodestringtype) and k.startswith(u"_"): + continue + if isinstance(k, bytestringtype) and k.startswith(b"_"): + continue + if k not in self or not isequal(v, self[k]): + return False + return True + + def __ne__(self, other): + return not self == other + + @recursion_lock() + def __repr__(self): + parts = [] + for k,v in self.items(): + if isinstance(k, str) and k.startswith("_"): + continue + if isinstance(v, stringtypes): + parts.append(str(k) + "=" + reprstring(v)) + else: + parts.append(str(k) + "=" + repr(v)) + return "Container(%s)" % ", ".join(parts) + + @recursion_lock() + def __str__(self): + indentation = "\n " + text = ["Container: "] + isflags = getattr(self, "_flagsenum", False) + for k,v in self.items(): + if isinstance(k, str) and k.startswith("_") and not globalPrintPrivateEntries: + continue + if isflags and not v and not globalPrintFalseFlags: + continue + text.extend([indentation, str(k), " = "]) + if v.__class__.__name__ == "EnumInteger": + text.append("(enum) (unknown) %s" % (v, )) + elif v.__class__.__name__ == "EnumIntegerString": + text.append("(enum) %s %s" % (v, v.intvalue, )) + elif v.__class__.__name__ in ["HexDisplayedBytes", "HexDumpDisplayedBytes"]: + text.append(indentation.join(str(v).split("\n"))) + elif isinstance(v, bytestringtype): + printingcap = 16 + if len(v) <= printingcap or globalPrintFullStrings: + text.append("%s (total %d)" % (reprstring(v), len(v))) + else: + text.append("%s... (truncated, total %d)" % (reprstring(v[:printingcap]), len(v))) + elif isinstance(v, unicodestringtype): + printingcap = 32 + if len(v) <= printingcap or globalPrintFullStrings: + text.append("%s (total %d)" % (reprstring(v), len(v))) + else: + text.append("%s... (truncated, total %d)" % (reprstring(v[:printingcap]), len(v))) + else: + text.append(indentation.join(str(v).split("\n"))) + return "".join(text) + + def _search(self, compiled_pattern, search_all): + items = [] + for key in self.keys(): + try: + if isinstance(self[key], (Container,ListContainer)): + ret = self[key]._search(compiled_pattern, search_all) + if ret is not None: + if search_all: + items.extend(ret) + else: + return ret + elif compiled_pattern.match(key): + if search_all: + items.append(self[key]) + else: + return self[key] + except: + pass + if search_all: + return items + else: + return None + + def search(self, pattern): + """ + Searches a container (non-recursively) using regex. + """ + compiled_pattern = re.compile(pattern) + return self._search(compiled_pattern, False) + + def search_all(self, pattern): + """ + Searches a container (recursively) using regex. + """ + compiled_pattern = re.compile(pattern) + return self._search(compiled_pattern, True) + + +class ListContainer(list): + r""" + Generic container like list. Provides pretty-printing. Also provides regex searching. + + Example:: + + >>> ListContainer() + >>> ListContainer([1, 2, 3]) + + :: + + >>> print(repr(obj)) + [1, 2, 3] + >>> print(obj) + ListContainer + 1 + 2 + 3 + """ + + @recursion_lock() + def __repr__(self): + return "ListContainer(%s)" % (list.__repr__(self), ) + + @recursion_lock() + def __str__(self): + indentation = "\n " + text = ["ListContainer: "] + for k in self: + text.append(indentation) + lines = str(k).split("\n") + text.append(indentation.join(lines)) + return "".join(text) + + def _search(self, compiled_pattern, search_all): + items = [] + for item in self: + try: + ret = item._search(compiled_pattern, search_all) + except: + continue + if ret is not None: + if search_all: + items.extend(ret) + else: + return ret + if search_all: + return items + else: + return None + + def search(self, pattern): + """ + Searches a container (non-recursively) using regex. + """ + compiled_pattern = re.compile(pattern) + return self._search(compiled_pattern, False) + + def search_all(self, pattern): + """ + Searches a container (recursively) using regex. + """ + compiled_pattern = re.compile(pattern) + return self._search(compiled_pattern, True) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/hex.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/hex.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/hex.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/hex.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,94 @@ +from checkbox_support.vendor.construct.lib.py3compat import * +import binascii + + +class HexDisplayedInteger(integertypes[0]): + """Used internally.""" + def __str__(self): + return "0x" + format(self, self.fmtstr).upper() + + @staticmethod + def new(intvalue, fmtstr): + obj = HexDisplayedInteger(intvalue) + obj.fmtstr = fmtstr + return obj + +class HexDisplayedBytes(bytestringtype): + """Used internally.""" + def __str__(self): + if not hasattr(self, "render"): + self.render = "unhexlify(%s)" % (trimstring(binascii.hexlify(self)), ) + return self.render + +class HexDisplayedDict(dict): + """Used internally.""" + def __str__(self): + if not hasattr(self, "render"): + self.render = "unhexlify(%s)" % (trimstring(binascii.hexlify(self["data"])), ) + return self.render + +class HexDumpDisplayedBytes(bytestringtype): + """Used internally.""" + def __str__(self): + if not hasattr(self, "render"): + self.render = hexdump(self, 16) + return self.render + +class HexDumpDisplayedDict(dict): + """Used internally.""" + def __str__(self): + if not hasattr(self, "render"): + self.render = hexdump(self["data"], 16) + return self.render + + +# Map an integer in the inclusive range 0-255 to its string byte representation +PRINTABLE = [bytes2str(int2byte(i)) if 32 <= i < 128 else '.' for i in range(256)] +HEXPRINT = [format(i, '02X') for i in range(256)] + + +def hexdump(data, linesize): + r""" + Turns bytes into a unicode string of the format: + + :: + + >>>print(hexdump(b'0' * 100, 16)) + hexundump(\"\"\" + 0000 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 0000000000000000 + 0010 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 0000000000000000 + 0020 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 0000000000000000 + 0030 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 0000000000000000 + 0040 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 0000000000000000 + 0050 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 0000000000000000 + 0060 30 30 30 30 0000 + \"\"\") + """ + if len(data) < 16**4: + fmt = "%%04X %%-%ds %%s" % (3*linesize-1,) + elif len(data) < 16**8: + fmt = "%%08X %%-%ds %%s" % (3*linesize-1,) + else: + raise ValueError("hexdump cannot process more than 16**8 or 4294967296 bytes") + prettylines = [] + prettylines.append('hexundump("""') + for i in range(0, len(data), linesize): + line = data[i:i+linesize] + hextext = " ".join(HEXPRINT[b] for b in iterateints(line)) + rawtext = "".join(PRINTABLE[b] for b in iterateints(line)) + prettylines.append(fmt % (i, str(hextext), str(rawtext))) + prettylines.append('""")') + prettylines.append("") + return "\n".join(prettylines) + + +def hexundump(data, linesize): + r""" + Reverse of `hexdump`. + """ + raw = [] + for line in data.split("\n")[1:-2]: + line = line[line.find(" "):].lstrip() + bytes = [int2byte(int(s,16)) for s in line[:3*linesize].split()] + raw.extend(bytes) + return b"".join(raw) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/__init__.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/__init__.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/__init__.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,62 @@ +from checkbox_support.vendor.construct.lib.containers import * +from checkbox_support.vendor.construct.lib.binary import * +from checkbox_support.vendor.construct.lib.bitstream import * +from checkbox_support.vendor.construct.lib.hex import * +from checkbox_support.vendor.construct.lib.py3compat import * + +__all__ = [ + 'bits2bytes', + 'bits2integer', + 'byte2int', + 'bytes', + 'bytes2bits', + 'bytes2integer', + 'bytes2integers', + 'bytes2str', + 'bytestringtype', + 'Container', + 'globalPrintFalseFlags', + 'globalPrintFullStrings', + 'HexDisplayedBytes', + 'HexDisplayedDict', + 'HexDisplayedInteger', + 'hexdump', + 'HexDumpDisplayedBytes', + 'HexDumpDisplayedDict', + 'hexlify', + 'hexundump', + 'int2byte', + 'integer2bits', + 'integer2bytes', + 'integers2bytes', + 'integertypes', + 'iteratebytes', + 'iterateints', + 'ListContainer', + 'PY', + 'PY2', + 'PY3', + 'PYPY', + 'RebufferedBytesIO', + 'reprstring', + 'RestreamedBytesIO', + 'setGlobalPrintFalseFlags', + 'setGlobalPrintFullStrings', + 'setGlobalPrintPrivateEntries', + 'str2bytes', + 'str2unicode', + 'stringtypes', + 'supportshalffloats', + 'supportsintenum', + 'supportsintflag', + 'supportsksyexport', + 'supportskwordered', + 'supportsnumpy', + 'swapbitsinbytes', + 'swapbytes', + 'swapbytesinbits', + 'trimstring', + 'unhexlify', + 'unicode2str', + 'unicodestringtype', +] diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/py3compat.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/py3compat.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/py3compat.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/lib/py3compat.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,181 @@ +import sys + +PY = sys.version_info[:2] +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PYPY = '__pypy__' in sys.builtin_module_names + +try: + import numpy + supportsnumpy = True +except ImportError: + supportsnumpy = False +try: + import ruamel.yaml + assert PY3 + supportsksyexport = True +except (ImportError, AssertionError): + supportsksyexport = False +try: + from enum import IntEnum + supportsintenum = True +except ImportError: + supportsintenum = False +try: + from enum import IntFlag + supportsintflag = True +except ImportError: + supportsintflag = False + +supportskwordered = PY >= (3,6) or PYPY +supportshalffloats = PY >= (3,6) + + +if PY3: + #: PY2: str unicode + #: PY3: bytes str + stringtypes = (bytes, str, ) + #: PY2: int long + #: PY3: int + integertypes = (int, ) + #: PY2: unicode + #: PY3: str + unicodestringtype = str + #: PY2: str + #: PY3: bytes + bytestringtype = bytes + + INT2BYTE_CACHE = {i:bytes((i,)) for i in range(256)} + def int2byte(character): + """Converts (0 through 255) integer into b'...' character.""" + return INT2BYTE_CACHE[character] + + def byte2int(character): + """Converts b'...' character into (0 through 255) integer.""" + return ord(character) + + def str2bytes(string): + """Converts '...' string into b'...' string. On PY2 they are equivalent. On PY3 its utf8 encoded.""" + return string.encode("utf8") + + def bytes2str(string): + """Converts b'...' string into '...' string. On PY2 they are equivalent. On PY3 its utf8 decoded.""" + return string.decode("utf8") + + def str2unicode(string): + """Converts '...' string into u'...' string. On PY2 its utf8 encoded. On PY3 they are equivalent.""" + return string + + def unicode2str(string): + """Converts u'...' string into '...' string. On PY2 its utf8 decoded. On PY3 they are equivalent.""" + return string + + ITERATEBYTES_CACHE = {i:bytes((i,)) for i in range(256)} + def iteratebytes(data): + """Iterates though b'...' string yielding b'...' characters.""" + return (ITERATEBYTES_CACHE[i] for i in data) + + def iterateints(data): + """Iterates though b'...' string yielding (0 through 255) integers.""" + return data + + def reprstring(data): + """Ensures there is b- u- prefix before the string.""" + if isinstance(data, bytes): + return repr(data) + if isinstance(data, str): + return 'u' + repr(data) + + def trimstring(data): + """Trims b- u- prefix""" + if isinstance(data, bytes): + return repr(data)[1:] + if isinstance(data, str): + return repr(data) + + import builtins + bytes = builtins.bytes + + def integers2bytes(ints): + """Converts integer generator into bytes.""" + return bytes(ints) + + def bytes2integers(data): + """Converts bytes into bytes/bytearray, so indexing/iterating yields integers.""" + return data + + +else: + #: PY2: str unicode + #: PY3: bytes str + stringtypes = (str, unicode, ) + #: PY2: int long + #: PY3: int + integertypes = (long, int, ) + #: PY2: unicode + #: PY3: str + unicodestringtype = unicode + #: PY2: str + #: PY3: bytes + bytestringtype = str + + def int2byte(character): + """Converts (0 through 255) integer into b'...' character.""" + return chr(character) + + def byte2int(character): + """Converts b'...' character into (0 through 255) integer.""" + return ord(character) + + def str2bytes(string): + """Converts '...' string into b'...' string. On PY2 they are equivalent. On PY3 its utf8 encoded.""" + return string + + def bytes2str(string): + """Converts b'...' string into '...' string. On PY2 they are equivalent. On PY3 its utf8 decoded.""" + return string + + def str2unicode(string): + """Converts '...' string into u'...' string. On PY2 its utf8 encoded. On PY3 they are equivalent.""" + return string.encode("utf8") + + def unicode2str(string): + """Converts u'...' string into '...' string. On PY2 its utf8 decoded. On PY3 they are equivalent.""" + return string.decode("utf8") + + def iteratebytes(data): + """Iterates though b'...' string yielding b'...' characters.""" + return data + + def iterateints(data): + """Iterates though b'...' string yielding (0 through 255) integers.""" + return bytearray(data) + + def reprstring(data): + """Ensures there is b- u- prefix before the string.""" + if isinstance(data, str): + return 'b' + repr(data) + if isinstance(data, unicode): + return repr(data) + + def trimstring(data): + """Trims b- u- prefix""" + if isinstance(data, str): + return repr(data) + if isinstance(data, unicode): + return repr(data)[1:] + + def bytes(countorseq=0): + """Backports bytes() from PY3.""" + if isinstance(countorseq, integertypes): + return b"\x00" * countorseq + else: + return b"".join(chr(x) for x in countorseq) + + def integers2bytes(ints): + """Converts integer generator into bytes.""" + return bytes(bytearray(ints)) + + def bytes2integers(data): + """Converts bytes into bytes/bytearray, so indexing/iterating yields integers.""" + return bytearray(data) diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/LICENSE checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/LICENSE --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/LICENSE 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,22 @@ +Copyright (C) 2006-2020 + Arkadiusz Bulski (arek.bulski@gmail.com) + Tomer Filiba (tomerfiliba@gmail.com) + Corbin Simpson (MostAwesomeDude@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/version.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/version.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/version.py 1970-01-01 00:00:00.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/checkbox_support/vendor/construct/version.py 2021-07-12 15:29:05.000000000 +0000 @@ -0,0 +1,3 @@ +version = (2,10,53) +version_string = "2.10.53" +release_date = "2020.01.19" diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/debian/changelog checkbox-support-0.51.0~ppa~ubuntu21.10.1/debian/changelog --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/debian/changelog 2021-05-27 06:47:38.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/debian/changelog 2021-07-12 15:29:29.000000000 +0000 @@ -1,10 +1,10 @@ -checkbox-support (0.50.0~ppa~ubuntu21.10.1) impish; urgency=low +checkbox-support (0.51.0~ppa~ubuntu21.10.1) impish; urgency=low * Auto build. - -- Sylvain Pineau Thu, 27 May 2021 06:47:38 +0000 + -- Canonical Certification Team Mon, 12 Jul 2021 15:29:29 +0000 -checkbox-support (0.50.0-1) UNRELEASED; urgency=medium +checkbox-support (0.51.0-1) UNRELEASED; urgency=medium [ Pierre Equoy ] * Open for development (remove this message before releasing) @@ -66,8 +66,10 @@ * "new upstream version" * "new upstream version" * "new upstream version" + * "new upstream version" + * "new upstream version" - -- Jenkins Fri, 30 Apr 2021 07:11:14 +0000 + -- Jenkins Mon, 12 Jul 2021 14:58:04 +0000 checkbox-support (0.28) unstable; urgency=medium diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/debian/control checkbox-support-0.51.0~ppa~ubuntu21.10.1/debian/control --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/debian/control 2021-05-27 06:47:38.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/debian/control 2021-07-12 15:29:29.000000000 +0000 @@ -9,6 +9,7 @@ debhelper (>= 9), dh-python, python3-all, + python3-bluez, python3-dbus, python3-distro, python3-gi, @@ -29,6 +30,7 @@ Package: python3-checkbox-support Architecture: all Depends: gir1.2-gudev-1.0, + python3-bluez, python3-dbus, python3-distro, python3-gi, diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/debian/git-build-recipe.manifest checkbox-support-0.51.0~ppa~ubuntu21.10.1/debian/git-build-recipe.manifest --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/debian/git-build-recipe.manifest 2021-05-27 06:47:38.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/debian/git-build-recipe.manifest 2021-07-12 15:29:29.000000000 +0000 @@ -1,3 +1,3 @@ -# git-build-recipe format 0.4 deb-version 0.50.0~ppa -lp:checkbox-support git-commit:6ef705cb734ad9658820a487c04c6f3452016958 -nest-part packaging lp:~checkbox-dev/checkbox-support/+git/packaging debian debian git-commit:4dd0e58ffe08b36c371b6b3bd20dc6e3dbe87ac7 +# git-build-recipe format 0.4 deb-version 0.51.0~ppa +lp:checkbox-support git-commit:265b2d5bdd59f0ea61d9892f313fea526fe10005 +nest-part packaging lp:~checkbox-dev/checkbox-support/+git/packaging debian debian git-commit:ea0ca467bae5bbd24d084b9da773563986bd6627 diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/debian/.git-dpm checkbox-support-0.51.0~ppa~ubuntu21.10.1/debian/.git-dpm --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/debian/.git-dpm 2021-05-27 06:47:38.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/debian/.git-dpm 2021-07-12 15:29:29.000000000 +0000 @@ -1,8 +1,8 @@ # see git-dpm(1) from git-dpm package -6cc80734ef3768ccf1c0646140606319ff8e5c56 -6cc80734ef3768ccf1c0646140606319ff8e5c56 -6cc80734ef3768ccf1c0646140606319ff8e5c56 -6cc80734ef3768ccf1c0646140606319ff8e5c56 -checkbox-support_0.50.0.orig.tar.gz -5c141700a66678cea7b89529431d185a9ce000b2 -1206175 +4c7a308476533092dc8e21bbb52213790feb89c4 +4c7a308476533092dc8e21bbb52213790feb89c4 +4c7a308476533092dc8e21bbb52213790feb89c4 +4c7a308476533092dc8e21bbb52213790feb89c4 +checkbox-support_0.51.0.orig.tar.gz +4ae67ff97826bb951e82b176ee52aa1c08a977a3 +1296187 diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/requirements/deb-core.txt checkbox-support-0.51.0~ppa~ubuntu21.10.1/requirements/deb-core.txt --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/requirements/deb-core.txt 2021-05-27 06:47:04.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/requirements/deb-core.txt 2021-07-12 15:29:05.000000000 +0000 @@ -2,3 +2,4 @@ python3-requests python3-requests-unixsocket python3-distro +python3-bluez diff -Nru checkbox-support-0.50.0~ppa~ubuntu21.10.1/setup.py checkbox-support-0.51.0~ppa~ubuntu21.10.1/setup.py --- checkbox-support-0.50.0~ppa~ubuntu21.10.1/setup.py 2021-05-27 06:47:04.000000000 +0000 +++ checkbox-support-0.51.0~ppa~ubuntu21.10.1/setup.py 2021-07-12 15:29:05.000000000 +0000 @@ -38,7 +38,7 @@ setup( name="checkbox-support", - version="0.50.0", + version="0.51.0", url="https://launchpad.net/checkbox/", packages=find_packages(), test_suite='checkbox_support.tests.test_suite',